Skip to content

Sprint 4 PR 4.6b — integration tests for password-reset router - #242

Merged
tomqwu merged 1 commit into
mainfrom
sprint-4-pr-4-6b-password-reset-integration
Jul 19, 2026
Merged

tomqwu merged 1 commit into
mainfrom
sprint-4-pr-4-6b-password-reset-integration

Conversation

@tomqwu

@tomqwu tomqwu commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

Continues Sprint 4 PR 4.6b (file-by-file revival of the tests/integration/ tier). Adds a production-endpoint integration file that drives /auth/forgot-password and /auth/reset-password over real HTTP against the session-scoped uvicorn api_server fixture. Sets DEBUG_RETURN_RESET_TOKEN=true at module import time (before pytest instantiates the session-scoped api_server fixture) so the raw reset token is returned in the JSON body and the full flow can be exercised end-to-end.

Coverage

tests/integration/test_password_reset.py — 7 tests covering:

  • POST /auth/forgot-password — known email 200 (with token when debug flag is on), unknown email 200 with identical shape (anti-enumeration), malformed email 422
  • POST /auth/reset-password — bogus token 400, empty token 400, full happy path (request → confirm → new password authenticates + old password 401), token single-use (second submission of the same token 400)

Validation

  • poetry run pytest tests/integration/test_password_reset.py -v — 7 passed
  • poetry run black tests/integration/test_password_reset.py — clean
  • poetry run ruff check tests/integration/test_password_reset.py — clean

No OpenAPI snapshot refresh (no endpoints added or changed).

Notes

  • The two happy-path tests guard against a hypothetical run order where the api_server fixture starts before DEBUG_RETURN_RESET_TOKEN is set: they pytest.skip rather than fail. That path never triggers today because pytest collects (imports) test files before starting the session fixture.
  • Unknown-email path asserts both "message" in body and "token" not in body — the second half is what actually forbids enumeration; the router must not leak "matched" via a differing shape.
  • The single-use assertion locks in the router's atomic UPDATE claim: a naive SELECT-then-UPDATE would let both requests succeed.

Follow-ups

Remaining routers still to revive under tests/integration/: assignments, analytics, calendar, solutions, solver, people, webhooks.


Generated by Claude Code

Summary: Continues PR 4.6b file-by-file revival of the integration tier.
Adds real-HTTP coverage for /api/v1/auth/{forgot,reset}-password over
the session-scoped uvicorn api_server. Uses DEBUG_RETURN_RESET_TOKEN
(set at test-module import time before api_server picks up the env) so
the raw reset token is exposed and the full request → confirm → old
password rejected flow can be exercised.

Changed files:
- tests/integration/test_password_reset.py (new) — 7 tests covering:
  - /forgot-password: known email 200, unknown email same generic
    shape (anti-enumeration), malformed email 422
  - /reset-password: bogus token 400, empty token 400, happy-path
    reset + new password authenticates + old password rejected,
    token single-use (second submission with the same token 400)

Validation:
- poetry run pytest tests/integration/test_password_reset.py -v — 7 passed
- poetry run black tests/integration/test_password_reset.py — clean
- poetry run ruff check tests/integration/test_password_reset.py — clean
- No OpenAPI snapshot refresh (no endpoints added or changed).

Follow-ups:
- Remaining integration files to revive: assignments, analytics,
  calendar, solutions, solver, people, webhooks.
@tomqwu
tomqwu marked this pull request as ready for review July 19, 2026 13:04
@tomqwu
tomqwu merged commit 2282687 into main Jul 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants