test(kanban-ws-auth): patch hermes_cli.web_server attribute alongside sys.modules entry
Some checks failed
Nix / nix (macos-latest) (pull_request) Waiting to run
Supply Chain Audit / Scan PR for critical supply chain risks (pull_request) Successful in 42s
Contributor Attribution Check / check-attribution (pull_request) Failing after 43s
Tests / e2e (pull_request) Successful in 2m13s
Nix / nix (ubuntu-latest) (pull_request) Failing after 14m21s
Tests / test (pull_request) Failing after 23m16s

`monkeypatch.setitem(sys.modules, "hermes_cli.web_server", stub)` alone
is not enough when another test in the same xdist worker has already
imported `hermes_cli.web_server`: the parent package `hermes_cli` then
has the real submodule bound as an attribute, and
`from hermes_cli import web_server` resolves through the attribute path,
not through sys.modules. Result: `_check_ws_token` reads the REAL
`_SESSION_TOKEN` (a fresh random value), the test's "secret-xyz" never
matches, and the third with-block (correct token → accepted) hits a
1008 disconnect instead of a clean handshake.

Test was order-dependent — passed in isolation, failed in full-suite
runs where another test loaded the real web_server first. Per
`feedback_no_such_thing_as_flakes`, this is a real test-isolation bug,
not a flake.

Fix: also `monkeypatch.setattr(hermes_cli, "web_server", stub,
raising=False)` so both lookup paths see the stub. Inline comment
documents the gotcha for the next reader.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
dev-lead 2026-05-08 14:08:59 -07:00
parent 3697e6cea2
commit 04d5633745

View File

@ -478,9 +478,19 @@ def test_ws_events_rejects_when_token_required(tmp_path, monkeypatch):
kb.init_db() kb.init_db()
# Stub web_server so _check_ws_token has a token to compare against. # Stub web_server so _check_ws_token has a token to compare against.
# NOTE: monkeypatch.setitem(sys.modules, ...) alone is not enough.
# If another test in the same xdist worker has already imported
# hermes_cli.web_server, the parent package `hermes_cli` has the real
# module bound as an attribute. `from hermes_cli import web_server`
# then resolves via the attribute, NOT sys.modules — so the stub is
# bypassed and _check_ws_token compares against the real (random)
# _SESSION_TOKEN, rejecting our "secret-xyz" branch with 1008.
# Patching the parent package attribute keeps both lookup paths in sync.
import types import types
import hermes_cli
stub = types.SimpleNamespace(_SESSION_TOKEN="secret-xyz") stub = types.SimpleNamespace(_SESSION_TOKEN="secret-xyz")
monkeypatch.setitem(sys.modules, "hermes_cli.web_server", stub) monkeypatch.setitem(sys.modules, "hermes_cli.web_server", stub)
monkeypatch.setattr(hermes_cli, "web_server", stub, raising=False)
app = FastAPI() app = FastAPI()
app.include_router(_load_plugin_router(), prefix="/api/plugins/kanban") app.include_router(_load_plugin_router(), prefix="/api/plugins/kanban")