Skip to content

tests: cover NIP-55 approval-flow biometric failure + cancellation branches (Android) #396

Description

@kwsantiago

Follow-up split from #376 (parent #323).

#376's acceptance named three unhappy approval-flow branches: biometric failure, user cancellation, and kill-switch-active. The kill-switch branch is now covered by ApprovalFlowKillSwitchInstrumentedTest. The biometric-failure and user-cancellation branches are documented as out-of-scope in that suite rather than exercised; this issue tracks closing that gap.

Why deferred

The failure/cancellation decision logic lives inside anonymous BiometricPrompt.AuthenticationCallback objects constructed inline in BiometricHelper (authenticateWithResult / authenticateWithCrypto): onAuthenticationError maps to AuthResult.FAILED / LOCKOUT, and ERROR_USER_CANCELED / ERROR_NEGATIVE_BUTTON resume with null. BiometricPrompt is instantiated directly with no injected factory, and on the target devices biometric is BIOMETRIC_STRONG with no PIN fallback, so those callbacks are invoked only by the real hardware prompt. There is no non-UI seam to drive them, and no emulator biometric injection is available. Stubbing them into a hollow pass was rejected in favor of documenting the gap.

Work

Introduce a test seam so the biometric outcome can be driven deterministically without real hardware, then assert key use is gated on both branches:

  • Extract an injectable BiometricPrompt factory (or an interface around the authenticate call) in BiometricHelper so tests can supply a fake that invokes onAuthenticationError with FAILED / LOCKOUT and with ERROR_USER_CANCELED / ERROR_NEGATIVE_BUTTON.
  • Assert that on failure the approval flow does not sign: no signature emitted, result maps to the canceled/error contract.
  • Assert that on cancellation the flow resumes with null and maps to the canceled/rejected contract, never a signature.

Acceptance

  • The biometric-failure and user-cancellation branches are each exercised via a deterministic seam (no real-hardware dependency, no flakiness).
  • Each asserts key use is correctly gated (no signature, correct result mapping), matching the unhappy-path contract used by the sibling NIP-55 instrumented tests.

Mirrors the #389 precedent: a deferred branch tracked as a follow-up scoped around adding a deterministic test seam rather than a real-hardware dependency.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestnip55NIP-55 signer protocolp3Lowest Priority

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions