Skip to content

Commit efe509f

Browse files
test(web): stub the park-first backlog gate in start-flow picker tests
In the full integration sweep, TestStartSessionFlow's four tests timed out waiting for the start POST's outcome. Diagnosed with a probe page: the click never reached /api/session/start, because startSession() first consults GET /api/backlog (the AuDHD MAX_ACTIVE_TOPICS park-first gate) — which was the ONE endpoint these tests left unstubbed. Earlier study-integration runs in the same pytest process leave 3+ active topics in the shared suite DB (their study sessions now persist through the context layer), so the gate swallowed the click into the park-first overlay and no POST, event, or picker error ever happened. In isolation the backlog was empty, which is why the tests passed alone. _stub_start() now stubs /api/backlog to 'no pressure' alongside the start route (and the network-error test does the same), so these tests assert what they claim to: the start POST contract, not backlog state leaked by whoever ran first. Verified: the minimal reproducing pair (study_integration + web_session_lifecycle) passes, as does the file alone.
1 parent c8315cc commit efe509f

1 file changed

Lines changed: 25 additions & 0 deletions

File tree

packages/studyloop/tests/test_web_session_lifecycle.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,26 @@ def _stub_topics_list(page: Page, topics: list[dict] | None = None) -> None:
132132
page.route("**/api/session/topics", lambda route: _fulfill(route, topics or []))
133133

134134

135+
def _stub_backlog(page: Page, payload: dict | None = None) -> None:
136+
"""Neutralise the park-first gate for start-flow tests.
137+
138+
startSession() consults GET /api/backlog BEFORE posting: at
139+
MAX_ACTIVE_TOPICS active topics it swallows the click into the park-first
140+
overlay and never reaches /api/session/start. That gate is real product
141+
behaviour with its own tests — but these tests assert on the start POST's
142+
outcome, so the backlog must answer "no pressure" regardless of what any
143+
earlier test in the process wrote into the shared suite DB (this exact
144+
leak — study-integration runs leaving 3+ active topics — made every
145+
start-flow test time out when the whole integration sweep ran together).
146+
"""
147+
page.route(
148+
"**/api/backlog",
149+
lambda route: _fulfill(
150+
route, payload or {"active": [], "backlog": [], "active_count": 0, "max_active": 3}
151+
),
152+
)
153+
154+
135155
def _goto_picker(page: Page) -> None:
136156
page.goto(f"http://127.0.0.1:{WEB_PORT}/#study-session")
137157
page.wait_for_load_state("domcontentloaded")
@@ -378,6 +398,10 @@ def test_each_target_kind_renders(self, web_page: Page, kind: str) -> None:
378398

379399
class TestStartSessionFlow:
380400
def _stub_start(self, page: Page, *, status: int, body: dict) -> None:
401+
# Every start-flow test needs the park-first gate neutralised too —
402+
# stubbing it here keeps the pairing impossible to forget.
403+
_stub_backlog(page)
404+
381405
def handler(route: Route) -> None:
382406
if route.request.method == "POST":
383407
_fulfill(route, body, status=status)
@@ -498,6 +522,7 @@ def test_network_error_surfaces_cleanly(self, web_page: Page) -> None:
498522
_stub_session_state(web_page)
499523
_stub_topics_list(web_page)
500524
web_page.route("**/api/session/start", lambda route: route.abort("failed"))
525+
_stub_backlog(web_page)
501526
_goto_picker(web_page)
502527

503528
web_page.evaluate(

0 commit comments

Comments
 (0)