Add vitest harness + initial tests for auth-api#151
Merged
Conversation
auth-api had no test coverage. Mirrors the competition-api setup
(@cloudflare/vitest-pool-workers with D1 migrations applied in the test
pool). Adds root-level `bun run test:auth` and wires it into `test:all`.
Initial coverage (30 passing, 13 todo):
Tier 1 — security invariants
- CORS allowlist mirror of competition-api's SEC-01 test
- isLocalDev gate (SEC-07): localhost variants → true;
glidecomp.com, suffix attacks, 127.0.0.1 → false
- GET /api/auth/me returns { user: null } with no cookie and with
garbage cookie (does not 500)
- POST /set-username and POST /delete-account return 401 anonymously
- POST /dev-login handles missing fields, non-JSON body, and the
happy path (sets a session cookie)
Tiers 2-4 stubbed as test.todo(...) so they show up in the runner and
we track what's still to cover: full set-username format rules,
delete-account cascade, Google revocation failure, and apiKey plugin
round-trip / rate-limit. See the PR description for the full plan.
The full SEC-07 "dev-login 404 in production mode" integration test
would need a second vitest project to swap BETTER_AUTH_URL, so for
now we unit-test isLocalDev directly — that's the gate that matters.
https://claude.ai/code/session_01Tvuta7yC8Axf5iRQy7sjSX
The root `tsc --noEmit` walks the auth-api/test directory but doesn't have @cloudflare/vitest-pool-workers in its types, so it can't resolve the cloudflare:test module. Mirror the existing exclude for competition-api/test — the test directories have their own tsconfig that loads the right types. https://claude.ai/code/session_01Tvuta7yC8Axf5iRQy7sjSX
…t-harness # Conflicts: # bun.lock # package.json # tsconfig.json # web/workers/auth-api/package.json # web/workers/auth-api/test/apply-migrations.ts # web/workers/auth-api/test/helpers.ts # web/workers/auth-api/vitest.config.ts
The "two users do not see each other's preferences" test in preferences.test.ts:296 was timing out on CI runners with the default 5s. dev-login does a real signUp + signIn (Better Auth hashes a password) on every call; the multi-user test does this twice plus four round trips, which is fine locally but borderline on slower runners. 15s gives a safety margin without masking real perf regressions. Passed previously on master CI because test:all didn't include test:auth — this PR is the one wiring it in. https://claude.ai/code/session_01Tvuta7yC8Axf5iRQy7sjSX
|
Preview Deployment |
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.
Summary
auth-api had zero test coverage. This PR wires up a vitest harness (mirroring the competition-api setup) and adds Tier-1 security-invariant tests. Tiers 2–4 are stubbed as
test.todo(...)so they show up in the runner and nothing is silently missing.bun run test:authruns the new suitebun run test:allnow includes auth-apiAPI surface reviewed
use/api/auth/*GET/api/auth/me{ user: null }POST/api/auth/set-usernamePOST/api/auth/delete-accountPOST/api/auth/dev-loginall/api/auth/*What's in this PR (Tier 1)
isLocalDevunit tests (SEC-07) — localhost variants → true;glidecomp.com,localhost.evil.examplesuffix attack,127.0.0.1→ false.GET /api/auth/mereturns{ user: null }with no cookie and with a garbage cookie (does not 500).POST /set-username+POST /delete-accountreturn 401 anonymously.POST /dev-loginhappy-path test (sets a session cookie), plus empty-body and non-JSON body → 400.Proposed follow-up tests (Tier 2–4, stubbed as
test.todo)Tier 2 —
set-usernamevalidationab(2) → 400,abcdefghijklmnopqrstu(21) → 400." alice "stored as"alice".AND id != ?clause).Tier 3 —
delete-accountfetchfails (needs outbound fetch mocked).Tier 4 — Better Auth apiKey plugin
/mewithx-api-keyresolves to the owner./mecall.getSessionround-trip: sign up viadev-login, replaySet-Cookieon/me.Not planned
trustedOriginsCSRF enforcement inside Better Auth (covered upstream).BETTER_AUTH_URL. TheisLocalDevunit test covers the same property.Harness notes
vitest.config.tssupplies dummyBETTER_AUTH_SECRET,GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRETvia miniflare bindings. DefaultBETTER_AUTH_URLishttp://localhost:8788so dev-login is enabled.test/helpers.tshasclearAuthData(),seedUser(),devSignIn(),fetchWorker().test/apply-migrations.tsapplies D1 migrations once per pool.Test plan
bun run test:authpasses locally (30 passed, 13 todo)bun run typecheck:authpassestest.todoitems to graduate to real tests (separate PRs)https://claude.ai/code/session_01Tvuta7yC8Axf5iRQy7sjSX