Skip to content

Commit c881945

Browse files
committed
refactor(mfa): derive invalid-code error from state
1 parent 884788a commit c881945

4 files changed

Lines changed: 14 additions & 17 deletions

File tree

src/components/MultifactorAuthentication/machine/mfaMachine.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {CONST as COMMON_CONST} from 'expensify-common';
1414
import {assign, setup} from 'xstate';
1515

1616
import type {MfaMachineEvent} from './machineEvents';
17-
import type {MfaContext, MfaTag} from './types';
17+
import type {MfaContext} from './types';
1818

1919
import createActors from './mfaActors';
2020

@@ -56,7 +56,6 @@ const MFAMachine = setup({
5656
types: {
5757
context: {} as MfaContext,
5858
events: {} as MfaMachineEvent,
59-
tags: {} as MfaTag,
6059
},
6160
/* eslint-enable @typescript-eslint/no-unsafe-type-assertion */
6261
actors: createActors(),
@@ -238,7 +237,6 @@ const MFAMachine = setup({
238237
// (typing, a resend, a new submission) drops the error by
239238
// construction and nothing stale can outlive the screen.
240239
[MFA_STATE.INVALID_CODE]: {
241-
tags: 'showsInvalidCodeError',
242240
on: {
243241
VALIDATE_CODE_CHANGED: MFA_STATE.AWAITING_INPUT,
244242
},

src/components/MultifactorAuthentication/machine/snapshotToState.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ function snapshotToState(snapshot: MfaSnapshot): MfaState {
4141
...snapshot.context,
4242
modalState: getModalState(snapshot),
4343
canResendValidateCode: snapshot.can({type: 'RESEND_VALIDATE_CODE'}),
44-
showsInvalidCodeError: snapshot.hasTag('showsInvalidCodeError'),
44+
showsInvalidCodeError: snapshot.matches({
45+
[MFA_STATE.OPEN]: {
46+
[MFA_STATE.MAGIC_CODE]: {
47+
[MFA_STATE.AWAITING_VALIDATE_CODE]: MFA_STATE.INVALID_CODE,
48+
},
49+
},
50+
}),
4551
};
4652
}
4753

src/components/MultifactorAuthentication/machine/types.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,6 @@ type MfaEvent =
7474
| {type: 'RESEND_VALIDATE_CODE'}
7575
| {type: 'VALIDATE_CODE_CHANGED'};
7676

77-
/**
78-
* Tags the chart marks UI-facing conditions with. The view bridge reads them through `hasTag`
79-
* instead of matching a concrete state path, so a chart restructuring that moves the tagged state
80-
* does not break the bridge.
81-
*/
82-
type MfaTag = 'showsInvalidCodeError';
83-
8477
/** Describes the input the machine passes to the device-check actor. */
8578
type ValidateDeviceInput = {allowedAuthenticationMethods: AllowedAuthenticationMethods};
8679

@@ -101,7 +94,6 @@ export type {
10194
MfaContext,
10295
MfaEvent,
10396
MfaModalState,
104-
MfaTag,
10597
MultifactorAuthenticationInitEvent,
10698
ReadHasAcceptedSoftPromptInput,
10799
RequestRegistrationChallengeInput,

tests/unit/components/MultifactorAuthentication/machine/validateCodeTransition.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import mfaMachine from '@components/MultifactorAuthentication/machine/mfaMachine';
2+
import snapshotToState from '@components/MultifactorAuthentication/machine/snapshotToState';
23
import type {CheckLocalCredentialsInput, ValidateDeviceInput} from '@components/MultifactorAuthentication/machine/types';
34

45
import type {MFAResult} from '@libs/MultifactorAuthentication/shared/MFAResult';
@@ -123,7 +124,7 @@ describe('MFA magic code and registration decision', () => {
123124

124125
const result = actor.getSnapshot();
125126
expect(result.matches({[MFA_STATE.OPEN]: {[MFA_STATE.MAGIC_CODE]: {[MFA_STATE.AWAITING_VALIDATE_CODE]: MFA_STATE.AWAITING_INPUT}}})).toBe(true);
126-
expect(result.hasTag('showsInvalidCodeError')).toBe(false);
127+
expect(snapshotToState(result).showsInvalidCodeError).toBe(false);
127128
expect(requestValidateCodeActionMock).toHaveBeenCalledTimes(1);
128129

129130
actor.stop();
@@ -183,7 +184,7 @@ describe('MFA magic code and registration decision', () => {
183184

184185
const result = actor.getSnapshot();
185186
expect(result.matches({[MFA_STATE.OPEN]: {[MFA_STATE.MAGIC_CODE]: {[MFA_STATE.AWAITING_VALIDATE_CODE]: MFA_STATE.INVALID_CODE}}})).toBe(true);
186-
expect(result.hasTag('showsInvalidCodeError')).toBe(true);
187+
expect(snapshotToState(result).showsInvalidCodeError).toBe(true);
187188
expect(result.context.registrationChallenge).toBeUndefined();
188189
expect(result.context.error).toBeUndefined();
189190
expect(requestValidateCodeActionMock).not.toHaveBeenCalled();
@@ -198,14 +199,14 @@ describe('MFA magic code and registration decision', () => {
198199
actor.start();
199200
actor.send({type: 'VALIDATE_CODE_ENTERED', validateCode: MFA_TEST_VALIDATE_CODE});
200201
await waitForBatchedUpdates();
201-
expect(actor.getSnapshot().hasTag('showsInvalidCodeError')).toBe(true);
202+
expect(snapshotToState(actor.getSnapshot()).showsInvalidCodeError).toBe(true);
202203
actor.send({type: 'VALIDATE_CODE_ENTERED', validateCode: MFA_TEST_VALIDATE_CODE});
203204
await waitForBatchedUpdates();
204205

205206
const result = actor.getSnapshot();
206207
expect(result.context.registrationChallenge).toBe(MFA_TEST_REGISTRATION_CHALLENGE);
207208
expect(result.context.validateCode).toBe(MFA_TEST_VALIDATE_CODE);
208-
expect(result.hasTag('showsInvalidCodeError')).toBe(false);
209+
expect(snapshotToState(result).showsInvalidCodeError).toBe(false);
209210

210211
actor.stop();
211212
});
@@ -250,7 +251,7 @@ describe('MFA magic code and registration decision', () => {
250251

251252
const result = actor.getSnapshot();
252253
expect(result.matches({[MFA_STATE.OPEN]: {[MFA_STATE.MAGIC_CODE]: {[MFA_STATE.AWAITING_VALIDATE_CODE]: MFA_STATE.AWAITING_INPUT}}})).toBe(true);
253-
expect(result.hasTag('showsInvalidCodeError')).toBe(false);
254+
expect(snapshotToState(result).showsInvalidCodeError).toBe(false);
254255

255256
actor.stop();
256257
});

0 commit comments

Comments
 (0)