allow upload options if user is in experiment

allow upload options if user is in experiment

testing

removed unused import

fixed unit test and corrected button text

combined assignment line for values coming from context

fixed error in message

added testing for photo mode panel

restructured

added checks for portrait and ID panels

removed unused import, added checks for reroutes

added tests and corrected messages

fix
This commit is contained in:
Alie Langston
2021-03-19 08:58:14 -04:00
parent 82170f383f
commit 6094509679
14 changed files with 572 additions and 18 deletions

View File

@@ -0,0 +1,66 @@
import React, { useContext } from 'react';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Button, Collapsible } from '@edx/paragon';
import { Link } from 'react-router-dom';
import PropTypes from 'prop-types';
import IdVerificationContext, { MEDIA_ACCESS } from './IdVerificationContext';
import messages from './IdVerification.messages';
function CollapsibleImageHelp(props) {
const {
shouldUseCamera, setShouldUseCamera, optimizelyExperimentName, mediaAccess,
} = useContext(IdVerificationContext);
function handleClick() {
setShouldUseCamera(!shouldUseCamera);
}
if (optimizelyExperimentName && mediaAccess !== MEDIA_ACCESS.DENIED && mediaAccess !== MEDIA_ACCESS.UNSUPPORTED) {
return (
<Collapsible
styling="card"
title={shouldUseCamera ? props.intl.formatMessage(messages['id.verification.photo.upload.help.title']) : props.intl.formatMessage(messages['id.verification.photo.camera.help.title'])}
className="mb-4 shadow"
defaultOpen
>
<p data-testid="help-text">
{shouldUseCamera
? props.intl.formatMessage(messages['id.verification.photo.upload.help.text'])
: props.intl.formatMessage(messages['id.verification.photo.camera.help.text'])}
</p>
{ (mediaAccess === MEDIA_ACCESS.PENDING && !shouldUseCamera)
? (
// if a user has not enabled camera access yet, and they are trying to switch
// to camera mode, direct them to panel that requests camera access
<Link
to={{ pathname: 'request-camera-access', state: { fromPortraitCapture: props.isPortrait, fromIdCapture: !props.isPortrait } }}
className="btn btn-primary"
data-testid="access-link"
>
{props.intl.formatMessage(messages['id.verification.photo.camera.help.button'])}
</Link>
)
: (
<Button
title={shouldUseCamera ? 'Upload Portrait Photo' : 'Take Portrait Photo'}
data-testid="toggle-button"
onClick={handleClick}
style={{ marginTop: '0.5rem' }}
>
{shouldUseCamera ? props.intl.formatMessage(messages['id.verification.photo.upload.help.button']) : props.intl.formatMessage(messages['id.verification.photo.camera.help.button'])}
</Button>
)}
</Collapsible>
);
}
return null;
}
CollapsibleImageHelp.propTypes = {
intl: intlShape.isRequired,
isPortrait: PropTypes.bool.isRequired,
};
export default injectIntl(CollapsibleImageHelp);

View File

@@ -641,6 +641,56 @@ const messages = defineMessages({
defaultMessage: 'Return to Course',
description: 'Return to the course which ID verification was accessed from.',
},
'id.verification.photo.upload.help.title': {
id: 'id.verification.photo.upload.help.title',
defaultMessage: 'Upload a Photo Instead',
description: 'Title for section that allows switching to photo upload mode.',
},
'id.verification.photo.camera.help.title': {
id: 'id.verification.photo.camera.help.title',
defaultMessage: 'Use Your Camera Instead',
description: 'Title for section that allows switching to camera mode.',
},
'id.verification.photo.upload.help.text': {
id: 'id.verification.photo.upload.help.text',
defaultMessage: 'If you are having trouble using the photo capture above, you may want to upload a photo instead. To upload a photo, click the button below.',
description: 'Help text for switching to upload mode.',
},
'id.verification.photo.camera.help.text': {
id: 'id.verification.photo.camera.help.text',
defaultMessage: 'If you are having trouble uploading a photo above, you may want to use your camera instead. To use your camera, click the button below.',
description: 'Help text for switching to camera mode.',
},
'id.verification.photo.upload.help.button': {
id: 'id.verification.upload.help.button',
defaultMessage: 'Switch to Upload Mode',
description: 'Button used to switch to upload mode.',
},
'id.verification.photo.camera.help.button': {
id: 'id.verification.camera.help.button',
defaultMessage: 'Switch to Camera Mode',
description: 'Button used to switch to camera mode.',
},
'id.verification.choose.mode.title': {
id: 'id.verification.choose.mode.title',
defaultMessage: 'Photo Requirements Options',
description: 'Title for section that allows user to choose photo mode.',
},
'id.verification.choose.mode.help.text': {
id: 'id.verification.choose.mode.hep.text',
defaultMessage: 'To complete verification, please select one of the following options to submit photos. You will be able to switch between these options throughout the process if needed.',
description: 'Help text for section that allows user to choose photo mode.',
},
'id.verification.choose.mode.radio.upload': {
id: 'id.verification.choose.mode.radio.upload',
defaultMessage: 'Upload photos from my device',
description: 'Radio button to choose to upload photos.',
},
'id.verification.choose.mode.radio.camera': {
id: 'id.verification.choose.mode.radio.camera',
defaultMessage: 'Take pictures using my camera',
description: 'Radio button to choose to use camera for photos.',
},
});
export default messages;

View File

@@ -77,6 +77,7 @@ export default function IdVerificationContextProvider({ children }) {
}, [authenticatedUser]);
const [optimizelyExperimentName, setOptimizelyExperimentName] = useState('');
const [shouldUseCamera, setShouldUseCamera] = useState(false);
const contextValue = {
existingIdVerification,
@@ -89,16 +90,19 @@ export default function IdVerificationContextProvider({ children }) {
nameOnAccount: authenticatedUser.name,
profileDataManager,
optimizelyExperimentName,
shouldUseCamera,
setExistingIdVerification,
setFacePhotoFile,
setIdPhotoFile,
setIdPhotoName,
setOptimizelyExperimentName,
setShouldUseCamera,
tryGetUserMedia: async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
setMediaAccess(MEDIA_ACCESS.GRANTED);
setMediaStream(stream);
setShouldUseCamera(true);
// stop the stream, as we are not using it yet
const tracks = stream.getTracks();
tracks.forEach(track => track.stop());

View File

@@ -11,6 +11,7 @@ import './getUserMediaShim';
import IdVerificationContextProvider from './IdVerificationContextProvider';
import ReviewRequirementsPanel from './panels/ReviewRequirementsPanel';
import ChooseModePanel from './panels/ChooseModePanel';
import RequestCameraAccessPanel from './panels/RequestCameraAccessPanel';
import PortraitPhotoContextPanel from './panels/PortraitPhotoContextPanel';
import TakePortraitPhotoPanel from './panels/TakePortraitPhotoPanel';
@@ -52,6 +53,7 @@ function IdVerificationPage(props) {
<IdVerificationContextProvider>
<Switch>
<Route path={`${path}/review-requirements`} component={ReviewRequirementsPanel} />
<Route path={`${path}/choose-mode`} component={ChooseModePanel} />
<Route path={`${path}/request-camera-access`} component={RequestCameraAccessPanel} />
<Route path={`${path}/portrait-photo-context`} component={PortraitPhotoContextPanel} />
<Route path={`${path}/take-portrait-photo`} component={TakePortraitPhotoPanel} />

View File

@@ -27,7 +27,7 @@ export default function ImageFileUpload({ onFileChange, intl }) {
<>
<input
type="file"
accept="image/*"
accept=".png, .jpg, .jpeg"
data-testid="fileUpload"
onChange={handleChange}
/>

View File

@@ -0,0 +1,60 @@
import React, { useContext } from 'react';
import { Link } from 'react-router-dom';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Form } from '@edx/paragon';
import { useNextPanelSlug } from '../routing-utilities';
import BasePanel from './BasePanel';
import IdVerificationContext from '../IdVerificationContext';
import messages from '../IdVerification.messages';
function ChooseModePanel(props) {
const panelSlug = 'choose-mode';
const { shouldUseCamera, setShouldUseCamera } = useContext(IdVerificationContext);
function onPhotoModeChange(value) {
setShouldUseCamera(value);
}
return (
<BasePanel
name={panelSlug}
title={props.intl.formatMessage(messages['id.verification.choose.mode.title'])}
>
<p>
{props.intl.formatMessage(messages['id.verification.choose.mode.help.text'])}
</p>
<fieldset>
<Form.Group controlId="formChoosePhotoOption" style={{ marginLeft: '1.25rem' }}>
<Form.Check
type="radio"
id="useUploadMode"
label={props.intl.formatMessage(messages['id.verification.choose.mode.radio.upload'])}
name="photoMode"
checked={!shouldUseCamera}
onChange={() => onPhotoModeChange(false)}
/>
<Form.Check
type="radio"
id="useCameraMode"
label={props.intl.formatMessage(messages['id.verification.choose.mode.radio.camera'])}
name="photoMode"
checked={shouldUseCamera}
onChange={() => onPhotoModeChange(true)}
/>
</Form.Group>
</fieldset>
<div className="action-row">
<Link to={useNextPanelSlug(panelSlug)} className="btn btn-primary" data-testid="next-button">
{props.intl.formatMessage(messages['id.verification.next'])}
</Link>
</div>
</BasePanel>
);
}
ChooseModePanel.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(ChooseModePanel);

View File

@@ -9,24 +9,43 @@ import IdVerificationContext from '../IdVerificationContext';
import messages from '../IdVerification.messages';
import CameraHelp from '../CameraHelp';
import ImagePreview from '../ImagePreview';
import ImageFileUpload from '../ImageFileUpload';
import CollapsibleImageHelp from '../CollapsibleImageHelp';
function TakeIdPhotoPanel(props) {
const panelSlug = 'take-id-photo';
const nextPanelSlug = useNextPanelSlug(panelSlug);
const { setIdPhotoFile, idPhotoFile } = useContext(IdVerificationContext);
const {
setIdPhotoFile, idPhotoFile, optimizelyExperimentName, shouldUseCamera,
} = useContext(IdVerificationContext);
return (
<BasePanel
name={panelSlug}
title={props.intl.formatMessage(messages['id.verification.id.photo.title.camera'])}
title={shouldUseCamera ? props.intl.formatMessage(messages['id.verification.id.photo.title.camera']) : props.intl.formatMessage(messages['id.verification.id.photo.title.upload'])}
>
<div>
<p>
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.camera'])}
</p>
<Camera onImageCapture={setIdPhotoFile} isPortrait={false} />
{idPhotoFile && !shouldUseCamera && <ImagePreview src={idPhotoFile} alt={props.intl.formatMessage(messages['id.verification.id.photo.preview.alt'])} />}
{shouldUseCamera ? (
<div>
<p>
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.camera'])}
</p>
<Camera onImageCapture={setIdPhotoFile} isPortrait={false} />
</div>
) : (
<div style={{ marginBottom: '1.25rem' }}>
<p data-testid="upload-text">
{props.intl.formatMessage(messages['id.verification.id.photo.instructions.upload'])}
</p>
<ImageFileUpload onFileChange={setIdPhotoFile} intl={props.intl} />
</div>
)}
</div>
<CameraHelp />
{shouldUseCamera && !optimizelyExperimentName && <CameraHelp />}
<CollapsibleImageHelp isPortrait={false} />
<div className="action-row" style={{ visibility: idPhotoFile ? 'unset' : 'hidden' }}>
<Link to={nextPanelSlug} className="btn btn-primary" data-testid="next-button">
{props.intl.formatMessage(messages['id.verification.next'])}

View File

@@ -11,14 +11,14 @@ import CameraHelp from '../CameraHelp';
import IdVerificationContext from '../IdVerificationContext';
import messages from '../IdVerification.messages';
import CollapsibleImageHelp from '../CollapsibleImageHelp';
function TakePortraitPhotoPanel(props) {
const panelSlug = 'take-portrait-photo';
const nextPanelSlug = useNextPanelSlug(panelSlug);
const { setFacePhotoFile, facePhotoFile } = useContext(IdVerificationContext);
const shouldUseCamera = true;
// to reenable upload component:
// const shouldUseCamera = mediaAccess === MEDIA_ACCESS.GRANTED;
const {
setFacePhotoFile, facePhotoFile, shouldUseCamera, optimizelyExperimentName,
} = useContext(IdVerificationContext);
return (
<BasePanel
@@ -36,15 +36,16 @@ function TakePortraitPhotoPanel(props) {
<Camera onImageCapture={setFacePhotoFile} isPortrait />
</div>
) : (
<div>
<p>
<div style={{ marginBottom: '1.25rem' }}>
<p data-testid="upload-text">
{props.intl.formatMessage(messages['id.verification.portrait.photo.instructions.upload'])}
</p>
<ImageFileUpload onFileChange={setFacePhotoFile} />
<ImageFileUpload onFileChange={setFacePhotoFile} intl={props.intl} />
</div>
)}
</div>
{shouldUseCamera && <CameraHelp isPortrait />}
{shouldUseCamera && !optimizelyExperimentName && <CameraHelp isPortrait />}
<CollapsibleImageHelp isPortrait />
<div className="action-row" style={{ visibility: facePhotoFile ? 'unset' : 'hidden' }}>
<Link to={nextPanelSlug} className="btn btn-primary" data-testid="next-button">
{props.intl.formatMessage(messages['id.verification.next'])}

View File

@@ -4,6 +4,7 @@ import IdVerificationContext from './IdVerificationContext';
const panelSteps = [
'review-requirements',
'choose-mode',
'request-camera-access',
'portrait-photo-context',
'take-portrait-photo',
@@ -19,9 +20,28 @@ export const useNextPanelSlug = (originSlug) => {
// Go back to the summary view if that's where they came from
const location = useLocation();
const isFromSummary = location.state && location.state.fromSummary;
const isFromPortrait = location.state && location.state.fromPortraitCapture;
const isFromId = location.state && location.state.fromIdCapture;
const { shouldUseCamera, optimizelyExperimentName } = useContext(IdVerificationContext);
if (isFromSummary) {
return 'summary';
}
if (isFromPortrait) {
return 'portrait-photo-context';
}
if (isFromId) {
return 'id-context';
}
if (originSlug === 'review-requirements' && !optimizelyExperimentName) {
return 'request-camera-access';
}
if (originSlug === 'choose-mode' && !shouldUseCamera) {
return 'take-portrait-photo';
}
if (originSlug === 'take-portrait-photo' && !shouldUseCamera) {
return 'take-id-photo';
}
const nextIndex = panelSteps.indexOf(originSlug) + 1;
return nextIndex < panelSteps.length ? panelSteps[nextIndex] : null;
@@ -30,9 +50,11 @@ export const useNextPanelSlug = (originSlug) => {
// check if the user is too far into the flow and if so, return the slug of the
// furthest panel they are allow to be.
export const useVerificationRedirectSlug = (slug) => {
const { facePhotoFile, idPhotoFile } = useContext(IdVerificationContext);
const { facePhotoFile, idPhotoFile, optimizelyExperimentName } = useContext(IdVerificationContext);
const indexOfCurrentPanel = panelSteps.indexOf(slug);
if (!optimizelyExperimentName && slug === 'choose-mode') {
return 'review-requirements';
}
if (!facePhotoFile) {
if (indexOfCurrentPanel > panelSteps.indexOf('take-portrait-photo')) {
return 'portrait-photo-context';

View File

@@ -0,0 +1,153 @@
import React from 'react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import '@testing-library/jest-dom/extend-expect';
import {
render, cleanup, screen, act, fireEvent,
} from '@testing-library/react';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import * as analytics from '@edx/frontend-platform/analytics';
import IdVerificationContext from '../IdVerificationContext';
import CollapsibleImageHelp from '../CollapsibleImageHelp';
jest.mock('jslib-html5-camera-photo');
jest.mock('@tensorflow-models/blazeface');
jest.mock('@edx/frontend-platform/analytics');
analytics.sendTrackEvent = jest.fn();
window.HTMLMediaElement.prototype.play = () => {};
const IntlCollapsible = injectIntl(CollapsibleImageHelp);
const history = createMemoryHistory();
describe('CollapsibleImageHelpPanel', () => {
const defaultProps = {
intl: {},
isPortrait: true,
};
const contextValue = {
shouldUseCamera: true,
setShouldUseCamera: jest.fn(),
optimizelyExperimentName: '',
mediaAccess: 'granted',
};
afterEach(() => {
cleanup();
});
it('does not return if not part of experiment', async () => {
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCollapsible {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
const titleText = screen.queryByText('Upload a Photo Instead');
expect(titleText).not.toBeInTheDocument();
});
it('does not return if media access denied or unsupported', async () => {
let titleText = '';
contextValue.mediaAccess = 'denied';
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCollapsible {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
titleText = screen.queryByText('Upload a Photo Instead');
expect(titleText).not.toBeInTheDocument();
contextValue.mediaAccess = 'unsupported';
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCollapsible {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
titleText = screen.queryByText('Upload a Photo Instead');
expect(titleText).not.toBeInTheDocument();
});
it('shows the correct text if user should switch to upload', async () => {
contextValue.optimizelyExperimentName = 'test';
contextValue.mediaAccess = 'granted';
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCollapsible {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
const titleText = screen.getByText('Upload a Photo Instead');
expect(titleText).toBeInTheDocument();
const helpText = screen.getByTestId('help-text');
expect(helpText.textContent).toContain('If you are having trouble using the photo capture above');
const button = screen.getByTestId('toggle-button');
expect(button).toHaveTextContent('Switch to Upload Mode');
});
it('shows the correct text if user should switch to camera', async () => {
contextValue.optimizelyExperimentName = 'test';
contextValue.mediaAccess = 'granted';
contextValue.shouldUseCamera = false;
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCollapsible {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
const titleText = screen.getByText('Use Your Camera Instead');
expect(titleText).toBeInTheDocument();
const helpText = screen.getByTestId('help-text');
expect(helpText.textContent).toContain('If you are having trouble uploading a photo above');
const button = screen.getByTestId('toggle-button');
expect(button).toHaveTextContent('Switch to Camera Mode');
});
it('shows the correct text if user should switch to camera with pending media access', async () => {
contextValue.optimizelyExperimentName = 'test';
contextValue.mediaAccess = 'pending';
contextValue.shouldUseCamera = false;
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlCollapsible {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
const titleText = screen.getByText('Use Your Camera Instead');
expect(titleText).toBeInTheDocument();
const helpText = screen.getByTestId('help-text');
expect(helpText.textContent).toContain('If you are having trouble uploading a photo above');
const accessLink = screen.getByTestId('access-link');
fireEvent.click(accessLink);
expect(history.location.pathname).toEqual('/request-camera-access');
});
});

View File

@@ -0,0 +1,93 @@
import React from 'react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import {
render, cleanup, act, screen,
} from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import IdVerificationContext from '../../IdVerificationContext';
import ChooseModePanel from '../../panels/ChooseModePanel';
jest.mock('@edx/frontend-platform/analytics', () => ({
sendTrackEvent: jest.fn(),
}));
const IntlChooseModePanel = injectIntl(ChooseModePanel);
const history = createMemoryHistory();
describe('ChooseModePanel', () => {
const defaultProps = {
intl: {},
};
const contextValue = {
optimizelyExperimentName: 'test',
shouldUseCamera: false,
};
afterEach(() => {
cleanup();
});
it('renders correctly', async () => {
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlChooseModePanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
// check that radio button for upload is selected
const uploadRadioButton = await screen.findByLabelText('Upload photos from my device');
expect(uploadRadioButton).toBeChecked();
// check that if upload is selected, next button goes to correct screen
const nextButton = await screen.findByTestId('next-button');
expect(nextButton.getAttribute('href')).toEqual('/take-portrait-photo');
});
it('renders correctly if user wants to use camera', async () => {
contextValue.shouldUseCamera = true;
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlChooseModePanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
// check that radio button for camera is selected
const cameraRadioButton = await screen.findByLabelText('Take pictures using my camera');
expect(cameraRadioButton).toBeChecked();
// check that if upload is selected, next button goes to correct screen
const nextButton = await screen.findByTestId('next-button');
expect(nextButton.getAttribute('href')).toEqual('/request-camera-access');
});
it('redirects if user is not part of experiment', async () => {
contextValue.optimizelyExperimentName = '';
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlChooseModePanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
// check that radio button is not in document
const cameraRadioButton = await screen.queryByLabelText('Take pictures using my camera');
expect(cameraRadioButton).not.toBeInTheDocument();
});
});

View File

@@ -181,4 +181,42 @@ describe('RequestCameraAccessPanel', () => {
const text = await screen.findByTestId('camera-failure-instructions');
expect(text).toHaveTextContent(/Open the Flash Player/);
});
it('reroutes correctly to portrait context', async () => {
contextValue.mediaAccess = 'granted';
history.location.state = { fromPortraitCapture: true };
Bowser.parse = jest.fn().mockReturnValue({ browser: { name: '' } });
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlRequestCameraAccessPanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
const button = await screen.findByTestId('next-button');
fireEvent.click(button);
expect(history.location.pathname).toEqual('/portrait-photo-context');
});
it('reroutes correctly to ID context', async () => {
contextValue.mediaAccess = 'granted';
history.location.state = { fromIdCapture: true };
Bowser.parse = jest.fn().mockReturnValue({ browser: { name: '' } });
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlRequestCameraAccessPanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
const button = await screen.findByTestId('next-button');
fireEvent.click(button);
expect(history.location.pathname).toEqual('/id-context');
});
});

View File

@@ -81,4 +81,26 @@ describe('TakeIdPhotoPanel', () => {
fireEvent.click(button);
expect(history.location.pathname).toEqual('/summary');
});
it('shows correct text if user should use upload', async () => {
contextValue.optimizelyExperimentName = 'test';
contextValue.shouldUseCamera = false;
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlTakeIdPhotoPanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
// check that upload title and text are correct
const title = await screen.findByText('Upload a Photo of Your ID');
expect(title).toBeVisible();
const text = await screen.findByTestId('upload-text');
expect(text.textContent).toContain('Please upload an ID photo');
});
});

View File

@@ -27,6 +27,7 @@ describe('TakePortraitPhotoPanel', () => {
const contextValue = {
facePhotoFile: null,
setFacePhotoFile: jest.fn(),
setShouldUseCamera: jest.fn(),
};
afterEach(() => {
@@ -49,6 +50,7 @@ describe('TakePortraitPhotoPanel', () => {
it('shows next button after photo is taken and routes to IdContextPanel', async () => {
contextValue.facePhotoFile = 'test.jpg';
contextValue.shouldUseCamera = true;
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
@@ -80,4 +82,26 @@ describe('TakePortraitPhotoPanel', () => {
fireEvent.click(button);
expect(history.location.pathname).toEqual('/summary');
});
it('shows correct text if user should use upload', async () => {
contextValue.optimizelyExperimentName = 'test';
contextValue.shouldUseCamera = false;
await act(async () => render((
<Router history={history}>
<IntlProvider locale="en">
<IdVerificationContext.Provider value={contextValue}>
<IntlTakePortraitPhotoPanel {...defaultProps} />
</IdVerificationContext.Provider>
</IntlProvider>
</Router>
)));
// check that upload title and text are correct
const title = await screen.findByText('Upload a Photo of Yourself');
expect(title).toBeVisible();
const text = await screen.findByTestId('upload-text');
expect(text.textContent).toContain('Please upload a portrait photo');
});
});