test(01-06): harden matrix room-vs-chat regressions

- Seed invite tests with explicit next_chat_index progression instead of C1 assumptions
- Separate Matrix room ids from logical chat ids in dispatcher coverage
- Verify the full Matrix adapter suite against the tightened assertions
This commit is contained in:
Mikhail Putilovskij 2026-04-03 12:35:09 +03:00
parent 3e06a67e24
commit 9cdb6118e9
2 changed files with 25 additions and 14 deletions

View file

@ -12,28 +12,30 @@ from sdk.mock import MockPlatformClient
async def test_matrix_dispatcher_registers_custom_handlers(): async def test_matrix_dispatcher_registers_custom_handlers():
runtime = build_runtime(platform=MockPlatformClient()) runtime = build_runtime(platform=MockPlatformClient())
current_chat_id = "C9"
start = IncomingCommand(user_id="u1", platform="matrix", chat_id="C1", command="start") start = IncomingCommand(user_id="u1", platform="matrix", chat_id=current_chat_id, command="start")
await runtime.dispatcher.dispatch(start) await runtime.dispatcher.dispatch(start)
new = IncomingCommand( new = IncomingCommand(
user_id="u1", platform="matrix", chat_id="C1", command="new", args=["Research"] user_id="u1", platform="matrix", chat_id=current_chat_id, command="new", args=["Research"]
) )
result = await runtime.dispatcher.dispatch(new) result = await runtime.dispatcher.dispatch(new)
assert any(isinstance(r, OutgoingMessage) and "Research" in r.text for r in result) assert any(isinstance(r, OutgoingMessage) and "Research" in r.text for r in result)
chats = await runtime.chat_mgr.list_active("u1") chats = await runtime.chat_mgr.list_active("u1")
assert [c.chat_id for c in chats] == ["C1"] assert [c.chat_id for c in chats] == ["C1"]
assert [c.surface_ref for c in chats] == [current_chat_id]
new2 = IncomingCommand( new2 = IncomingCommand(
user_id="u1", platform="matrix", chat_id="C1", command="new", args=["Ops"] user_id="u1", platform="matrix", chat_id=current_chat_id, command="new", args=["Ops"]
) )
await runtime.dispatcher.dispatch(new2) await runtime.dispatcher.dispatch(new2)
chats = await runtime.chat_mgr.list_active("u1") chats = await runtime.chat_mgr.list_active("u1")
assert [c.chat_id for c in chats] == ["C1", "C2"] assert [c.chat_id for c in chats] == ["C1", "C2"]
skills = IncomingCommand( skills = IncomingCommand(
user_id="u1", platform="matrix", chat_id="C1", command="settings_skills" user_id="u1", platform="matrix", chat_id=current_chat_id, command="settings_skills"
) )
result = await runtime.dispatcher.dispatch(skills) result = await runtime.dispatcher.dispatch(skills)
assert any(isinstance(r, OutgoingMessage) and "!skill on/off" in r.text for r in result) assert any(isinstance(r, OutgoingMessage) and "!skill on/off" in r.text for r in result)
@ -56,15 +58,15 @@ async def test_new_chat_creates_real_matrix_room_when_client_available():
room_invite=AsyncMock(), room_invite=AsyncMock(),
) )
runtime = build_runtime(platform=MockPlatformClient(), client=client) runtime = build_runtime(platform=MockPlatformClient(), client=client)
await set_user_meta(runtime.store, "u1", {"space_id": "!space:example", "next_chat_index": 1}) await set_user_meta(runtime.store, "u1", {"space_id": "!space:example", "next_chat_index": 7})
start = IncomingCommand(user_id="u1", platform="matrix", chat_id="C1", command="start") start = IncomingCommand(user_id="u1", platform="matrix", chat_id="C3", command="start")
await runtime.dispatcher.dispatch(start) await runtime.dispatcher.dispatch(start)
new = IncomingCommand( new = IncomingCommand(
user_id="u1", user_id="u1",
platform="matrix", platform="matrix",
chat_id="C1", chat_id="C3",
command="new", command="new",
args=["Research"], args=["Research"],
) )
@ -75,12 +77,14 @@ async def test_new_chat_creates_real_matrix_room_when_client_available():
put_call = client.room_put_state.call_args put_call = client.room_put_state.call_args
assert put_call.kwargs.get("room_id") == "!space:example" or put_call.args[0] == "!space:example" assert put_call.kwargs.get("room_id") == "!space:example" or put_call.args[0] == "!space:example"
chats = await runtime.chat_mgr.list_active("u1") chats = await runtime.chat_mgr.list_active("u1")
assert [c.chat_id for c in chats] == ["C7"]
assert [c.surface_ref for c in chats] == ["!r2:example"] assert [c.surface_ref for c in chats] == ["!r2:example"]
assert any(isinstance(r, OutgoingMessage) and "Research" in r.text for r in result) assert any(isinstance(r, OutgoingMessage) and "Research" in r.text for r in result)
async def test_invite_event_creates_space_and_chat_room(): async def test_invite_event_creates_space_and_chat_room():
runtime = build_runtime(platform=MockPlatformClient()) runtime = build_runtime(platform=MockPlatformClient())
await set_user_meta(runtime.store, "@alice:example.org", {"next_chat_index": 4})
space_resp = SimpleNamespace(room_id="!space:example.org") space_resp = SimpleNamespace(room_id="!space:example.org")
chat_resp = SimpleNamespace(room_id="!chat1:example.org") chat_resp = SimpleNamespace(room_id="!chat1:example.org")
client = SimpleNamespace( client = SimpleNamespace(
@ -111,10 +115,11 @@ async def test_invite_event_creates_space_and_chat_room():
room_meta = await get_room_meta(runtime.store, "!chat1:example.org") room_meta = await get_room_meta(runtime.store, "!chat1:example.org")
assert room_meta is not None assert room_meta is not None
assert room_meta["chat_id"] == "C1" assert room_meta["chat_id"] == "C4"
assert room_meta["space_id"] == "!space:example.org" assert room_meta["space_id"] == "!space:example.org"
assert await runtime.auth_mgr.is_authenticated("@alice:example.org") is True assert await runtime.auth_mgr.is_authenticated("@alice:example.org") is True
assert user_meta.get("next_chat_index") == 5
client.room_send.assert_awaited_once() client.room_send.assert_awaited_once()
@ -155,11 +160,14 @@ async def test_bot_ignores_its_own_messages():
async def test_mat11_settings_returns_dashboard(): async def test_mat11_settings_returns_dashboard():
runtime = build_runtime(platform=MockPlatformClient()) runtime = build_runtime(platform=MockPlatformClient())
current_chat_id = "C9"
start = IncomingCommand(user_id="u1", platform="matrix", chat_id="C1", command="start") start = IncomingCommand(user_id="u1", platform="matrix", chat_id=current_chat_id, command="start")
await runtime.dispatcher.dispatch(start) await runtime.dispatcher.dispatch(start)
settings_cmd = IncomingCommand(user_id="u1", platform="matrix", chat_id="C1", command="settings") settings_cmd = IncomingCommand(
user_id="u1", platform="matrix", chat_id=current_chat_id, command="settings"
)
result = await runtime.dispatcher.dispatch(settings_cmd) result = await runtime.dispatcher.dispatch(settings_cmd)
assert len(result) >= 1 assert len(result) >= 1

View file

@ -5,7 +5,7 @@ from unittest.mock import AsyncMock
from adapter.matrix.bot import build_runtime from adapter.matrix.bot import build_runtime
from adapter.matrix.handlers.auth import handle_invite from adapter.matrix.handlers.auth import handle_invite
from adapter.matrix.store import get_room_meta, get_user_meta from adapter.matrix.store import get_room_meta, get_user_meta, set_user_meta
from sdk.mock import MockPlatformClient from sdk.mock import MockPlatformClient
@ -23,6 +23,7 @@ def _make_client():
async def test_mat01_invite_creates_space_and_chat1(): async def test_mat01_invite_creates_space_and_chat1():
runtime = build_runtime(platform=MockPlatformClient()) runtime = build_runtime(platform=MockPlatformClient())
await set_user_meta(runtime.store, "@alice:example.org", {"next_chat_index": 4})
client = _make_client() client = _make_client()
room = SimpleNamespace(room_id="!dm:example.org", display_name="Alice") room = SimpleNamespace(room_id="!dm:example.org", display_name="Alice")
event = SimpleNamespace(sender="@alice:example.org", membership="invite") event = SimpleNamespace(sender="@alice:example.org", membership="invite")
@ -45,8 +46,9 @@ async def test_mat01_invite_creates_space_and_chat1():
room_meta = await get_room_meta(runtime.store, "!chat1:example.org") room_meta = await get_room_meta(runtime.store, "!chat1:example.org")
assert room_meta is not None assert room_meta is not None
assert room_meta["chat_id"] == "C1" assert room_meta["chat_id"] == "C4"
assert room_meta["space_id"] == "!space:example.org" assert room_meta["space_id"] == "!space:example.org"
assert user_meta["next_chat_index"] == 5
async def test_mat02_invite_idempotent(): async def test_mat02_invite_idempotent():
@ -63,6 +65,7 @@ async def test_mat02_invite_idempotent():
async def test_mat03_no_hardcoded_c1(): async def test_mat03_no_hardcoded_c1():
runtime = build_runtime(platform=MockPlatformClient()) runtime = build_runtime(platform=MockPlatformClient())
await set_user_meta(runtime.store, "@alice:example.org", {"next_chat_index": 7})
client = _make_client() client = _make_client()
room = SimpleNamespace(room_id="!dm:example.org", display_name="Alice") room = SimpleNamespace(room_id="!dm:example.org", display_name="Alice")
event = SimpleNamespace(sender="@alice:example.org", membership="invite") event = SimpleNamespace(sender="@alice:example.org", membership="invite")
@ -71,8 +74,8 @@ async def test_mat03_no_hardcoded_c1():
room_meta = await get_room_meta(runtime.store, "!chat1:example.org") room_meta = await get_room_meta(runtime.store, "!chat1:example.org")
assert room_meta is not None assert room_meta is not None
assert room_meta["chat_id"] == "C1" assert room_meta["chat_id"] == "C7"
user_meta = await get_user_meta(runtime.store, "@alice:example.org") user_meta = await get_user_meta(runtime.store, "@alice:example.org")
assert user_meta is not None assert user_meta is not None
assert user_meta["next_chat_index"] == 2 assert user_meta["next_chat_index"] == 8