test(browser): close mutation-testing coverage gaps in passkeys SDK#40
Merged
Conversation
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
added a commit
that referenced
this pull request
Jun 8, 2026
…coverage test(browser): cover the full ceremony flows (correcting a PR #40 oversight)
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.
What
Adds the missing test assertions that StrykerJS mutation testing — introduced by @bernata in #39 — flagged in the
passkeys-browserSDK. 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.tshad zero coverage (0% mutation score). Newresults.test.tspins both branches ofisCeremonySuccess/isCeremonyFailureand the success-narrowing path.http.ts— assert theacceptheader is always sent; content-type/body are omitted on body-less requests; JSONnull/primitive bodies leavePkAuthHttpError.dataundefined (the&&vs||object check); and an absentgetTokenyields the friendly validation error, not a rawTypeError.refresh.ts— assert the negative branch of both type guards, the default/auth/refreshpath, and that a non-JSON 401 body maps to"unknown"instead of throwing (thee.data?.detailoptional-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 theauthenticatedflag can no longer be mutated tofalseundetected.Intentionally left alone
A handful of remaining
base64urlsurvivors are equivalent mutants (out-of-bounds typed-array writes are ignored,atobis lenient, the padding-regex anchor is moot forbtoaoutput) — no test can kill them without contrived inputs, so they're documented rather than chased.Verification
npx vitest run)tsc --noEmitclean🤖 Generated with Claude Code