[PM-27134] feat: Add Register Passkey screen to TestHarness - #2946
[PM-27134] feat: Add Register Passkey screen to TestHarness#2946morganzellers-bw wants to merge 4 commits into
Conversation
🤖 Bitwarden Claude Code ReviewOverall Assessment: APPROVE Reviewed the new "Register Passkey" TestHarness screen (Action/Effect/State/Processor/View plus processor tests), its wiring into Code Review Details
PR Metadata Assessment
|
a989b44 to
290508f
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## pm-40519-testharness-passkeys-sdk-foundation #2946 +/- ##
================================================================================
- Coverage 79.54% 79.53% -0.01%
================================================================================
Files 1169 1169
Lines 75095 75095
================================================================================
- Hits 59732 59730 -2
- Misses 15363 15365 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
290508f to
fbbcc0c
Compare
fbbcc0c to
06ae2bb
Compare
06ae2bb to
63a2611
Compare
63a2611 to
3835795
Compare
3835795 to
c0911cd
Compare
c0911cd to
bcaf088
Compare
bcaf088 to
3d55e64
Compare
548c7e3 to
eca9f12
Compare
dd97b1d to
9ef86d8
Compare
9ef86d8 to
0f5816e
Compare
0f5816e to
63f2af4
Compare
63f2af4 to
d271a67
Compare
d271a67 to
3863d3b
Compare
3863d3b to
494041a
Compare
494041a to
ecc8ae3
Compare
ecc8ae3 to
e29a4aa
Compare
| override func receive(_ action: RegisterPasskeyAction) { | ||
| switch action { | ||
| case let .displayNameChanged(newValue): | ||
| state.displayName = newValue | ||
| state.status = .idle | ||
| case let .rpIdChanged(newValue): | ||
| state.rpId = newValue | ||
| state.status = .idle | ||
| case let .userNameChanged(newValue): | ||
| state.userName = newValue | ||
| state.status = .idle | ||
| } | ||
| } |
There was a problem hiding this comment.
🎨 SUGGESTED: Editing a field while a registration is in flight resets status to .idle, re-enabling the register button.
Details and fix
The text fields stay editable during registration (only the button is .disabled), so typing mid-flight sets status back to .idle. That hides the ProgressView and re-enables the Register button (RegisterPasskeyView.swift:83), which lets a second concurrent registerPasskey run and register a duplicate credential for the same RP — later ambiguous for assertPasskey(credentialId: nil, rpId:).
Guarding the reset keeps the in-progress state authoritative:
| override func receive(_ action: RegisterPasskeyAction) { | |
| switch action { | |
| case let .displayNameChanged(newValue): | |
| state.displayName = newValue | |
| state.status = .idle | |
| case let .rpIdChanged(newValue): | |
| state.rpId = newValue | |
| state.status = .idle | |
| case let .userNameChanged(newValue): | |
| state.userName = newValue | |
| state.status = .idle | |
| } | |
| } | |
| override func receive(_ action: RegisterPasskeyAction) { | |
| switch action { | |
| case let .displayNameChanged(newValue): | |
| state.displayName = newValue | |
| case let .rpIdChanged(newValue): | |
| state.rpId = newValue | |
| case let .userNameChanged(newValue): | |
| state.userName = newValue | |
| } | |
| if state.status != .inProgress { | |
| state.status = .idle | |
| } | |
| } |
e29a4aa to
c27001f
Compare
c27001f to
ab70204
Compare
ab70204 to
612b7f9
Compare
Adds the "Register Passkey" scenario: a form for relying party ID, username, and display name that calls PasskeyService.registerPasskey directly, showing the resulting credential ID and attestation object. Wires it into the scenario picker and root navigation. Also drops the dead "Passkey Autofill" scenario stub (route: nil, already unused) and adds a missing accessibility identifier case for the TOTP scenario button while touching this file.
612b7f9 to
2bd6942
Compare
🎟️ Tracking
PM-27134
📔 Objective
Third PR in a 5-PR stack adding SDK-backed passkey test scenarios to TestHarness. Stacked on #2945.
SDKPasskeyService.registerPasskeydirectly, showing the resulting credential ID and attestation object.route: nil, already unused) and adds a missing accessibility identifier case for the TOTP scenario button, since this PR was already touching those files.📸 Screenshots
Stack: #2945 → #2946 → #2947 → #2948