"""Tests for the room graph + ASCII map renderer.""" from __future__ import annotations from progetto2.mapper import Mapper def test_visit_returns_stable_id() -> None: m = Mapper() a = m.visit("Cave Entrance", "", ["n", "s"]) b = m.visit("Cave Entrance", "", ["n", "s"]) assert a == b def test_dynamic_description_does_not_break_id() -> None: m = Mapper() a = m.visit("Cave Entrance", "Dry and dusty.", ["n"]) b = m.visit("Cave Entrance", "Now dripping with water.", ["n"]) assert a == b assert len(m.rooms) == 1 def test_render_empty() -> None: assert Mapper().render() == "[mappa vuota]" def test_render_single_room() -> None: m = Mapper() m.visit("Lobby", "Wide open space.", []) out = m.render() assert "Lobby" in out assert "»" in out # current marker assert "·" not in out # no neighbours def test_render_grid_with_connectors() -> None: m = Mapper() a = m.visit("Hub", "central.", ["n", "e", "s", "w"]) b = m.visit("NorthRoom", "cold.", ["s"]) m.link_rooms(a, "n", b) m.link_rooms(b, "s", a) c = m.visit("EastRoom", "drafty.", ["w"]) m.link_rooms(a, "e", c) m.link_rooms(c, "w", a) out = m.render() assert "Hub" in out assert "NorthRoom" in out assert "EastRoom" in out assert "│" in out or "───" in out # ----- multi-source BFS / orphan placement ------------------------------- def test_backtracking_visits_are_connected() -> None: """Walking A → B and never back should NOT leave B as orphan, because B's exits include the back-edge to A. """ m = Mapper() a = m.visit("A", "", ["n"]) b = m.visit("B", "", ["s"]) # No link_rooms() — but B has 's' which would point to A. out = m.render(max_cols=20, max_rows=20) assert "A" in out assert "B" in out # Both rooms must be visible in the rendered map. rows = [r for r in out.splitlines() if r.strip()] # Find the row containing B assert any("B" in r for r in rows) assert any("A" in r for r in rows) def test_isolated_room_lands_somewhere_visible() -> None: """A room that has no edges at all should still end up in the rendered map (stacked in the isolated-corner fallback). """ m = Mapper() m.visit("Lobby", "", []) m.visit("Void", "", []) # no edges to anyone out = m.render(max_cols=20, max_rows=20) assert "Lobby" in out assert "Void" in out def test_id_override_used_for_visit() -> None: """When GMCP supplies a vnum, ``id_override`` is used instead of name-hash.""" m = Mapper() a = m.visit("Outer Courtyard", "", ["n"], id_override="vnum42") b = m.visit("Outer Courtyard", "", ["n", "e"], id_override="vnum42") assert a == b == "vnum42" def test_multi_source_render_does_not_split_obviously_connected_rooms() -> None: m = Mapper() a = m.visit("A", "", ["n", "s"]) b = m.visit("B", "", ["s"]) m.link_rooms(a, "n", b) c = m.visit("C", "", []) out = m.render(max_cols=10, max_rows=10) assert "A" in out assert "B" in out assert "C" in out