Skip to content

Commit

Permalink
chore: move default error components to separate components (#680)
Browse files Browse the repository at this point in the history
* chore: move default error components to separate components

* chore: update unit tests

* fix: remove unused variable
  • Loading branch information
thaddmt authored Jan 11, 2023
1 parent 08aa7a6 commit 0da2250
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 71 deletions.
51 changes: 43 additions & 8 deletions examples/liveness-next/pages/components/LivenessDefault.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useState } from 'react';
import {
FaceLivenessDetector,
View,
Flex,
Loader,
Icon,
Text,
FaceLivenessErrorModal,
FaceLivenessFailureModal,
} from '@aws-amplify/ui-react';
import { useLiveness } from './useLiveness';
import { SessionIdAlert } from './SessionIdAlert';
Expand All @@ -25,6 +28,9 @@ export default function LivenessDefault({
stopLiveness,
} = useLiveness();

const [error, setError] = useState(undefined);
const [checkFailed, setCheckFailed] = useState(false);

if (createLivenessSessionApiError) {
return <div>Some error occured...</div>;
}
Expand Down Expand Up @@ -54,14 +60,43 @@ export default function LivenessDefault({
<LivenessLogo />
</Icon>

<FaceLivenessDetector
sessionId={createLivenessSessionApiData.sessionId}
onUserCancel={stopLiveness}
onGetLivenessDetection={handleGetLivenessDetection}
enableAnalytics={true}
disableStartScreen={disableStartScreen}
components={components}
/>
<Flex direction="column" position="relative">
<FaceLivenessDetector
sessionId={createLivenessSessionApiData.sessionId}
onUserCancel={stopLiveness}
onGetLivenessDetection={handleGetLivenessDetection}
onError={(error) => {
setError(error);
}}
onFailure={() => {
setCheckFailed(true);
}}
enableAnalytics={true}
disableStartScreen={disableStartScreen}
components={components}
/>
{error ? (
<View style={{ zIndex: '1' }}>
<FaceLivenessErrorModal
error={error}
onRetry={() => {
setError(undefined);
stopLiveness();
}}
/>
</View>
) : null}
{checkFailed ? (
<View style={{ zIndex: '1' }}>
<FaceLivenessFailureModal
onRetry={() => {
setCheckFailed(false);
stopLiveness();
}}
/>
</View>
) : null}
</Flex>

<GetLivenessResultCard getLivenessResponse={getLivenessResponse} />
</Flex>
Expand Down
2 changes: 2 additions & 0 deletions packages/react/__tests__/__snapshots__/exports.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Array [
"Expander",
"ExpanderItem",
"FaceLivenessDetector",
"FaceLivenessErrorModal",
"FaceLivenessFailureModal",
"FieldGroupIcon",
"FieldGroupIconButton",
"FileUploader",
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/components/Liveness/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './FaceLivenessDetector';
export * from './shared/FaceLivenessErrorModal';
export * from './shared/FaceLivenessFailureModal';
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import {
translate,
LivenessErrorState,
LivenessErrorStateStringMap,
} from '@aws-amplify/ui';

import { Toast } from './Toast';
import { Overlay } from './Overlay';
import { Flex, Button } from '../../../primitives';

export interface FaceLivenessErrorModalProps {
error: Error;
onRetry: () => void;
}

export const FaceLivenessErrorModal: React.FC<FaceLivenessErrorModalProps> = (
props
) => {
const { error, onRetry } = props;
const { name: errorState } = error;

let heading: string = null;

switch (errorState) {
case LivenessErrorState.TIMEOUT:
heading = translate('Time out');
break;
case LivenessErrorState.SERVER_ERROR:
heading = translate('Server Issue');
break;
case LivenessErrorState.RUNTIME_ERROR:
case LivenessErrorState.FACE_DISTANCE_ERROR:
heading = translate('Client error');
break;
default:
heading = null;
}

return (
<Overlay backgroundColor="overlay.40">
<Toast heading={heading} variation="error">
{errorState && LivenessErrorStateStringMap[errorState]}
<Flex justifyContent="center">
<Button variation="primary" type="button" onClick={onRetry}>
{translate('Try again')}
</Button>
</Flex>
</Toast>
</Overlay>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from 'react';
import { translate } from '@aws-amplify/ui';

import { Toast } from './Toast';
import { Overlay } from './Overlay';
import { Flex, Button } from '../../../primitives';

export interface FaceLivenessFailureModalProps {
onRetry: () => void;
}

export const FaceLivenessFailureModal: React.FC<FaceLivenessFailureModalProps> =
(props) => {
const { onRetry } = props;

return (
<Overlay backgroundColor="overlay.40">
<Toast heading={translate('Check unsuccessful')} variation="error">
<Flex justifyContent="center">
<Button variation="primary" type="button" onClick={onRetry}>
{translate('Try again')}
</Button>
</Flex>
</Toast>
</Overlay>
);
};
44 changes: 3 additions & 41 deletions packages/react/src/components/Liveness/shared/Instruction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import {
IlluminationState,
IlluminationStateStringMap,
FaceMatchStateStringMap,
LivenessErrorState,
LivenessErrorStateStringMap,
} from '@aws-amplify/ui';

import {
Expand All @@ -15,7 +13,7 @@ import {
} from '../hooks';
import { Toast } from './Toast';
import { Overlay } from './Overlay';
import { Flex, Loader, View, Button } from '../../../primitives';
import { Flex, Loader, View } from '../../../primitives';

export const selectErrorState = createLivenessSelector(
(state) => state.context.errorState
Expand All @@ -36,7 +34,7 @@ export const selectOnuserCancel = createLivenessSelector(
export interface InstructionProps {}

export const Instruction: React.FC<InstructionProps> = () => {
const [state, send] = useLivenessActor();
const [state] = useLivenessActor();

// NOTE: Do not change order of these selectors as the unit tests depend on this order
const errorState = useLivenessSelector(selectErrorState);
Expand All @@ -62,43 +60,7 @@ export const Instruction: React.FC<InstructionProps> = () => {

const getInstructionContent = () => {
if (errorState || isCheckFailed) {
let heading: string = null;

switch (errorState) {
case LivenessErrorState.TIMEOUT:
heading = translate('Time out');
break;
case LivenessErrorState.SERVER_ERROR:
heading = translate('Server Issue');
break;
case LivenessErrorState.RUNTIME_ERROR:
case LivenessErrorState.FACE_DISTANCE_ERROR:
heading = translate('Client error');
break;
default:
heading = isCheckFailed ? translate('Check unsuccessful') : null;
}

return (
<Overlay backgroundColor="overlay.40">
<Toast heading={heading} variation="error">
{errorState && LivenessErrorStateStringMap[errorState]}
<Flex justifyContent="center">
<Button
variation="primary"
type="button"
onClick={() => {
send({
type: 'CANCEL',
});
}}
>
{translate('Try again')}
</Button>
</Flex>
</Toast>
</Overlay>
);
return;
}

if (isCheckFaceDetectedBeforeStart) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';

import { FaceLivenessErrorModal } from '../FaceLivenessErrorModal';
import {
LivenessErrorState,
LivenessErrorStateStringMap,
} from '@aws-amplify/ui';

describe('FaceLivenessErrorModal', () => {
it('should render the component content appropriately', () => {
const error = new Error();
error.name = LivenessErrorState.SERVER_ERROR;
render(<FaceLivenessErrorModal error={error} onRetry={() => {}} />);

expect(
screen.getByText(
LivenessErrorStateStringMap[LivenessErrorState.SERVER_ERROR]
)
).toBeInTheDocument();
});

it('should render the timeout message appropriately', () => {
const error = new Error();
error.name = LivenessErrorState.TIMEOUT;
render(<FaceLivenessErrorModal error={error} onRetry={() => {}} />);

expect(
screen.getByText(LivenessErrorStateStringMap[LivenessErrorState.TIMEOUT])
).toBeInTheDocument();
});

it('should render the runtime error message appropriately', () => {
const error = new Error();
error.name = LivenessErrorState.RUNTIME_ERROR;
render(<FaceLivenessErrorModal error={error} onRetry={() => {}} />);

expect(
screen.getByText(
LivenessErrorStateStringMap[LivenessErrorState.RUNTIME_ERROR]
)
).toBeInTheDocument();
});

it('should render the timeout message appropriately', () => {
const error = new Error();
error.name = LivenessErrorState.TIMEOUT;
render(<FaceLivenessErrorModal error={error} onRetry={() => {}} />);

expect(
screen.getByText(LivenessErrorStateStringMap[LivenessErrorState.TIMEOUT])
).toBeInTheDocument();
});

it('should render the null error type message appropriately', () => {
const error = new Error();
render(<FaceLivenessErrorModal error={error} onRetry={() => {}} />);

expect(screen.getByText('Try again')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';

import { FaceLivenessFailureModal } from '../FaceLivenessFailureModal';

describe('FaceLivenessFailureModal', () => {
it('should render the component content appropriately', () => {
render(<FaceLivenessFailureModal onRetry={() => {}} />);

expect(screen.getByText('Check unsuccessful')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,6 @@ describe('Instruction', () => {
resetAllWhenMocks();
});

it('should render errorState if present', () => {
errorState = LivenessErrorState.RUNTIME_ERROR;
mockStateMatchesAndSelectors();

renderWithLivenessProvider(<Instruction />);

expect(
screen.getByText(
LivenessErrorStateStringMap[LivenessErrorState.RUNTIME_ERROR]
)
).toBeInTheDocument();
});

it('should render check failed state if present', () => {
isCheckFailed = true;
mockStateMatchesAndSelectors();

renderWithLivenessProvider(<Instruction />);

expect(screen.getByText('Check unsuccessful')).toBeInTheDocument();
});

it('should render not recording state if present', () => {
isNotRecording = true;
mockStateMatchesAndSelectors();
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/machines/liveness/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ export const livenessMachine = createMachine<LivenessContext, LivenessEvent>(
'cancelOvalDrawingTimeout',
'cancelWaitForDisconnectTimeout',
'cancelOvalMatchTimeout',
'freezeStream',
],
},
checkFailed: {
Expand Down

0 comments on commit 0da2250

Please sign in to comment.