Repository navigation
fix(e2e): bump stale 2026-06-07 seed dates so /v/open tests stop timing out - #227
Merged
Merged
Conversation
Summary: Four e2e tests (test_decline_reopen, test_event_roster_fill,
test_open_shifts, test_swap_marketplace) seed a "Sunday 10am Service"
event with hard-coded date 2026-06-07 and then wait for it on `/v/open`
(or the swap-open list). Those volunteer-facing views filter out past
events, so as soon as today's date passed 2026-06-07 the selector
`#open-list:has-text('Sunday 10am Service')` started timing out on
every PR — blocking the E2E lane for all new work.
The fix replaces the literal with a `next_sunday_iso()` helper in
`tests/e2e/_helpers.py` that always returns a Sunday at least 7 days
out, so the seed event is reliably in the future regardless of when the
suite runs.
Scoped narrowly: only the 4 tests whose date drives a future-filtered
view are touched. Other tests still using 2026-06-07 (analytics,
recurring, smoke, etc.) interact with admin views that don't filter on
date, and some pair the date with a hard-coded solver window — bumping
their date would require also bumping the window. Left for a follow-up.
Changed files:
- tests/e2e/_helpers.py — add next_sunday_iso() helper
- tests/e2e/test_decline_reopen.py
- tests/e2e/test_event_roster_fill.py
- tests/e2e/test_open_shifts.py
- tests/e2e/test_swap_marketplace.py
Validation:
- poetry run black tests/e2e/ — clean
- poetry run ruff check tests/e2e/ — clean
- poetry run pytest --co tests/ — 361 tests collected (imports OK)
- E2E suite couldn't run locally (Playwright browser version mismatch);
CI is the source of truth for the E2E lane.
Follow-ups:
- Sweep the remaining 7 e2e files that still use 2026-06-07; they pass
today but will rot. Bump dates AND the associated solver windows in
the same PR to avoid breaking previously-green tests.
tomqwu
marked this pull request as ready for review
June 25, 2026 13:46
tomqwu
pushed a commit
that referenced
this pull request
Jun 25, 2026
Summary: `GET /api/v1/calendar/org/export` previously accepted `person_id` as a query parameter and used it as the auth proxy — "must refer to an admin in this org." Person ids are deterministic (often email-derived slugs), so anyone who could enumerate or guess an admin's id could download the entire org's events. Auth is now JWT-only via Depends(get_current_admin_user), with the same-org check delegated to verify_org_member. This closes the follow-up explicitly named in PR #226 (4.5b). Changed files: - api/routers/calendar.py — replace spoofable person_id query param with Depends(get_current_admin_user) + verify_org_member(current_admin, org_id). The `person_id` query param is dropped from the signature; any extra query params remaining on legacy callers are ignored by FastAPI. - tests/api/test_calendar_auth.py — new TestOrgExportAuth class with 5 cases: unauth → 401/403, volunteer-in-same-org → 403, admin-cross-org → 403, admin-same-org-no-events → 404, and an explicit regression test that a volunteer cannot escalate by passing an admin's id as the legacy ?person_id= spoof param. - tests/conftest.py — extend the unit-tier verify_org_member monkey-patch list to include api.routers.calendar (it now imports the symbol directly so the patch must rebind there too). - tests/unit/test_calendar.py — drop the now-dead ?person_id= query param from the URLs; remove `test_org_export_as_volunteer_denied` (mocked auth always returns an admin so the case is not representable in this tier — the equivalent assertion lives in TestOrgExportAuth). - tests/contract/openapi.snapshot.json — refreshed via make update-openapi-snapshot: person_id parameter removed, HTTPBearer security added to the operation, description bumped. Validation: - poetry run pytest tests/api/test_calendar_auth.py tests/unit/test_calendar.py → 32 passed - make test-unit-fast → 338 passed, 21 skipped - poetry run pytest tests/api tests/contract → 316 passed - poetry run pytest tests/cli tests/integration → 59 passed - poetry run black api tests — clean - poetry run ruff check api tests — clean Follow-ups: - E2E lane will only go green once #227 (fix-e2e-stale-dates) lands and this branch is rebased onto the updated main. The stale-date flake is unrelated to this change and pre-exists in the suite.
tomqwu
pushed a commit
that referenced
this pull request
Jun 25, 2026
Summary: `GET /api/v1/calendar/org/export` previously accepted `person_id` as a query parameter and used it as the auth proxy — "must refer to an admin in this org." Person ids are deterministic (often email-derived slugs), so anyone who could enumerate or guess an admin's id could download the entire org's events. Auth is now JWT-only via Depends(get_current_admin_user), with the same-org check delegated to verify_org_member. This closes the follow-up explicitly named in PR Changed files: - api/routers/calendar.py — replace spoofable person_id query param with Depends(get_current_admin_user) + verify_org_member(current_admin, org_id). The `person_id` query param is dropped from the signature; any extra query params remaining on legacy callers are ignored by FastAPI. - tests/api/test_calendar_auth.py — new TestOrgExportAuth class with 5 cases: unauth → 401/403, volunteer-in-same-org → 403, admin-cross-org → 403, admin-same-org-no-events → 404, and an explicit regression test that a volunteer cannot escalate by passing an admin's id as the legacy ?person_id= spoof param. - tests/conftest.py — extend the unit-tier verify_org_member monkey-patch list to include api.routers.calendar (it now imports the symbol directly so the patch must rebind there too). - tests/unit/test_calendar.py — drop the now-dead ?person_id= query param from the URLs; remove `test_org_export_as_volunteer_denied` (mocked auth always returns an admin so the case is not representable in this tier — the equivalent assertion lives in TestOrgExportAuth). - tests/contract/openapi.snapshot.json — refreshed via make update-openapi-snapshot: person_id parameter removed, HTTPBearer security added to the operation, description bumped. Validation: - poetry run pytest tests/api/test_calendar_auth.py tests/unit/test_calendar.py → 32 passed - make test-unit-fast → 338 passed, 21 skipped - poetry run pytest tests/api tests/contract → 316 passed - poetry run pytest tests/cli tests/integration → 59 passed - poetry run black api tests — clean - poetry run ruff check api tests — clean Follow-ups: - E2E lane will only go green once #227 (fix-e2e-stale-dates) lands and this branch is rebased onto the updated main. The stale-date flake is unrelated to this change and pre-exists in the suite.
tomqwu
added a commit
that referenced
this pull request
Jun 25, 2026
Summary: `GET /api/v1/calendar/org/export` previously accepted `person_id` as a query parameter and used it as the auth proxy — "must refer to an admin in this org." Person ids are deterministic (often email-derived slugs), so anyone who could enumerate or guess an admin's id could download the entire org's events. Auth is now JWT-only via Depends(get_current_admin_user), with the same-org check delegated to verify_org_member. This closes the follow-up explicitly named in PR Changed files: - api/routers/calendar.py — replace spoofable person_id query param with Depends(get_current_admin_user) + verify_org_member(current_admin, org_id). The `person_id` query param is dropped from the signature; any extra query params remaining on legacy callers are ignored by FastAPI. - tests/api/test_calendar_auth.py — new TestOrgExportAuth class with 5 cases: unauth → 401/403, volunteer-in-same-org → 403, admin-cross-org → 403, admin-same-org-no-events → 404, and an explicit regression test that a volunteer cannot escalate by passing an admin's id as the legacy ?person_id= spoof param. - tests/conftest.py — extend the unit-tier verify_org_member monkey-patch list to include api.routers.calendar (it now imports the symbol directly so the patch must rebind there too). - tests/unit/test_calendar.py — drop the now-dead ?person_id= query param from the URLs; remove `test_org_export_as_volunteer_denied` (mocked auth always returns an admin so the case is not representable in this tier — the equivalent assertion lives in TestOrgExportAuth). - tests/contract/openapi.snapshot.json — refreshed via make update-openapi-snapshot: person_id parameter removed, HTTPBearer security added to the operation, description bumped. Validation: - poetry run pytest tests/api/test_calendar_auth.py tests/unit/test_calendar.py → 32 passed - make test-unit-fast → 338 passed, 21 skipped - poetry run pytest tests/api tests/contract → 316 passed - poetry run pytest tests/cli tests/integration → 59 passed - poetry run black api tests — clean - poetry run ruff check api tests — clean Follow-ups: - E2E lane will only go green once #227 (fix-e2e-stale-dates) lands and this branch is rebased onto the updated main. The stale-date flake is unrelated to this change and pre-exists in the suite. Co-authored-by: Claude <noreply@anthropic.com>
tomqwu
added a commit
that referenced
this pull request
Jul 13, 2026
* fix(e2e): sweep stale 2026-06-07 seed dates + hardcoded solver windows Summary: Follow-up from PR #227. That PR bumped `2026-06-07` in four e2e files that watch `/v/open` (which filters out past events), but explicitly left the remaining seven for a separate sweep because their tests also seed a hardcoded solver window (`from=2026-05-19, to=2026-06-30`) that had to move in lockstep with the seed event date. Today (2026-07-13) is already past `2026-06-07`, so a solve-and-publish flow can produce an empty solution and drop /v/schedule assertions. Adds `solver_window_around(seed_iso)` to `tests/e2e/_helpers.py` returning a (from, to) 3-week bracket, then replaces the literal seed date with `next_sunday_iso()` and the literal window with `solver_window_around()` across all seven files. Changed files: - tests/e2e/_helpers.py — new `solver_window_around()` helper (docstring documents the rot pattern it prevents). - tests/e2e/test_smoke_full_loop.py, tests/e2e/test_availability_solver.py, tests/e2e/test_bulk_notify.py, tests/e2e/test_calendar_subscription.py, tests/e2e/test_onboarding_wizard.py — inline seed/window inside the single test function. - tests/e2e/test_notif_assign_unpublish.py, tests/e2e/test_analytics_recurring_swapreview.py — module-level `EV_DATE` / `FROM_DATE` / `TO_DATE` so the shared `_new_event` / `_solve_and_publish` helpers stay parameterless. - tests/unit/test_e2e_helpers.py — new: 3 invariants for the helpers (Sunday-in-future, seed strictly inside window, deterministic). Validation: - `poetry run pytest tests/unit/test_e2e_helpers.py tests/unit/test_e2e_lane.py` → 5 passed - `make test-unit-fast` → 341 passed, 21 skipped - `poetry run pytest tests/api tests/contract tests/web` → 550 passed - `poetry run black --check api tests` → clean - `poetry run ruff check api tests` → clean - `python -m py_compile` on all touched files → clean Follow-ups: - `2026-07-05` in test_analytics_recurring_swapreview.py (recurring-series start date, `#rs_sd`) is not on the same solve-and-publish path and is still ~2 weeks in the future — leaving alone to keep this sweep narrow. Worth bumping alongside a future rot fix. * chore: re-trigger CI after Service Unavailable infra flake The prior run's "Lint, type-check, and test" job failed at step 1 (Set up job) with "Failed to resolve action download info. Error: Service Unavailable" — a GitHub Actions runner-provisioning outage, not a real test failure. The e2e job on the same commit passed. * chore: second retrigger after GHA action-metadata outage --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Four e2e tests (
test_decline_reopen,test_event_roster_fill,test_open_shifts,test_swap_marketplace) seed a "Sunday 10am Service" event with hard-coded date2026-06-07and then wait for it on/v/open(or the swap-open list). Those volunteer-facing views filter out past events, so as soon as today's date rolled past 2026-06-07 the selector#open-list:has-text('Sunday 10am Service')started timing out on every PR — blocking the E2E lane for all new work, not just the PR that happens to be open.PR #226 (calendar/export auth) is currently red on this exact pattern. Landing this first unblocks both #226 and the in-flight
sprint-4-pr-4-5c-calendar-org-export-authwork.What changed
tests/e2e/_helpers.py— newnext_sunday_iso()helper returning a Sunday at least 7 days fromdate.today(). Keeps the seed event reliably in the future regardless of when the suite runs.tests/e2e/test_decline_reopen.py,test_event_roster_fill.py,test_open_shifts.py,test_swap_marketplace.py— replace the literal"2026-06-07"withnext_sunday_iso().Scope
Narrow on purpose. Seven other e2e files still pass
"2026-06-07", but they exercise admin views that do not filter on date, and some pair the date with a hard-coded solver window (e.g._solve_and_publishusesfrom=2026-05-19, to=2026-06-30). Bumping their date without also bumping the window would break previously-green tests. Left as a follow-up.Validation
poetry run black tests/e2e/cleanpoetry run ruff check tests/e2e/cleanpoetry run pytest --co tests/collects 361 tests (imports OK)Follow-ups
2026-06-07. Bump the dates and the matching solver windows in the same PR.Generated by Claude Code.
Generated by Claude Code