diff --git a/app/javascript/packages/document-capture/components/acuant-capture.tsx b/app/javascript/packages/document-capture/components/acuant-capture.tsx index 6bc85b80884..6a7bf111812 100644 --- a/app/javascript/packages/document-capture/components/acuant-capture.tsx +++ b/app/javascript/packages/document-capture/components/acuant-capture.tsx @@ -529,7 +529,6 @@ function AcuantCapture( }); setImageCaptureText(''); - setIsCapturingEnvironment(true); } function onSelfieCaptureClosed() { diff --git a/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx b/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx index 86dab1889a2..916f75a9ffd 100644 --- a/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx +++ b/app/javascript/packages/document-capture/components/acuant-selfie-capture-canvas.jsx @@ -21,6 +21,16 @@ function AcuantSelfieCaptureCanvas({ imageCaptureText, onSelfieCaptureClosed }) // The Acuant SDK script AcuantPassiveLiveness attaches to whatever element has // this id. It then uses that element as the root for the full screen selfie capture const acuantCaptureContainerId = 'acuant-face-capture-container'; + + // This solves a fairly nasty bug for screenreader users where the screenreader focus would jump away + // from the capture button (added by Acuant SDK) to the button in this component. Specifically we + // need to detect when Acuant actually hydrates in their capture screen and hide the button. + // See PR 10668 for more information. + const elementInShadow = document + ?.getElementById('acuant-face-capture-camera') + ?.shadowRoot?.getElementById('cameraContainer'); + const loadedAcuantCamera = !!elementInShadow; + return ( <> {!isReady && } @@ -31,9 +41,11 @@ function AcuantSelfieCaptureCanvas({ imageCaptureText, onSelfieCaptureClosed }) )}

- + {!loadedAcuantCamera && ( + + )} ); } diff --git a/spec/javascript/packages/document-capture/components/acuant-selfie-capture-canvas-spec.jsx b/spec/javascript/packages/document-capture/components/acuant-selfie-capture-canvas-spec.jsx index e862a1fcd79..0a54a25f1af 100644 --- a/spec/javascript/packages/document-capture/components/acuant-selfie-capture-canvas-spec.jsx +++ b/spec/javascript/packages/document-capture/components/acuant-selfie-capture-canvas-spec.jsx @@ -27,3 +27,47 @@ it('shows the Acuant div when the script has loaded', () => { expect(container.querySelector('#acuant-face-capture-container')).to.exist(); expect(container.querySelector('.acuant-capture-canvas__spinner')).not.to.exist(); }); + +it('shows the fullscreen close button before acuant is hydrated in', () => { + // Render the AcuantSelfieCaptureCanvas component with some text + const imageCaptureText = 'Face not found'; + const { rerender, container, queryByRole } = render( + + + + + , + ); + // Check that the button exists + expect(queryByRole('button')).to.exist(); + + // Mock how Acuant sets up the dom by creating this structure of divs + // '#acuant-face-capture-container>#acuant-face-capture-camera>#cameraContainer' + const acuantFaceCaptureDiv = document.createElement('div'); + acuantFaceCaptureDiv.id = 'acuant-face-capture-camera'; + const acuantFaceCaptureContainer = container.querySelector('#acuant-face-capture-container'); + acuantFaceCaptureContainer.appendChild(acuantFaceCaptureDiv); + expect( + container.querySelector('#acuant-face-capture-container>#acuant-face-capture-camera'), + ).to.exist(); + + // Mock how Acuant sets up the shadow dom with the #cameraContainer div inside it + const cameraContainer = document.createElement('div'); + cameraContainer.id = 'cameraContainer'; + const shadow = container + .querySelector('#acuant-face-capture-camera') + .attachShadow({ mode: 'open' }); + shadow.appendChild(cameraContainer); + + // Rerender the component, the shadow dom continues to exist + const newImageCaptureText = 'Too many faces'; + rerender( + + + + + , + ); + // The button now disappears + expect(queryByRole('button')).not.to.exist(); +});