Skip to content

Commit

Permalink
fix: Update error handling (#679)
Browse files Browse the repository at this point in the history
* WIP

* chore: update error state handling to only user onError, added onFailure callback
  • Loading branch information
thaddmt authored Jan 9, 2023
1 parent c1eebb1 commit 08aa7a6
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const Instruction: React.FC<InstructionProps> = () => {
heading = translate('Server Issue');
break;
case LivenessErrorState.RUNTIME_ERROR:
case LivenessErrorState.FACE_DISTANCE_TIMEOUT:
case LivenessErrorState.FACE_DISTANCE_ERROR:
heading = translate('Client error');
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/helpers/liveness/liveness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ export const LivenessErrorStateStringMap: Record<LivenessErrorState, string> = {
[LivenessErrorState.TIMEOUT]: translate<string>(
'Face not detected within time limit. Try again and place face inside oval within 5 seconds.'
),
[LivenessErrorState.FACE_DISTANCE_TIMEOUT]: translate<string>(
[LivenessErrorState.FACE_DISTANCE_ERROR]: translate<string>(
'Movement detected. Try again and hold position during countdown.'
),
[LivenessErrorState.CAMERA_FRAMERATE_ERROR]: undefined,
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/i18n/dictionaries/liveness/defaultTexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const defaultTexts = {
LIVENESS_ERROR: 'Check encountered an error',
LIVENESS_TIMEOUT:
'Face not detected within time limit. Try again and place face inside oval within 5 seconds.',
LIVENESS_FACE_DISTANCE_TIMEOUT:
LIVENESS_FACE_DISTANCE_ERROR:
'Movement detected. Try again and hold position during countdown.',

LIVENESS_HINT_MULTIPLE_FACES_DETECTED: 'Multiple faces detected',
Expand Down
14 changes: 10 additions & 4 deletions packages/ui/src/machines/liveness/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ describe('Liveness Machine', () => {
onGetLivenessDetection: jest.fn(),
onError: jest.fn(),
onSuccess: jest.fn(),
onFailure: jest.fn(),
onUserCancel: jest.fn(),
onUserPermissionDenied: jest.fn(),
onUserTimeout: jest.fn(),
};

const mockVideoConstaints: MediaTrackConstraints = {
Expand Down Expand Up @@ -450,7 +450,7 @@ describe('Liveness Machine', () => {
expect(service.state.value).toEqual('timeout');
expect(service.state.context.errorState).toBe(LivenessErrorState.TIMEOUT);
await flushPromises();
expect(mockcomponentProps.onUserTimeout).toHaveBeenCalledTimes(1);
expect(mockcomponentProps.onError).toHaveBeenCalledTimes(1);
});

it('should reach ovalMatching state after detectInitialFaceAndDrawOval success and respect ovalMatchingTimeout', async () => {
Expand All @@ -475,7 +475,7 @@ describe('Liveness Machine', () => {
expect(service.state.value).toEqual('timeout');
expect(service.state.context.errorState).toBe(LivenessErrorState.TIMEOUT);
await flushPromises();
expect(mockcomponentProps.onUserTimeout).toHaveBeenCalledTimes(1);
expect(mockcomponentProps.onError).toHaveBeenCalledTimes(1);
});

it('should reach checkFaceDetected again if no face is detected', async () => {
Expand Down Expand Up @@ -693,7 +693,7 @@ describe('Liveness Machine', () => {
LivenessErrorState.SERVER_ERROR
);
await flushPromises();
expect(mockcomponentProps.onUserTimeout).toHaveBeenCalledTimes(1);
expect(mockcomponentProps.onError).toHaveBeenCalledTimes(1);
});

it('should reach checkSucceeded state after getLivenessResult', async () => {
Expand All @@ -719,6 +719,9 @@ describe('Liveness Machine', () => {
expect(
mockcomponentProps.onGetLivenessDetection as jest.Mock
).toHaveBeenCalledTimes(1);
expect(mockcomponentProps.onSuccess as jest.Mock).toHaveBeenCalledTimes(
1
);
});

it('should reach checkFailed state after getLivenessResult returns false', async () => {
Expand All @@ -739,6 +742,9 @@ describe('Liveness Machine', () => {
expect(
mockcomponentProps.onGetLivenessDetection as jest.Mock
).toHaveBeenCalledTimes(1);
expect(mockcomponentProps.onFailure as jest.Mock).toHaveBeenCalledTimes(
1
);
});

it('should reach error state after getLiveness returns error', async () => {
Expand Down
26 changes: 20 additions & 6 deletions packages/ui/src/machines/liveness/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import {
FreshnessColorDisplay,
} from '../../helpers';
import { v4 } from 'uuid';
import { getStaticLivenessOvalDetails } from '../../helpers/liveness/liveness';
import {
getStaticLivenessOvalDetails,
LivenessErrorStateStringMap,
} from '../../helpers/liveness/liveness';
import {
isThrottlingExceptionEvent,
isServiceQuotaExceededExceptionEvent,
Expand Down Expand Up @@ -398,7 +401,9 @@ export const livenessMachine = createMachine<LivenessContext, LivenessEvent>(
'cancelOvalMatchTimeout',
],
},
checkFailed: {},
checkFailed: {
entry: 'callFailureCallback',
},
checkSucceeded: {
entry: 'callSuccessCallback',
},
Expand Down Expand Up @@ -669,7 +674,7 @@ export const livenessMachine = createMachine<LivenessContext, LivenessEvent>(
sendTimeoutAfterFaceDistanceDelay: actions.send(
{
type: 'TIMEOUT',
data: { errorState: LivenessErrorState.FACE_DISTANCE_TIMEOUT },
data: { errorState: LivenessErrorState.FACE_DISTANCE_ERROR },
},
{
delay: 0,
Expand Down Expand Up @@ -707,13 +712,21 @@ export const livenessMachine = createMachine<LivenessContext, LivenessEvent>(
attributes: { action: 'FailedWithTimeout' },
metrics: { count: 1 },
});
context.componentProps.onUserTimeout?.();
const error = new Error(
LivenessErrorStateStringMap[context.errorState]
);
error.name = context.errorState;
context.componentProps.onError?.(error);
},
callSuccessCallback: (context) => {
context.componentProps.onSuccess?.();
},
callFailureCallback: (context) => {
context.componentProps.onFailure?.();
},
callErrorCallback: async (context, event) => {
context.componentProps.onError?.(event.data as Error);
const error = event.data as Error;
context.componentProps.onError?.(error);
},
cleanUpResources: async (context) => {
const {
Expand Down Expand Up @@ -1230,9 +1243,10 @@ const responseStreamActor = async (callback) => {
});
}
}
} catch (e) {
} catch (error) {
callback({
type: 'SERVER_ERROR',
data: { ...error },
});
}
};
12 changes: 6 additions & 6 deletions packages/ui/src/types/liveness/liveness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ export interface FaceLivenessDetectorProps {
*/
onUserPermissionDenied?: (error: Error) => void;

/**
* Callback called when the flow times out after retry attempts
*/
onUserTimeout?: () => void;

/**
* Callback called when the user cancels the flow
*/
Expand All @@ -41,6 +36,11 @@ export interface FaceLivenessDetectorProps {
*/
onSuccess?: () => void;

/**
* Callback called when the flow completes unsuccessfully
*/
onFailure?: () => void;

/**
* Enable analytical events for the flow via Amplify Analytics
* NOTE: The Amplify Analytics category needs to be configured for this to work
Expand Down Expand Up @@ -116,5 +116,5 @@ export enum LivenessErrorState {
SERVER_ERROR = 'SERVER_ERROR',
CAMERA_FRAMERATE_ERROR = 'CAMERA_FRAMERATE_ERROR',
CAMERA_ACCESS_ERROR = 'CAMERA_ACCESS_ERROR',
FACE_DISTANCE_TIMEOUT = 'FACE_DISTANCE_TIMEOUT',
FACE_DISTANCE_ERROR = 'FACE_DISTANCE_ERROR',
}

0 comments on commit 08aa7a6

Please sign in to comment.