Two invariants only a live homeserver can check, now enforced rather than verified by hand: - The configured NISSE_MATRIX_USER_ID must be the token's real owner. MatrixTransport filters its own messages by comparing sender to that value, so a mismatch would make the bot read its own posts as operator input. - The account must be a testing identity, so a stray live run can never act as the production agent. Both hold today; this keeps them holding when the production nisse-dev account is created. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
"""Live smoke test against the real homeserver, bound strictly to the
|
|
dedicated test room (never the production room).
|
|
|
|
NISSE_MATRIX_HOMESERVER alone decides whether this runs: if it is set, the
|
|
live path is expected to work, and anything else missing is a *failure*, not
|
|
a skip. A half-configured environment must not pass quietly as a skip — that
|
|
is how a broken CI credential hides."""
|
|
|
|
import os
|
|
import uuid
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from nisse_dev.envfile import load_env_file
|
|
from nisse_dev.matrix import MatrixConfig, MatrixTransport
|
|
|
|
load_env_file(Path(__file__).resolve().parents[2] / ".env")
|
|
|
|
SENTINEL = "NISSE_MATRIX_HOMESERVER"
|
|
ALSO_REQUIRED = (
|
|
"NISSE_MATRIX_USER_ID",
|
|
"NISSE_MATRIX_TOKEN",
|
|
"NISSE_MATRIX_TEST_ROOM_ID",
|
|
)
|
|
|
|
pytestmark = [
|
|
pytest.mark.integration,
|
|
pytest.mark.skipif(
|
|
not os.environ.get(SENTINEL),
|
|
reason=f"no live homeserver configured ({SENTINEL} unset)",
|
|
),
|
|
]
|
|
|
|
|
|
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"NISSE_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() -> None:
|
|
missing = [var for var in ALSO_REQUIRED if not os.environ.get(var)]
|
|
assert not missing, (
|
|
f"{SENTINEL} is set, so the live Matrix path is expected to work, "
|
|
f"but these are missing: {', '.join(missing)}"
|
|
)
|
|
config = MatrixConfig.from_env(room_var="NISSE_MATRIX_TEST_ROOM_ID")
|
|
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()
|