diff --git a/app/javascript/packages/document-capture/components/acuant-capture.tsx b/app/javascript/packages/document-capture/components/acuant-capture.tsx
index 5ddcf36b6cd..f1b681b4097 100644
--- a/app/javascript/packages/document-capture/components/acuant-capture.tsx
+++ b/app/javascript/packages/document-capture/components/acuant-capture.tsx
@@ -490,44 +490,50 @@ function AcuantCapture(
setIsCapturingEnvironment(false);
}
+ function onAcuantImageCaptureFailure(error: AcuantCaptureFailureError, code: string | undefined) {
+ const { SEQUENCE_BREAK_CODE } = window.AcuantJavascriptWebSdk;
+ if (isAcuantCameraAccessFailure(error)) {
+ if (fullScreenRef.current?.focusTrap) {
+ suspendFocusTrapForAnticipatedFocus(fullScreenRef.current.focusTrap);
+ }
+
+ // Internally, Acuant sets a cookie to bail on guided capture if initialization had
+ // previously failed for any reason, including declined permission. Since the cookie
+ // never expires, and since we want to re-prompt even if the user had previously
+ // declined, unset the cookie value when failure occurs for permissions.
+ setAcuantFailureCookie(null);
+
+ onCameraAccessDeclined();
+ } else if (code === SEQUENCE_BREAK_CODE) {
+ setOwnErrorMessage(
+ `${t('doc_auth.errors.upload_error')} ${t('errors.messages.try_again')
+ .split(' ')
+ .join(NBSP_UNICODE)}`,
+ );
+
+ refreshAcuantFailureCookie();
+ } else if (error === undefined) {
+ // Show a more generic error message when there's a cropping error.
+ // Errors with a value of `undefined` are cropping errors.
+ setOwnErrorMessage(t('errors.general'));
+ } else {
+ setOwnErrorMessage(t('doc_auth.errors.camera.failed'));
+ }
+
+ setIsCapturingEnvironment(false);
+ trackEvent('IdV: Image capture failed', {
+ field: name,
+ error: getNormalizedAcuantCaptureFailureMessage(error, code),
+ });
+ }
+
return (
{isCapturingEnvironment && (
setHasStartedCropping(true)}
onImageCaptureSuccess={onAcuantImageCaptureSuccess}
- onImageCaptureFailure={(error, code) => {
- const { SEQUENCE_BREAK_CODE } = window.AcuantJavascriptWebSdk;
- if (isAcuantCameraAccessFailure(error)) {
- if (fullScreenRef.current?.focusTrap) {
- suspendFocusTrapForAnticipatedFocus(fullScreenRef.current.focusTrap);
- }
-
- // Internally, Acuant sets a cookie to bail on guided capture if initialization had
- // previously failed for any reason, including declined permission. Since the cookie
- // never expires, and since we want to re-prompt even if the user had previously
- // declined, unset the cookie value when failure occurs for permissions.
- setAcuantFailureCookie(null);
-
- onCameraAccessDeclined();
- } else if (code === SEQUENCE_BREAK_CODE) {
- setOwnErrorMessage(
- `${t('doc_auth.errors.upload_error')} ${t('errors.messages.try_again')
- .split(' ')
- .join(NBSP_UNICODE)}`,
- );
-
- refreshAcuantFailureCookie();
- } else {
- setOwnErrorMessage(t('doc_auth.errors.camera.failed'));
- }
-
- setIsCapturingEnvironment(false);
- trackEvent('IdV: Image capture failed', {
- field: name,
- error: getNormalizedAcuantCaptureFailureMessage(error, code),
- });
- }}
+ onImageCaptureFailure={onAcuantImageCaptureFailure}
>
{!hasStartedCropping && (
{
expect(document.activeElement).to.equal(button);
});
+ it('shows a generic error if camera starts but cropping error occurs', async () => {
+ const trackEvent = sinon.spy();
+ const { container, getByLabelText, findByText } = render(
+
+
+
+
+
+
+ ,
+ );
+
+ initialize({
+ // Call `onCropped` with a response of 'undefined'
+ start: sinon.stub().callsArgWithAsync(1, undefined),
+ });
+
+ const button = getByLabelText('Image');
+ await userEvent.click(button);
+ // "Oops, something went wrong. Please try again."
+ await findByText('errors.general');
+
+ expect(window.AcuantCameraUI.end).to.have.been.calledOnce();
+ expect(container.querySelector('.full-screen')).to.be.null();
+ expect(trackEvent).to.have.been.calledWith('IdV: Image capture failed', {
+ field: 'test',
+ error: 'Cropping failure',
+ });
+ expect(document.activeElement).to.equal(button);
+ });
+
it('shows error if capture fails: latest version of Acuant SDK', async () => {
const trackEvent = sinon.spy();
const { container, getByLabelText, findByText } = render(