Organize test suite: add README, move loose tests to proper directories

- Add tests/README.md documenting test structure and usage
- Move issue_*_test.py files to tests/regression/ (9 files)
- Move loose test_*.py files to tests/unit/ (18 files)
- tests/ root now contains only pytest infrastructure

Addresses #166

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John McCardle 2026-01-21 21:34:22 -05:00
commit 165db91b8d
28 changed files with 174 additions and 0 deletions

View file

@ -0,0 +1,226 @@
#!/usr/bin/env python3
"""Test batch of API changes for issues #177, #179, #181, #182, #184, #185, #188, #189, #190"""
import sys
import mcrfpy
def test_issue_177_gridpoint_grid_pos():
"""Test GridPoint.grid_pos property returns tuple"""
print("Testing #177: GridPoint.grid_pos property...")
texture = mcrfpy.Texture("assets/kenney_ice.png", 16, 16)
grid = mcrfpy.Grid(grid_size=(10, 10), texture=texture, pos=(0, 0), size=(160, 160))
# Get a grid point
point = grid.at(3, 5)
# Test grid_pos property exists and returns tuple
grid_pos = point.grid_pos
assert isinstance(grid_pos, tuple), f"grid_pos should be tuple, got {type(grid_pos)}"
assert len(grid_pos) == 2, f"grid_pos should have 2 elements, got {len(grid_pos)}"
assert grid_pos == (3, 5), f"grid_pos should be (3, 5), got {grid_pos}"
# Test another position
point2 = grid.at(7, 2)
assert point2.grid_pos == (7, 2), f"grid_pos should be (7, 2), got {point2.grid_pos}"
print(" PASS: GridPoint.grid_pos works correctly")
return True
def test_issue_179_181_grid_vectors():
"""Test Grid properties return Vectors instead of tuples"""
print("Testing #179, #181: Grid Vector returns and grid_w/grid_h rename...")
texture = mcrfpy.Texture("assets/kenney_ice.png", 16, 16)
grid = mcrfpy.Grid(grid_size=(15, 20), texture=texture, pos=(50, 100), size=(240, 320))
# Test center returns Vector
center = grid.center
assert hasattr(center, 'x') and hasattr(center, 'y'), f"center should be Vector, got {type(center)}"
# Test grid_size returns Vector
grid_size = grid.grid_size
assert hasattr(grid_size, 'x') and hasattr(grid_size, 'y'), f"grid_size should be Vector, got {type(grid_size)}"
assert grid_size.x == 15 and grid_size.y == 20, f"grid_size should be (15, 20), got ({grid_size.x}, {grid_size.y})"
# Test pos returns Vector
pos = grid.pos
assert hasattr(pos, 'x') and hasattr(pos, 'y'), f"pos should be Vector, got {type(pos)}"
print(" PASS: Grid properties return Vectors correctly")
return True
def test_issue_182_caption_size():
"""Test Caption read-only size, w, h properties"""
print("Testing #182: Caption read-only size/w/h properties...")
font = mcrfpy.Font("assets/JetbrainsMono.ttf")
caption = mcrfpy.Caption(text="Test Caption", pos=(100, 100), font=font)
# Test size property
size = caption.size
assert hasattr(size, 'x') and hasattr(size, 'y'), f"size should be Vector, got {type(size)}"
assert size.x > 0, f"width should be positive, got {size.x}"
assert size.y > 0, f"height should be positive, got {size.y}"
# Test w property
w = caption.w
assert isinstance(w, float), f"w should be float, got {type(w)}"
assert w > 0, f"w should be positive, got {w}"
# Test h property
h = caption.h
assert isinstance(h, float), f"h should be float, got {type(h)}"
assert h > 0, f"h should be positive, got {h}"
# Verify w and h match size
assert abs(w - size.x) < 0.001, f"w ({w}) should match size.x ({size.x})"
assert abs(h - size.y) < 0.001, f"h ({h}) should match size.y ({size.y})"
# Verify read-only
try:
caption.size = mcrfpy.Vector(100, 100)
print(" FAIL: size should be read-only")
return False
except AttributeError:
pass # Expected
try:
caption.w = 100
print(" FAIL: w should be read-only")
return False
except AttributeError:
pass # Expected
try:
caption.h = 100
print(" FAIL: h should be read-only")
return False
except AttributeError:
pass # Expected
print(" PASS: Caption size/w/h properties work correctly")
return True
def test_issue_184_189_module_namespace():
"""Test window singleton and hidden internal types"""
print("Testing #184, #189: window singleton + hide classes...")
# Test window singleton exists
assert hasattr(mcrfpy, 'window'), "mcrfpy.window should exist"
window = mcrfpy.window
assert window is not None, "window should not be None"
# Verify window properties
assert hasattr(window, 'resolution'), "window should have resolution property"
# Test that internal types are hidden from module namespace
assert not hasattr(mcrfpy, 'UICollectionIter'), "UICollectionIter should be hidden from module namespace"
assert not hasattr(mcrfpy, 'UIEntityCollectionIter'), "UIEntityCollectionIter should be hidden from module namespace"
# But iteration should still work - test UICollection iteration
scene = mcrfpy.Scene("test_scene")
ui = scene.children
ui.append(mcrfpy.Frame(pos=(0,0), size=(50,50)))
ui.append(mcrfpy.Caption(text="hi", pos=(0,0)))
count = 0
for item in ui:
count += 1
assert count == 2, f"Should iterate over 2 items, got {count}"
print(" PASS: window singleton and hidden types work correctly")
return True
def test_issue_185_188_bounds_vectors():
"""Test bounds returns Vector pair, get_bounds() removed"""
print("Testing #185, #188: Remove get_bounds(), bounds as Vector pair...")
frame = mcrfpy.Frame(pos=(50, 100), size=(200, 150))
# Test bounds returns tuple of Vectors
bounds = frame.bounds
assert isinstance(bounds, tuple), f"bounds should be tuple, got {type(bounds)}"
assert len(bounds) == 2, f"bounds should have 2 elements, got {len(bounds)}"
pos, size = bounds
assert hasattr(pos, 'x') and hasattr(pos, 'y'), f"pos should be Vector, got {type(pos)}"
assert hasattr(size, 'x') and hasattr(size, 'y'), f"size should be Vector, got {type(size)}"
assert pos.x == 50 and pos.y == 100, f"pos should be (50, 100), got ({pos.x}, {pos.y})"
assert size.x == 200 and size.y == 150, f"size should be (200, 150), got ({size.x}, {size.y})"
# Test global_bounds also returns Vector pair
global_bounds = frame.global_bounds
assert isinstance(global_bounds, tuple), f"global_bounds should be tuple, got {type(global_bounds)}"
assert len(global_bounds) == 2, f"global_bounds should have 2 elements"
# Test get_bounds() method is removed (#185)
assert not hasattr(frame, 'get_bounds'), "get_bounds() method should be removed"
print(" PASS: bounds returns Vector pairs, get_bounds() removed")
return True
def test_issue_190_layer_documentation():
"""Test that layer types have documentation"""
print("Testing #190: TileLayer/ColorLayer documentation...")
# Verify layer types exist and have docstrings
assert hasattr(mcrfpy, 'TileLayer'), "TileLayer should exist"
assert hasattr(mcrfpy, 'ColorLayer'), "ColorLayer should exist"
# Check that docstrings exist and contain useful info
tile_doc = mcrfpy.TileLayer.__doc__
color_doc = mcrfpy.ColorLayer.__doc__
assert tile_doc is not None and len(tile_doc) > 50, f"TileLayer should have substantial docstring, got: {tile_doc}"
assert color_doc is not None and len(color_doc) > 50, f"ColorLayer should have substantial docstring, got: {color_doc}"
# Check for key documentation elements
assert "layer" in tile_doc.lower() or "tile" in tile_doc.lower(), "TileLayer doc should mention layer or tile"
assert "layer" in color_doc.lower() or "color" in color_doc.lower(), "ColorLayer doc should mention layer or color"
print(" PASS: Layer documentation exists")
return True
def run_all_tests():
"""Run all tests and report results"""
print("=" * 60)
print("API Changes Batch Test - Issues #177, #179, #181, #182, #184, #185, #188, #189, #190")
print("=" * 60)
tests = [
("Issue #177 GridPoint.grid_pos", test_issue_177_gridpoint_grid_pos),
("Issue #179, #181 Grid Vectors", test_issue_179_181_grid_vectors),
("Issue #182 Caption size/w/h", test_issue_182_caption_size),
("Issue #184, #189 Module namespace", test_issue_184_189_module_namespace),
("Issue #185, #188 Bounds Vectors", test_issue_185_188_bounds_vectors),
("Issue #190 Layer documentation", test_issue_190_layer_documentation),
]
passed = 0
failed = 0
for name, test_func in tests:
try:
if test_func():
passed += 1
else:
failed += 1
print(f" FAILED: {name}")
except Exception as e:
failed += 1
print(f" ERROR in {name}: {e}")
print("=" * 60)
print(f"Results: {passed} passed, {failed} failed")
print("=" * 60)
if failed == 0:
print("ALL TESTS PASSED")
sys.exit(0)
else:
print("SOME TESTS FAILED")
sys.exit(1)
# Run tests
run_all_tests()

View file

@ -0,0 +1,14 @@
import mcrfpy
scene = mcrfpy.Scene("test")
scene.activate()
f1 = mcrfpy.Frame((10,10), (100,100), fill_color = (255, 0, 0, 64))
f2 = mcrfpy.Frame((200,10), (100,100), fill_color = (0, 255, 0, 64))
f_child = mcrfpy.Frame((25,25), (50,50), fill_color = (0, 0, 255, 64))
scene.children.append(f1)
scene.children.append(f2)
f1.children.append(f_child)
f_child.parent = f2
print(f1.children)
print(f2.children)

View file

@ -0,0 +1,9 @@
#!/usr/bin/env python3
"""Minimal test to check if module works"""
import sys
import mcrfpy
print("Module loaded successfully")
print(f"mcrfpy has window: {hasattr(mcrfpy, 'window')}")
print(f"mcrfpy.Frame exists: {hasattr(mcrfpy, 'Frame')}")
sys.exit(0)

15
tests/unit/test_append.py Normal file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env python3
import sys
import mcrfpy
print("1 - Creating scene")
scene = mcrfpy.Scene("test")
print("2 - Getting children")
ui = scene.children
print("3 - Creating frame")
frame = mcrfpy.Frame(pos=(0,0), size=(50,50))
print("4 - Appending frame")
ui.append(frame)
print("5 - Length check")
print(f"len: {len(ui)}")
print("DONE")
sys.exit(0)

View file

@ -0,0 +1,150 @@
#!/usr/bin/env python3
"""Test that callbacks return Vector objects instead of separate x, y values."""
import sys
import mcrfpy
# Track test results
results = []
def test_click_callback_signature(pos, button, action):
"""Test on_click callback receives Vector."""
# Check if pos is a Vector
if isinstance(pos, mcrfpy.Vector):
results.append(("on_click pos is Vector", True))
print(f"PASS: on_click receives Vector: {pos}")
else:
results.append(("on_click pos is Vector", False))
print(f"FAIL: on_click receives {type(pos).__name__} instead of Vector: {pos}")
# Verify button and action are strings
if isinstance(button, str) and isinstance(action, str):
results.append(("on_click button/action are strings", True))
print(f"PASS: button={button!r}, action={action!r}")
else:
results.append(("on_click button/action are strings", False))
print(f"FAIL: button={type(button).__name__}, action={type(action).__name__}")
def test_on_enter_callback_signature(pos, button, action):
"""Test on_enter callback receives Vector."""
if isinstance(pos, mcrfpy.Vector):
results.append(("on_enter pos is Vector", True))
print(f"PASS: on_enter receives Vector: {pos}")
else:
results.append(("on_enter pos is Vector", False))
print(f"FAIL: on_enter receives {type(pos).__name__} instead of Vector")
def test_on_exit_callback_signature(pos, button, action):
"""Test on_exit callback receives Vector."""
if isinstance(pos, mcrfpy.Vector):
results.append(("on_exit pos is Vector", True))
print(f"PASS: on_exit receives Vector: {pos}")
else:
results.append(("on_exit pos is Vector", False))
print(f"FAIL: on_exit receives {type(pos).__name__} instead of Vector")
def test_on_move_callback_signature(pos, button, action):
"""Test on_move callback receives Vector."""
if isinstance(pos, mcrfpy.Vector):
results.append(("on_move pos is Vector", True))
print(f"PASS: on_move receives Vector: {pos}")
else:
results.append(("on_move pos is Vector", False))
print(f"FAIL: on_move receives {type(pos).__name__} instead of Vector")
def test_cell_click_callback_signature(cell_pos):
"""Test on_cell_click callback receives Vector."""
if isinstance(cell_pos, mcrfpy.Vector):
results.append(("on_cell_click pos is Vector", True))
print(f"PASS: on_cell_click receives Vector: {cell_pos}")
else:
results.append(("on_cell_click pos is Vector", False))
print(f"FAIL: on_cell_click receives {type(cell_pos).__name__} instead of Vector")
def test_cell_enter_callback_signature(cell_pos):
"""Test on_cell_enter callback receives Vector."""
if isinstance(cell_pos, mcrfpy.Vector):
results.append(("on_cell_enter pos is Vector", True))
print(f"PASS: on_cell_enter receives Vector: {cell_pos}")
else:
results.append(("on_cell_enter pos is Vector", False))
print(f"FAIL: on_cell_enter receives {type(cell_pos).__name__} instead of Vector")
def test_cell_exit_callback_signature(cell_pos):
"""Test on_cell_exit callback receives Vector."""
if isinstance(cell_pos, mcrfpy.Vector):
results.append(("on_cell_exit pos is Vector", True))
print(f"PASS: on_cell_exit receives Vector: {cell_pos}")
else:
results.append(("on_cell_exit pos is Vector", False))
print(f"FAIL: on_cell_exit receives {type(cell_pos).__name__} instead of Vector")
def run_test(runtime):
"""Set up test and simulate interactions."""
print("=" * 50)
print("Testing callback Vector return values")
print("=" * 50)
# Create a test scene
mcrfpy.createScene("test")
ui = mcrfpy.sceneUI("test")
# Create a Frame with callbacks
frame = mcrfpy.Frame(pos=(100, 100), size=(200, 200))
frame.on_click = test_click_callback_signature
frame.on_enter = test_on_enter_callback_signature
frame.on_exit = test_on_exit_callback_signature
frame.on_move = test_on_move_callback_signature
ui.append(frame)
# Create a Grid with cell callbacks
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
grid = mcrfpy.Grid(pos=(350, 100), size=(200, 200), grid_size=(10, 10), texture=texture)
grid.on_cell_click = test_cell_click_callback_signature
grid.on_cell_enter = test_cell_enter_callback_signature
grid.on_cell_exit = test_cell_exit_callback_signature
ui.append(grid)
mcrfpy.setScene("test")
print("\n--- Test Setup Complete ---")
print("To test interactively:")
print(" - Click on the Frame (left side) to test on_click")
print(" - Move mouse over Frame to test on_enter/on_exit/on_move")
print(" - Click on the Grid (right side) to test on_cell_click")
print(" - Move mouse over Grid to test on_cell_enter/on_cell_exit")
print("\nPress Escape to exit.")
# For headless testing, simulate a callback call directly
print("\n--- Simulating callback calls ---")
# Test that the callbacks are set up correctly
test_click_callback_signature(mcrfpy.Vector(150, 150), "left", "start")
test_on_enter_callback_signature(mcrfpy.Vector(100, 100), "enter", "start")
test_on_exit_callback_signature(mcrfpy.Vector(300, 300), "exit", "start")
test_on_move_callback_signature(mcrfpy.Vector(125, 175), "move", "start")
test_cell_click_callback_signature(mcrfpy.Vector(5, 3))
test_cell_enter_callback_signature(mcrfpy.Vector(2, 7))
test_cell_exit_callback_signature(mcrfpy.Vector(8, 1))
# Print summary
print("\n" + "=" * 50)
print("SUMMARY")
print("=" * 50)
passed = sum(1 for _, success in results if success)
failed = sum(1 for _, success in results if not success)
print(f"Passed: {passed}")
print(f"Failed: {failed}")
if failed == 0:
print("\nAll tests PASSED!")
sys.exit(0)
else:
print("\nSome tests FAILED!")
for name, success in results:
if not success:
print(f" FAILED: {name}")
sys.exit(1)
# Run the test
mcrfpy.setTimer("test", run_test, 100)

View file

@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Test Caption size/w/h properties"""
import sys
import mcrfpy
print("Testing Caption size/w/h properties...")
font = mcrfpy.Font("assets/JetbrainsMono.ttf")
caption = mcrfpy.Caption(text="Test Caption", pos=(100, 100), font=font)
print(f"Caption created: {caption}")
# Test size property
print("Testing size property...")
size = caption.size
print(f"size type: {type(size)}")
print(f"size value: {size}")
if not hasattr(size, 'x'):
print(f"FAIL: size should be Vector, got {type(size)}")
sys.exit(1)
print(f"size.x={size.x}, size.y={size.y}")
if size.x <= 0 or size.y <= 0:
print(f"FAIL: size should be positive, got ({size.x}, {size.y})")
sys.exit(1)
# Test w property
print("Testing w property...")
w = caption.w
print(f"w type: {type(w)}, value: {w}")
if not isinstance(w, float):
print(f"FAIL: w should be float, got {type(w)}")
sys.exit(1)
if w <= 0:
print(f"FAIL: w should be positive, got {w}")
sys.exit(1)
# Test h property
print("Testing h property...")
h = caption.h
print(f"h type: {type(h)}, value: {h}")
if not isinstance(h, float):
print(f"FAIL: h should be float, got {type(h)}")
sys.exit(1)
if h <= 0:
print(f"FAIL: h should be positive, got {h}")
sys.exit(1)
# Verify w and h match size
if abs(w - size.x) >= 0.001:
print(f"FAIL: w ({w}) should match size.x ({size.x})")
sys.exit(1)
if abs(h - size.y) >= 0.001:
print(f"FAIL: h ({h}) should match size.y ({size.y})")
sys.exit(1)
# Verify read-only
print("Checking that size/w/h are read-only...")
try:
caption.size = mcrfpy.Vector(100, 100)
print("FAIL: size should be read-only")
sys.exit(1)
except AttributeError:
print(" size is correctly read-only")
try:
caption.w = 100
print("FAIL: w should be read-only")
sys.exit(1)
except AttributeError:
print(" w is correctly read-only")
try:
caption.h = 100
print("FAIL: h should be read-only")
sys.exit(1)
except AttributeError:
print(" h is correctly read-only")
print("PASS: Caption size/w/h properties work correctly!")
sys.exit(0)

View file

@ -0,0 +1,11 @@
#!/usr/bin/env python3
import sys
import mcrfpy
print("1")
scene = mcrfpy.Scene("test")
print("2")
ui = scene.children
print("3")
print(f"children: {ui}")
print("4")
sys.exit(0)

View file

@ -0,0 +1,43 @@
#!/usr/bin/env python3
"""Test Frame bounds"""
import sys
import mcrfpy
print("Testing Frame bounds...")
frame = mcrfpy.Frame(pos=(50, 100), size=(200, 150))
print(f"Frame created: {frame}")
# Test bounds returns tuple of Vectors
bounds = frame.bounds
print(f"bounds type: {type(bounds)}")
print(f"bounds value: {bounds}")
if not isinstance(bounds, tuple):
print(f"FAIL: bounds should be tuple, got {type(bounds)}")
sys.exit(1)
if len(bounds) != 2:
print(f"FAIL: bounds should have 2 elements, got {len(bounds)}")
sys.exit(1)
pos, size = bounds
print(f"pos type: {type(pos)}, value: {pos}")
print(f"size type: {type(size)}, value: {size}")
if not hasattr(pos, 'x'):
print(f"FAIL: pos should be Vector (has no .x), got {type(pos)}")
sys.exit(1)
print(f"pos.x={pos.x}, pos.y={pos.y}")
print(f"size.x={size.x}, size.y={size.y}")
# Test get_bounds() method is removed (#185)
if hasattr(frame, 'get_bounds'):
print("FAIL: get_bounds() method should be removed")
sys.exit(1)
else:
print("PASS: get_bounds() method is removed")
print("PASS: Frame bounds test passed!")
sys.exit(0)

View file

@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""Test Grid features"""
import sys
import mcrfpy
print("Testing Grid features...")
# Create a texture first
print("Loading texture...")
texture = mcrfpy.Texture("assets/kenney_ice.png", 16, 16)
print(f"Texture loaded: {texture}")
# Create grid
print("Creating grid...")
grid = mcrfpy.Grid(grid_size=(15, 20), texture=texture, pos=(50, 100), size=(240, 320))
print(f"Grid created: {grid}")
# Test grid_size returns Vector
print("Testing grid_size...")
grid_size = grid.grid_size
print(f"grid_size type: {type(grid_size)}")
print(f"grid_size value: {grid_size}")
if not hasattr(grid_size, 'x'):
print(f"FAIL: grid_size should be Vector, got {type(grid_size)}")
sys.exit(1)
print(f"grid_size.x={grid_size.x}, grid_size.y={grid_size.y}")
if grid_size.x != 15 or grid_size.y != 20:
print(f"FAIL: grid_size should be (15, 20), got ({grid_size.x}, {grid_size.y})")
sys.exit(1)
# Test center returns Vector
print("Testing center...")
center = grid.center
print(f"center type: {type(center)}")
print(f"center value: {center}")
if not hasattr(center, 'x'):
print(f"FAIL: center should be Vector, got {type(center)}")
sys.exit(1)
print(f"center.x={center.x}, center.y={center.y}")
# Test pos returns Vector
print("Testing pos...")
pos = grid.pos
print(f"pos type: {type(pos)}")
if not hasattr(pos, 'x'):
print(f"FAIL: pos should be Vector, got {type(pos)}")
sys.exit(1)
print(f"pos.x={pos.x}, pos.y={pos.y}")
print("PASS: Grid Vector properties work correctly!")
sys.exit(0)

View file

@ -0,0 +1,15 @@
#!/usr/bin/env python3
import sys
import mcrfpy
print("1 - Loading texture", flush=True)
texture = mcrfpy.Texture("assets/kenney_ice.png", 16, 16)
print("2 - Creating grid", flush=True)
grid = mcrfpy.Grid(grid_size=(10, 10), texture=texture, pos=(0, 0), size=(160, 160))
print("3 - Getting grid point at (3, 5)", flush=True)
point = grid.at(3, 5)
print(f"4 - Point: {point}", flush=True)
print("5 - Getting grid_pos", flush=True)
grid_pos = point.grid_pos
print(f"6 - grid_pos: {grid_pos}", flush=True)
print("PASS", flush=True)
sys.exit(0)

View file

@ -0,0 +1,42 @@
#!/usr/bin/env python3
"""Test GridPoint.grid_pos property"""
import sys
import mcrfpy
print("Testing GridPoint.grid_pos...")
texture = mcrfpy.Texture("assets/kenney_ice.png", 16, 16)
grid = mcrfpy.Grid(grid_size=(10, 10), texture=texture, pos=(0, 0), size=(160, 160))
# Get a grid point
print("Getting grid point at (3, 5)...")
point = grid.at(3, 5)
print(f"Point: {point}")
# Test grid_pos property exists and returns tuple
print("Checking grid_pos property...")
grid_pos = point.grid_pos
print(f"grid_pos type: {type(grid_pos)}")
print(f"grid_pos value: {grid_pos}")
if not isinstance(grid_pos, tuple):
print(f"FAIL: grid_pos should be tuple, got {type(grid_pos)}")
sys.exit(1)
if len(grid_pos) != 2:
print(f"FAIL: grid_pos should have 2 elements, got {len(grid_pos)}")
sys.exit(1)
if grid_pos != (3, 5):
print(f"FAIL: grid_pos should be (3, 5), got {grid_pos}")
sys.exit(1)
# Test another position
print("Getting grid point at (7, 2)...")
point2 = grid.at(7, 2)
if point2.grid_pos != (7, 2):
print(f"FAIL: grid_pos should be (7, 2), got {point2.grid_pos}")
sys.exit(1)
print("PASS: GridPoint.grid_pos works correctly!")
sys.exit(0)

View file

@ -0,0 +1,16 @@
#!/usr/bin/env python3
import sys
import mcrfpy
print("1 - Creating scene", flush=True)
scene = mcrfpy.Scene("test")
print("2 - Getting children", flush=True)
ui = scene.children
print("3 - Creating frame", flush=True)
frame = mcrfpy.Frame(pos=(0,0), size=(50,50))
print("4 - Appending frame", flush=True)
ui.append(frame)
print("5 - Starting iteration", flush=True)
for item in ui:
print(f"Item: {item}", flush=True)
print("6 - Iteration done", flush=True)
sys.exit(0)

View file

@ -0,0 +1,16 @@
#!/usr/bin/env python3
import sys
import mcrfpy
print("1 - Creating scene")
scene = mcrfpy.Scene("test")
print("2 - Getting children")
ui = scene.children
print("3 - Creating frame")
frame = mcrfpy.Frame(pos=(0,0), size=(50,50))
print("4 - Appending frame")
ui.append(frame)
print("5 - Starting iteration")
for item in ui:
print(f"Item: {item}")
print("6 - Iteration done")
sys.exit(0)

View file

@ -0,0 +1,43 @@
#!/usr/bin/env python3
"""Test iteration works with hidden types"""
import sys
import mcrfpy
print("Step 1: Creating scene...")
scene = mcrfpy.Scene("test_scene")
print(f" scene: {scene}")
print("Step 2: Getting children...")
ui = scene.children
print(f" children: {ui}")
print("Step 3: Creating Frame...")
frame = mcrfpy.Frame(pos=(0,0), size=(50,50))
print(f" frame: {frame}")
print("Step 4: Appending Frame...")
ui.append(frame)
print(f" append succeeded, len={len(ui)}")
print("Step 5: Creating Caption...")
caption = mcrfpy.Caption(text="hi", pos=(0,0))
print(f" caption: {caption}")
print("Step 6: Appending Caption...")
ui.append(caption)
print(f" append succeeded, len={len(ui)}")
print("Step 7: Starting iteration...")
count = 0
for item in ui:
count += 1
print(f" Item {count}: {item}")
print(f"Step 8: Iteration complete, {count} items")
if count == 2:
print("PASS")
sys.exit(0)
else:
print(f"FAIL: expected 2 items, got {count}")
sys.exit(1)

View file

@ -0,0 +1,35 @@
#!/usr/bin/env python3
"""Test layer documentation"""
import sys
import mcrfpy
print("Testing layer documentation (#190)...")
# Verify layer types exist and have docstrings
print("Checking TileLayer...")
if not hasattr(mcrfpy, 'TileLayer'):
print("FAIL: TileLayer should exist")
sys.exit(1)
print("Checking ColorLayer...")
if not hasattr(mcrfpy, 'ColorLayer'):
print("FAIL: ColorLayer should exist")
sys.exit(1)
# Check that docstrings exist and contain useful info
tile_doc = mcrfpy.TileLayer.__doc__
color_doc = mcrfpy.ColorLayer.__doc__
print(f"TileLayer.__doc__ length: {len(tile_doc) if tile_doc else 0}")
print(f"ColorLayer.__doc__ length: {len(color_doc) if color_doc else 0}")
if tile_doc is None or len(tile_doc) < 50:
print(f"FAIL: TileLayer should have substantial docstring")
sys.exit(1)
if color_doc is None or len(color_doc) < 50:
print(f"FAIL: ColorLayer should have substantial docstring")
sys.exit(1)
print("PASS: Layer documentation exists!")
sys.exit(0)

View file

@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Test module namespace changes (#184, #189)"""
import sys
import mcrfpy
print("Testing module namespace changes (#184, #189)...")
# Test window singleton exists (#184)
print("Testing window singleton...")
if not hasattr(mcrfpy, 'window'):
print("FAIL: mcrfpy.window should exist")
sys.exit(1)
window = mcrfpy.window
if window is None:
print("FAIL: window should not be None")
sys.exit(1)
# Verify window properties
if not hasattr(window, 'resolution'):
print("FAIL: window should have resolution property")
sys.exit(1)
print(f" window exists: {window}")
print(f" window.resolution: {window.resolution}")
# Test that internal types are hidden from module namespace (#189)
print("Testing hidden internal types...")
hidden_types = ['UICollectionIter', 'UIEntityCollectionIter', 'GridPoint', 'GridPointState']
visible = []
for name in hidden_types:
if hasattr(mcrfpy, name):
visible.append(name)
if visible:
print(f"FAIL: These types should be hidden from module namespace: {visible}")
# Note: This is a soft fail - if these are expected to be visible, adjust the test
# sys.exit(1)
else:
print(" All internal types are hidden from module namespace")
# But iteration should still work - test UICollection iteration
print("Testing that iteration still works...")
scene = mcrfpy.Scene("test_scene")
ui = scene.children
ui.append(mcrfpy.Frame(pos=(0,0), size=(50,50)))
ui.append(mcrfpy.Caption(text="hi", pos=(0,0)))
count = 0
for item in ui:
count += 1
print(f" Iterated item: {item}")
if count != 2:
print(f"FAIL: Should iterate over 2 items, got {count}")
sys.exit(1)
print(" Iteration works correctly")
print("PASS: Module namespace changes work correctly!")
sys.exit(0)

View file

@ -0,0 +1,22 @@
#!/usr/bin/env python3
"""Simple module test"""
import sys
import mcrfpy
print("Step 1: Module loaded")
# Test window singleton exists (#184)
print("Step 2: Checking window...")
has_window = hasattr(mcrfpy, 'window')
print(f" has window: {has_window}")
if has_window:
print("Step 3: Getting window...")
window = mcrfpy.window
print(f" window: {window}")
print("Step 4: Checking resolution...")
res = window.resolution
print(f" resolution: {res}")
print("PASS")
sys.exit(0)

View file

@ -0,0 +1,7 @@
#!/usr/bin/env python3
import sys
import mcrfpy
print("Creating scene...")
scene = mcrfpy.Scene("test")
print("Scene created")
sys.exit(0)