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 @@ -47,25 +47,6 @@ const ACCEPTABLE_GLARE_SCORE = 50;
*/
const ACCEPTABLE_SHARPNESS_SCORE = 50;

/**
* The minimum file size (bytes) for an image to be considered acceptable.
*
* @type {number}
*/
export const ACCEPTABLE_FILE_SIZE_BYTES = 250 * 1024;

/**
* Given a file, returns minimum acceptable file size in bytes, depending on the type of file and
* the current environment.
*
* @param {Blob} file File to assess.
*
* @return {number} Minimum file size, in bytes.
*/
export function getMinimumFileSize(file) {
return file.type.startsWith('image/') ? ACCEPTABLE_FILE_SIZE_BYTES : 0;
}

/**
* Returns an instance of File representing the given data URL.
*
Expand Down Expand Up @@ -149,19 +130,13 @@ function AcuantCapture(
}

/**
* Calls onChange with next value if valid. Validation occurs separately to AcuantCaptureCanvas
* for common checks derived from file properties (file size, etc). If invalid, error state is
* assigned with appropriate error message.
* Calls onChange with next value and resets any errors which may be present.
*
* @param {Blob?} nextValue Next value candidate.
* @param {Blob?} nextValue Next value.
*/
function onChangeIfValid(nextValue) {
if (nextValue && nextValue.size < getMinimumFileSize(nextValue)) {
setOwnErrorMessage(t('errors.doc_auth.photo_file_size'));
} else {
setOwnErrorMessage(null);
onChange(nextValue);
}
function onChangeAndResetError(nextValue) {
setOwnErrorMessage(null);
onChange(nextValue);
}

/**
Expand Down Expand Up @@ -202,7 +177,7 @@ function AcuantCapture(
} else {
const dataAsBlob = toBlob(nextCapture.image.data);
fileCache.set(dataAsBlob, nextCapture.image.data);
onChangeIfValid(dataAsBlob);
onChangeAndResetError(dataAsBlob);
}

setIsCapturing(false);
Expand All @@ -224,7 +199,7 @@ function AcuantCapture(
value={value}
errorMessage={ownErrorMessage ?? errorMessage}
onClick={startCaptureOrTriggerUpload}
onChange={onChangeIfValid}
onChange={onChangeAndResetError}
onError={() => setOwnErrorMessage(null)}
/>
<div className="margin-top-2">
Expand Down
1 change: 0 additions & 1 deletion config/js_locale_strings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
- errors.doc_auth.capture_failure
- errors.doc_auth.document_capture_selfie_consent_blocked
- errors.doc_auth.photo_blurry
- errors.doc_auth.photo_file_size
- errors.doc_auth.photo_glare
- errors.doc_auth.selfie
- errors.messages.format_mismatch
Expand Down
1 change: 0 additions & 1 deletion config/locales/errors/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ en:
phone_step_incomplete: You must go to your phone and upload photos of your ID
before continuing. We sent you a link with instructions.
photo_blurry: Photo is too blurry, please try again.
photo_file_size: Photo is too compressed, please try again with a higher quality.
photo_glare: Photo has glare, please try again.
quota_reached: Sorry your service provider has reached its identity verification
limit. Please contact your service provider for more information.
Expand Down
2 changes: 0 additions & 2 deletions config/locales/errors/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ es:
phone_step_incomplete: Debe ir a su teléfono y cargar fotos de su identificación
antes de continuar. Te enviamos un enlace con instrucciones.
photo_blurry: La foto está demasiado borrosa. Vuelve a intentarlo.
photo_file_size: La foto está demasiado comprimida. Vuelve a intentarlo con
una calidad superior.
photo_glare: La foto tiene un resplandor. Vuelve a intentarlo.
quota_reached: Lo sentimos, su proveedor de servicios ha alcanzado su límite
de verificación de identidad. Póngase en contacto con su proveedor de servicios
Expand Down
2 changes: 0 additions & 2 deletions config/locales/errors/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ fr:
photos de votre identifiant avant de continuer. Nous vous avons envoyé un
lien avec des instructions.
photo_blurry: La photo est trop floue, veuillez réessayer.
photo_file_size: La photo est trop compressée, veuillez réessayer avec une qualité
supérieure.
photo_glare: La photo a des reflets, veuillez réessayer.
quota_reached: Désolé, votre fournisseur de services a atteint sa limite de
vérification d'identité. Veuillez contacter votre fournisseur de services
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,15 @@ import { fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { waitForElementToBeRemoved } from '@testing-library/dom';
import sinon from 'sinon';
import AcuantCapture, {
getMinimumFileSize,
ACCEPTABLE_FILE_SIZE_BYTES,
} from '@18f/identity-document-capture/components/acuant-capture';
import AcuantCapture from '@18f/identity-document-capture/components/acuant-capture';
import { Provider as AcuantContextProvider } from '@18f/identity-document-capture/context/acuant';
import DeviceContext from '@18f/identity-document-capture/context/device';
import I18nContext from '@18f/identity-document-capture/context/i18n';
import render from '../../../support/render';
import { useAcuant } from '../../../support/acuant';
import { useSandbox } from '../../../support/sinon';

describe('document-capture/components/acuant-capture', () => {
const { initialize } = useAcuant();
const sandbox = useSandbox();

describe('getMinimumFileSize', () => {
it('returns zero for non-image file', () => {
const file = new window.File([], 'file.yml', { type: 'application/x-yaml' });
expect(getMinimumFileSize(file)).to.equal(0);
});

it('returns non-zero for image file', () => {
const file = new window.File([], 'file.png', { type: 'image/png' });
expect(getMinimumFileSize(file)).to.be.gt(0);
});
});

context('mobile', () => {
it('renders with assumed capture button support while acuant is not ready and on mobile', () => {
Expand Down Expand Up @@ -163,8 +146,6 @@ describe('document-capture/components/acuant-capture', () => {
});

it('calls onChange with the captured image on successful capture', async () => {
sandbox.stub(window.Blob.prototype, 'size').value(ACCEPTABLE_FILE_SIZE_BYTES);

const onChange = sinon.mock();
const { getByText } = render(
<DeviceContext.Provider value={{ isMobile: true }}>
Expand Down Expand Up @@ -363,8 +344,6 @@ describe('document-capture/components/acuant-capture', () => {
});

it('removes error message once image is corrected', async () => {
sandbox.stub(window.Blob.prototype, 'size').value(ACCEPTABLE_FILE_SIZE_BYTES);

const { getByText, findByText } = render(
<DeviceContext.Provider value={{ isMobile: true }}>
<AcuantContextProvider sdkSrc="about:blank">
Expand Down Expand Up @@ -413,38 +392,6 @@ describe('document-capture/components/acuant-capture', () => {
await waitForElementToBeRemoved(error);
});

it('renders error message if capture succeeds but photo is too small', async () => {
const { getByText, findByText } = render(
<DeviceContext.Provider value={{ isMobile: true }}>
<AcuantContextProvider sdkSrc="about:blank">
<AcuantCapture label="Image" minimumFileSize={500 * 1024} />
</AcuantContextProvider>
</DeviceContext.Provider>,
);

initialize({
start: sinon.stub().callsFake(async (callbacks) => {
await Promise.resolve();
callbacks.onCaptured();
await Promise.resolve();
callbacks.onCropped({
glare: 70,
sharpness: 38,
image: {
data: 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg"/%3E',
},
});
}),
});

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

const error = await findByText('errors.doc_auth.photo_blurry');
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the correct test case to be removing here, but it wasn't testing the correct thing.

I confirmed in master with the following diff that the tests will pass as expected:

diff --git a/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx b/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx
index bf7b2ec3b..14ad9a4a3 100644
--- a/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx
+++ b/spec/javascripts/packages/document-capture/components/acuant-capture-spec.jsx
@@ -429,7 +429,7 @@ describe('document-capture/components/acuant-capture', () => {
           await Promise.resolve();
           callbacks.onCropped({
             glare: 70,
-            sharpness: 38,
+            sharpness: 60,
             image: {
               data: 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg"/%3E',
             },
@@ -440,7 +440,7 @@ describe('document-capture/components/acuant-capture', () => {
       const button = getByText('doc_auth.buttons.take_picture');
       fireEvent.click(button);
 
-      const error = await findByText('errors.doc_auth.photo_blurry');
+      const error = await findByText('errors.doc_auth.photo_file_size');
 
       expect(error).to.be.ok();
     });

The test case to verify sharpness is still present after these changes:

it('renders error message if capture succeeds but photo is too blurry', async () => {

I assume it was a bad copy/paste on my part.


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

it('triggers forced upload', () => {
const { getByText } = render(
<I18nContext.Provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import React from 'react';
import userEvent from '@testing-library/user-event';
import { waitFor } from '@testing-library/dom';
import { fireEvent } from '@testing-library/react';
import { ACCEPTABLE_FILE_SIZE_BYTES } from '@18f/identity-document-capture/components/acuant-capture';
import { UploadFormEntriesError } from '@18f/identity-document-capture/services/upload';
import { AcuantProvider, DeviceContext } from '@18f/identity-document-capture';
import DocumentCapture, {
getFormattedErrorMessages,
} from '@18f/identity-document-capture/components/document-capture';
import render from '../../../support/render';
import { useAcuant } from '../../../support/acuant';
import { useSandbox } from '../../../support/sinon';

describe('document-capture/components/document-capture', () => {
const { initialize } = useAcuant();
const sandbox = useSandbox();

function isFormValid(form) {
return [...form.querySelectorAll('input')].every((input) => input.checkValidity());
Expand All @@ -24,7 +21,6 @@ describe('document-capture/components/document-capture', () => {

beforeEach(() => {
originalHash = window.location.hash;
sandbox.stub(window.Blob.prototype, 'size').value(ACCEPTABLE_FILE_SIZE_BYTES);
});

afterEach(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import sinon from 'sinon';
import { ACCEPTABLE_FILE_SIZE_BYTES } from '@18f/identity-document-capture/components/acuant-capture';
import DeviceContext from '@18f/identity-document-capture/context/device';
import DocumentsStep, { validate } from '@18f/identity-document-capture/components/documents-step';
import { RequiredValueMissingError } from '@18f/identity-document-capture/components/form-steps';
import render from '../../../support/render';
import { useSandbox } from '../../../support/sinon';

describe('document-capture/components/documents-step', () => {
const sandbox = useSandbox();

beforeEach(() => {
sandbox.stub(window.Blob.prototype, 'size').value(ACCEPTABLE_FILE_SIZE_BYTES);
});

describe('validate', () => {
it('returns errors if both front and back are unset', () => {
const value = {};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import sinon from 'sinon';
import { ACCEPTABLE_FILE_SIZE_BYTES } from '@18f/identity-document-capture/components/acuant-capture';
import SelfieStep, { validate } from '@18f/identity-document-capture/components/selfie-step';
import { RequiredValueMissingError } from '@18f/identity-document-capture/components/form-steps';
import render from '../../../support/render';
import { useSandbox } from '../../../support/sinon';

describe('document-capture/components/selfie-step', () => {
const sandbox = useSandbox();

beforeEach(() => {
sandbox.stub(window.Blob.prototype, 'size').value(ACCEPTABLE_FILE_SIZE_BYTES);
});

describe('validate', () => {
it('returns object with error if selfie is unset', () => {
const value = {};
Expand Down