Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,11 @@ interface AcuantCameraUIOptions {
text: AcuantCameraUIText;
}

/**
* Document type.
*
* 0 = None
* 1 = ID
* 2 = Passport
*/
export type AcuantDocumentType = 0 | 1 | 2;
export enum AcuantDocumentType {
NONE = 0,
ID = 1,
PASSPORT = 2,
}

export type AcuantCaptureFailureError =
| undefined // Cropping failure (SDK v11.5.0, L1171)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import type {
} from './acuant-camera';

type AcuantDocumentTypeLabel = 'id' | 'passport' | 'none';
type AcuantImageAssessment = 'success' | 'glare' | 'blurry';
type AcuantImageAssessment = 'success' | 'glare' | 'blurry' | 'unsupported';
type ImageSource = 'acuant' | 'upload';

interface ImageAnalyticsPayload {
Expand Down Expand Up @@ -438,15 +438,19 @@ function AcuantCapture(
const { image, cardtype, dpi, moire, glare, sharpness } = nextCapture;
const isAssessedAsGlare = glare < glareThreshold;
const isAssessedAsBlurry = sharpness < sharpnessThreshold;
const isAssessedAsUnsupported = cardtype !== 1;
const { width, height, data } = image;

let assessment: AcuantImageAssessment;
if (isAssessedAsGlare) {
setOwnErrorMessage(t('doc_auth.errors.glare.failed_short'));
assessment = 'glare';
} else if (isAssessedAsBlurry) {
if (isAssessedAsBlurry) {
setOwnErrorMessage(t('doc_auth.errors.sharpness.failed_short'));
assessment = 'blurry';
} else if (isAssessedAsGlare) {
setOwnErrorMessage(t('doc_auth.errors.glare.failed_short'));
assessment = 'glare';
} else if (isAssessedAsUnsupported) {
setOwnErrorMessage(t('doc_auth.errors.card_type'));
assessment = 'unsupported';
} else {
assessment = 'success';
}
Expand All @@ -456,6 +460,7 @@ function AcuantCapture(
height,
mimeType: 'image/jpeg', // Acuant Web SDK currently encodes all images as JPEG
source: 'acuant',
isAssessedAsUnsupported,
documentType: getDocumentTypeLabel(cardtype),
dpi,
moire,
Expand All @@ -475,7 +480,11 @@ function AcuantCapture(
onChangeAndResetError(data, analyticsPayload);
onResetFailedCaptureAttempts();
} else {
onFailedCaptureAttempt({ isAssessedAsGlare, isAssessedAsBlurry });
onFailedCaptureAttempt({
isAssessedAsGlare,
isAssessedAsBlurry,
isAssessedAsUnsupported,
});
}

setIsCapturingEnvironment(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import useCounter from '../hooks/use-counter';
interface CaptureAttemptMetadata {
isAssessedAsGlare: boolean;
isAssessedAsBlurry: boolean;
isAssessedAsUnsupported: boolean;
}

interface FailedCaptureAttemptsContextInterface {
Expand Down Expand Up @@ -66,6 +67,7 @@ interface FailedCaptureAttemptsContextInterface {
const DEFAULT_LAST_ATTEMPT_METADATA: CaptureAttemptMetadata = {
isAssessedAsGlare: false,
isAssessedAsBlurry: false,
isAssessedAsUnsupported: false,
};

const FailedCaptureAttemptsContext = createContext<FailedCaptureAttemptsContextInterface>({
Expand Down
1 change: 1 addition & 0 deletions config/locales/doc_auth/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ en:
browser or system settings, reload this page, or upload a photo
instead.
failed: Camera failed to start, please try again.
card_type: Try again with your driver’s license or state ID card.
dpi:
failed_short: Image is too small or blurry, please try again.
top_msg: We couldn’t read your ID. Your image size may be too small, or your ID
Expand Down
2 changes: 2 additions & 0 deletions config/locales/doc_auth/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ es:
compruebe la configuración de su navegador o sistema, recargue esta
página o suba una foto en su lugar.
failed: No se ha podido encender la cámara, por favor, inténtelo de nuevo.
card_type: Solo se aceptan licencias de conducir o documentos de identidad
estatales.
dpi:
failed_short: La imagen es demasiado pequeña o está borrosa, por favor inténtelo
de nuevo.
Expand Down
2 changes: 2 additions & 0 deletions config/locales/doc_auth/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ fr:
Veuillez vérifier les paramètres de votre navigateur ou de votre
système, recharger cette page ou télécharger une photo à la place.
failed: L’appareil photo n’a pas réussi à démarrer, veuillez réessayer.
card_type: Réessayez avec votre permis de conduire ou carte d’identité délivrée
par l’État.
dpi:
failed_short: L’image est trop petite ou floue, veuillez réessayer.
top_msg: Nous n’avons pas pu lire votre pièce d’identité. La taille de votre
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,47 @@ describe('document-capture/components/acuant-capture', () => {
);
});

it('renders error message and logs metadata if capture succeeds but the document type identified is unsupported', async () => {
const trackEvent = sinon.spy();
const { getByText, findByText } = render(
<AnalyticsContext.Provider value={{ trackEvent }}>
<DeviceContext.Provider value={{ isMobile: true }}>
<AcuantContextProvider sdkSrc="about:blank" cameraSrc="about:blank">
<AcuantCapture label="Image" name="test" />
</AcuantContextProvider>
</DeviceContext.Provider>
</AnalyticsContext.Provider>,
);

initialize({
start: sinon.stub().callsFake(async (callbacks) => {
await Promise.resolve();
callbacks.onCaptured();
await Promise.resolve();
callbacks.onCropped({
...ACUANT_CAPTURE_SUCCESS_RESULT,
cardtype: 2,
});
}),
});

const button = getByText('doc_auth.buttons.take_picture');
fireEvent.click(button);

const error = await findByText('doc_auth.errors.card_type');

expect(trackEvent).to.have.been.calledWith(
'IdV: test image added',
sinon.match({
documentType: 'passport',
isAssessedAsUnsupported: true,
assessment: 'unsupported',
}),
);

expect(error).to.be.ok();
});

it('renders error message if capture succeeds but photo glare exceeds threshold', async () => {
const trackEvent = sinon.spy();
const { getByText, findByText } = render(
Expand Down Expand Up @@ -585,6 +626,7 @@ describe('document-capture/components/acuant-capture', () => {
height: 1104,
sharpnessScoreThreshold: sinon.match.number,
glareScoreThreshold: 50,
isAssessedAsUnsupported: false,
isAssessedAsBlurry: false,
isAssessedAsGlare: true,
assessment: 'glare',
Expand Down Expand Up @@ -639,6 +681,7 @@ describe('document-capture/components/acuant-capture', () => {
height: 1104,
sharpnessScoreThreshold: 50,
glareScoreThreshold: sinon.match.number,
isAssessedAsUnsupported: false,
isAssessedAsBlurry: true,
isAssessedAsGlare: false,
assessment: 'blurry',
Expand Down Expand Up @@ -746,6 +789,7 @@ describe('document-capture/components/acuant-capture', () => {
height: 1104,
sharpnessScoreThreshold: 50,
glareScoreThreshold: sinon.match.number,
isAssessedAsUnsupported: false,
isAssessedAsBlurry: true,
isAssessedAsGlare: false,
assessment: 'blurry',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ describe('document-capture/context/capture-troubleshooting', () => {
expect(trackEvent).to.have.been.calledWith('IdV: Capture troubleshooting shown', {
isAssessedAsGlare: false,
isAssessedAsBlurry: false,
isAssessedAsUnsupported: false,
});

const tryAgainButton = getByRole('button', { name: 'idv.failure.button.warning' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ describe('document-capture/components/document-capture', () => {
image: {
data: validUpload,
},
cardtype: 1,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('document-capture/components/documents-step', () => {
);

initialize();
const result = { sharpness: 100, image: { data: '' } };
const result = { sharpness: 100, image: { data: '' }, cardtype: 1 };

window.AcuantCameraUI.start.callsFake(({ onCropped }) => onCropped({ ...result, glare: 10 }));
await userEvent.click(getByLabelText('doc_auth.headings.document_capture_front'));
Expand Down