Skip to content

test(browser): close mutation-testing coverage gaps in passkeys SDK#40

Merged
wolpert merged 1 commit into
mainfrom
test/browser-sdk-mutation-hardening
Jun 8, 2026
Merged

test(browser): close mutation-testing coverage gaps in passkeys SDK#40
wolpert merged 1 commit into
mainfrom
test/browser-sdk-mutation-hardening

Conversation

@wolpert

@wolpert wolpert commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What

Adds the missing test assertions that StrykerJS mutation testing — introduced by @bernata in #39 — flagged in the passkeys-browser SDK. The report scored 65.1% and pinpointed code that ran in tests but had no assertion pinning its behaviour, so a mutated version still passed. This closes those gaps.

Credit to @bernata for wiring up the tooling that surfaced these blind spots — line coverage hid them; mutation coverage did not.

Gaps closed (each new case kills a previously-surviving mutant)

  • results.ts had zero coverage (0% mutation score). New results.test.ts pins both branches of isCeremonySuccess / isCeremonyFailure and the success-narrowing path.
  • http.ts — assert the accept header is always sent; content-type/body are omitted on body-less requests; JSON null/primitive bodies leave PkAuthHttpError.data undefined (the && vs || object check); and an absent getToken yields the friendly validation error, not a raw TypeError.
  • refresh.ts — assert the negative branch of both type guards, the default /auth/refresh path, and that a non-JSON 401 body maps to "unknown" instead of throwing (the e.data?.detail optional-chaining branch).
  • admin.ts — cover the two previously-untested methods (completeEmailVerification, startPhoneVerification) and add a matrix asserting every admin call carries the Bearer token, so the authenticated flag can no longer be mutated to false undetected.

Intentionally left alone

A handful of remaining base64url survivors are equivalent mutants (out-of-bounds typed-array writes are ignored, atob is lenient, the padding-regex anchor is moot for btoa output) — no test can kill them without contrived inputs, so they're documented rather than chased.

Verification

  • All 67 browser-SDK tests pass (npx vitest run)
  • tsc --noEmit clean

🤖 Generated with Claude Code

StrykerJS mutation testing — added by Andrew Bernat (@bernata) in PR #39
(#39) — reported a 65.1%
mutation score for the browser SDK and pinpointed real test gaps that plain
line coverage hid: code that ran but had no assertion pinning its behaviour,
so a mutated version still passed. This adds the missing assertions.

Why this matters: these guards, header rules, and error-mapping branches are
the SDK's public contract with the server. A test that exercises them without
asserting on them gives false confidence — exactly what mutation testing
flags. Credit to Andrew for wiring up the tooling that surfaced these.

Gaps closed (each new case kills a previously-surviving mutant):
- results.ts: had ZERO coverage (0% score). New results.test.ts pins both
  branches of isCeremonySuccess / isCeremonyFailure and the success narrowing.
- http.ts: assert the `accept` header is always sent; content-type/body are
  omitted on body-less requests; JSON `null`/primitive bodies leave
  PkAuthHttpError.data undefined (the && vs || object check); and an absent
  getToken yields the friendly validation error, not a raw TypeError.
- refresh.ts: assert the negative branch of both type guards, the default
  /auth/refresh path, and that a non-JSON 401 body maps to "unknown" instead
  of throwing (the e.data?.detail optional-chaining branch).
- admin.ts: cover the two previously-untested methods
  (completeEmailVerification, startPhoneVerification) and add a matrix that
  asserts every admin call carries the Bearer token, so the `authenticated`
  flag can no longer be mutated to false undetected.

Note: a handful of remaining base64url survivors are equivalent mutants
(out-of-bounds typed-array writes are ignored, atob is lenient, the padding
regex anchor is moot for btoa output) and are intentionally left as-is.

All 67 browser-SDK tests pass; tsc --noEmit clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wolpert wolpert merged commit caf6974 into main Jun 8, 2026
3 checks passed
@wolpert wolpert deleted the test/browser-sdk-mutation-hardening branch June 8, 2026 14:19
wolpert added a commit that referenced this pull request Jun 8, 2026
…coverage

test(browser): cover the full ceremony flows (correcting a PR #40 oversight)
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.

1 participant