"""Live smoke test against the real homeserver, bound strictly to the dedicated test room that nisse-test.yaml names (never the production room).""" import uuid import pytest from nisse_core.conversation.matrix import MatrixConfig, MatrixTransport from nisse_dev.config import AgentConfig pytestmark = pytest.mark.integration def _assert_testing_identity(transport: MatrixTransport, config: MatrixConfig) -> None: """Two invariants that only a live homeserver can check. The configured user id must be the token's real owner, because the transport filters its own messages by comparing sender to that value — a mismatch would make the bot read its own posts as operator input. And tests must run as a testing identity, so a stray live run can never act as the production agent. """ whoami = transport._http.get("/account/whoami") whoami.raise_for_status() actual = whoami.json()["user_id"] assert actual == config.user_id, ( f"matrix.user_id is {config.user_id} but the token belongs to " f"{actual}; the self-message filter would not match" ) assert "testing" in actual, ( f"live tests must run as a testing identity, not {actual}" ) def test_send_lands_in_test_room(live_config: AgentConfig) -> None: config = live_config.matrix marker = f"transport smoke test {uuid.uuid4().hex}" transport = MatrixTransport(config) try: _assert_testing_identity(transport, config) transport.send_message(marker) response = transport._http.get( f"/rooms/{config.room_id}/messages", params={"dir": "b", "limit": "10"}, ) response.raise_for_status() bodies = [ event.get("content", {}).get("body") for event in response.json().get("chunk", []) ] assert marker in bodies finally: transport.close() def test_a_threaded_post_is_kept_in_its_thread(live_config: AgentConfig) -> None: """The homeserver accepts the thread relation and lists the reply under its root (L5: a work item's conversation is a thread).""" config = live_config.matrix marker = uuid.uuid4().hex transport = MatrixTransport(config) try: _assert_testing_identity(transport, config) root = transport.post(f"thread smoke test root {marker}") reply = transport.post(f"thread smoke test reply {marker}", thread=root) # The relations API is v1, not the transport's v3. response = transport._http.get( f"{config.homeserver}/_matrix/client/v1/rooms/{config.room_id}" f"/relations/{root}/m.thread" ) response.raise_for_status() in_thread = [e["event_id"] for e in response.json().get("chunk", [])] assert reply in in_thread finally: transport.close()