Skip to content

Commit 098a9da

Browse files
cursoragentBoden
andcommitted
test(pykotor): cover area layout deserialize errors and object roundtrip
Co-authored-by: Boden <th3w1zard1@users.noreply.github.com>
1 parent fce6ed6 commit 098a9da

1 file changed

Lines changed: 95 additions & 7 deletions

File tree

Libraries/PyKotor/tests/test_area_layout.py

Lines changed: 95 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,26 @@
1818

1919
def _layout_test_kit() -> TileKit:
2020
kit = TileKit(name="Layout Kit", kit_id="layout")
21-
kit.floors.append(TileTemplate(TileTemplateKind.FLOOR, "floor_a", "floor_a", name="Floor A", model="floor_a"))
21+
kit.floors.append(
22+
TileTemplate(TileTemplateKind.FLOOR, "floor_a", "floor_a", name="Floor A", model="floor_a")
23+
)
2224
kit.ceilings.append(
23-
TileTemplate(TileTemplateKind.CEILING, "ceiling_a", "ceiling_a", name="Ceiling A", model="ceiling_a")
25+
TileTemplate(
26+
TileTemplateKind.CEILING, "ceiling_a", "ceiling_a", name="Ceiling A", model="ceiling_a"
27+
)
28+
)
29+
kit.walls.append(
30+
TileTemplate(TileTemplateKind.WALL, "wall_a", "wall_a", name="Wall A", model="wall_a")
2431
)
25-
kit.walls.append(TileTemplate(TileTemplateKind.WALL, "wall_a", "wall_a", name="Wall A", model="wall_a"))
2632
kit.inner_corners.append(
27-
TileTemplate(TileTemplateKind.INNER_CORNER, "inner_a", "inner_a", name="Inner A", model="inner_a")
33+
TileTemplate(
34+
TileTemplateKind.INNER_CORNER, "inner_a", "inner_a", name="Inner A", model="inner_a"
35+
)
2836
)
2937
kit.outer_corners.append(
30-
TileTemplate(TileTemplateKind.OUTER_CORNER, "outer_a", "outer_a", name="Outer A", model="outer_a")
38+
TileTemplate(
39+
TileTemplateKind.OUTER_CORNER, "outer_a", "outer_a", name="Outer A", model="outer_a"
40+
)
3141
)
3242
kit.tiles.append(
3343
TileCellTemplate(
@@ -40,13 +50,22 @@ def _layout_test_kit() -> TileKit:
4050
WallHookTemplate("wall_a", Vector3(-5.0, 0.0, 0.0), QuaternionWXYZ()),
4151
],
4252
inner_corner_hooks=[
43-
CornerHookTemplate("inner_a", Vector3(5.0, 5.0, 0.0), QuaternionWXYZ(), adjacent=[0, 1])
53+
CornerHookTemplate(
54+
"inner_a", Vector3(5.0, 5.0, 0.0), QuaternionWXYZ(), adjacent=[0, 1]
55+
)
4456
],
4557
outer_corner_hooks=[
46-
CornerHookTemplate("outer_a", Vector3(-5.0, -5.0, 0.0), QuaternionWXYZ(), adjacent=[0, 1])
58+
CornerHookTemplate(
59+
"outer_a", Vector3(-5.0, -5.0, 0.0), QuaternionWXYZ(), adjacent=[0, 1]
60+
)
4761
],
4862
)
4963
)
64+
kit.objects.append(
65+
TileTemplate(
66+
TileTemplateKind.OBJECT, "crate_a", "crate_a", name="Crate A", model="crate_a"
67+
),
68+
)
5069
return kit
5170

5271

@@ -111,3 +130,72 @@ def test_area_layout_roundtrip_dict_preserves_tiles_and_wall_overrides():
111130
assert len(restored.rooms[0].tiles) == 2
112131
assert restored.rooms[0].tiles[1].local_position.x == pytest.approx(10.0)
113132
assert restored.rooms[0].tiles[0].walls[0].linked_tile is restored.rooms[0].tiles[1]
133+
134+
135+
def _kit_with_tile_b_wall_mismatch() -> TileKit:
136+
"""Second tile only exposes ``wall_b`` hooks; extending from a ``wall_a`` edge must fail loudly."""
137+
kit = _layout_test_kit()
138+
kit.walls.append(
139+
TileTemplate(TileTemplateKind.WALL, "wall_b", "wall_b", name="Wall B", model="wall_b")
140+
)
141+
kit.tiles.append(
142+
TileCellTemplate(
143+
template_id="tile_b",
144+
name="Tile B",
145+
default_floor_id="floor_a",
146+
default_ceiling_id="ceiling_a",
147+
wall_hooks=[WallHookTemplate("wall_b", Vector3(5.0, 0.0, 0.0), QuaternionWXYZ())],
148+
)
149+
)
150+
return kit
151+
152+
153+
def test_area_layout_extend_tile_from_wall_raises_when_no_hook_matches_wall_type():
154+
kit = _kit_with_tile_b_wall_mismatch()
155+
layout = AreaLayout()
156+
room = layout.add_room_from_tile(kit, "tile_a")
157+
wall_a = room.tiles[0].walls[0]
158+
159+
with pytest.raises(ValueError, match="has no wall hook for wall_a"):
160+
room.extend_tile_from_wall(kit, room.tiles[0], wall_a, "tile_b")
161+
162+
163+
def test_area_layout_from_dict_missing_kit_raises():
164+
kit = _layout_test_kit()
165+
layout = AreaLayout()
166+
layout.add_room_from_tile(kit, "tile_a")
167+
data = area_layout_to_dict(layout)
168+
data["rooms"][0]["tiles"][0]["kitID"] = "no_such_kit"
169+
170+
with pytest.raises(ValueError, match="Missing kit no_such_kit"):
171+
area_layout_from_dict(data, {"layout": kit})
172+
173+
174+
def test_area_layout_from_dict_invalid_floor_override_raises():
175+
kit = _layout_test_kit()
176+
layout = AreaLayout()
177+
layout.add_room_from_tile(kit, "tile_a")
178+
data = area_layout_to_dict(layout)
179+
data["rooms"][0]["tiles"][0]["floor"]["templateID"] = "not_a_floor_template"
180+
181+
with pytest.raises(ValueError, match="Missing floor template not_a_floor_template"):
182+
area_layout_from_dict(data, {"layout": kit})
183+
184+
185+
def test_area_layout_objects_roundtrip_dict():
186+
kit = _layout_test_kit()
187+
layout = AreaLayout()
188+
room = layout.add_room_from_tile(kit, "tile_a")
189+
room.add_object(kit, "crate_a", position=Vector3(1.0, 2.0, 3.0))
190+
191+
data = area_layout_to_dict(layout)
192+
restored = area_layout_from_dict(data, {"layout": kit})
193+
194+
assert len(restored.rooms) == 1
195+
assert len(restored.rooms[0].objects) == 1
196+
obj = restored.rooms[0].objects[0]
197+
assert obj.template_id == "crate_a"
198+
assert obj.kit_id == "layout"
199+
assert obj.local_position.x == pytest.approx(1.0)
200+
assert obj.local_position.y == pytest.approx(2.0)
201+
assert obj.local_position.z == pytest.approx(3.0)

0 commit comments

Comments
 (0)