diff --git a/app/javascript/packages/compose-components/README.md b/app/javascript/packages/compose-components/README.md deleted file mode 100644 index fec7f76731e..00000000000 --- a/app/javascript/packages/compose-components/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# `@18f/identity-compose-components` - -A utility function to compose a set of React components and their props to a single component. - -Convenient for flattening a deeply-nested arrangement of context providers, for example. - -## Example - -```jsx -const App = composeComponents( - [FirstContext.Provider, { value: 1 }], - [SecondContext.Provider, { value: 2 }], - AppRoot, -); - -render(App, document.getElementById('app-root')); -``` diff --git a/app/javascript/packages/compose-components/index.js b/app/javascript/packages/compose-components/index.js deleted file mode 100644 index 5dce9d65faf..00000000000 --- a/app/javascript/packages/compose-components/index.js +++ /dev/null @@ -1,51 +0,0 @@ -import { createElement } from 'react'; - -/** @typedef {import('react').ComponentType

} ComponentType @template P */ - -/** - * @typedef {[ComponentType

, P]} NormalizedComponentPair - * - * @template P - */ - -/** - * @typedef {[ComponentType

, P]|[ComponentType

]|ComponentType

} ComponentPair - * - * @template P - */ - -/** - * A utility function to compose a set of React components and their props to a single component. - * - * Convenient for flattening a deeply-nested arrangement of context providers, for example. - * - * @example - * ```jsx - * const App = composeComponents( - * [FirstContext.Provider, { value: 1 }], - * [SecondContext.Provider, { value: 2 }], - * AppRoot, - * ); - * - * render(App, document.getElementById('app-root')); - * ``` - * - * @param {...ComponentPair<*>} components - * - * @return {ComponentType<*>} - */ -export function composeComponents(...components) { - return function ComposedComponent() { - /** @type {JSX.Element?} */ - let element = null; - for (let i = components.length - 1; i >= 0; i--) { - const componentPair = /** @type {NormalizedComponentPair<*>} */ ( - Array.isArray(components[i]) ? components[i] : [components[i]] - ); - const [ComponentType, props] = componentPair; - element = createElement(ComponentType, props, element); - } - - return element; - }; -} diff --git a/app/javascript/packages/compose-components/index.spec.jsx b/app/javascript/packages/compose-components/index.spec.jsx deleted file mode 100644 index ba0e3f9c39b..00000000000 --- a/app/javascript/packages/compose-components/index.spec.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import { createContext, useContext } from 'react'; -import { render } from '@testing-library/react'; -import { composeComponents } from './index.js'; - -describe('composeComponents', () => { - it('composes components', () => { - const FirstContext = createContext(null); - const SecondContext = createContext(null); - function AppRoot() { - return ( - <> - {useContext(FirstContext)} - {useContext(SecondContext)} - - ); - } - - const ComposedComponent = composeComponents( - [FirstContext.Provider, { value: 1 }], - [SecondContext.Provider, { value: 2 }], - [({ children }) => <>{children}3], - AppRoot, - ); - - const { getByText } = render(); - - expect(getByText('123')).to.be.ok(); - }); -}); diff --git a/app/javascript/packages/compose-components/package.json b/app/javascript/packages/compose-components/package.json deleted file mode 100644 index 29fcd9d2b79..00000000000 --- a/app/javascript/packages/compose-components/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@18f/identity-compose-components", - "private": true, - "version": "1.0.0", - "dependencies": { - "react": "^17.0.2" - }, - "sideEffects": false -} diff --git a/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx b/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx index cc37fdf45aa..b50b883d9b7 100644 --- a/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx +++ b/app/javascript/packages/document-capture/components/document-capture-review-issues.spec.tsx @@ -5,7 +5,6 @@ import { toFormEntryError } from '@18f/identity-document-capture/services/upload import { I18nContext } from '@18f/identity-react-i18n'; import { I18n } from '@18f/identity-i18n'; import { expect } from 'chai'; -import { composeComponents } from '@18f/identity-compose-components'; describe('DocumentCaptureReviewIssues', () => { const DEFAULT_OPTIONS = { @@ -46,54 +45,51 @@ describe('DocumentCaptureReviewIssues', () => { context('with doc error', () => { it('renders for non doc type failure', () => { - const props = { - isFailedDocType: false, - remainingSubmitAttempts: 2, - unknownFieldErrors: [ - { - field: 'general', - error: toFormEntryError({ field: 'network', message: 'general error' }), - }, - ], - errors: [ - { - field: 'front', - error: toFormEntryError({ field: 'front', message: 'front side error' }), - }, - { - field: 'back', - error: toFormEntryError({ field: 'back', message: 'back side error' }), - }, - ], - }; - const App = composeComponents( - [ - InPersonContext.Provider, - { - value: { - inPersonURL: '/verify/doc_capture', - }, - }, - ], - [ - I18nContext.Provider, - { - value: new I18n({ - strings: { - 'idv.failure.attempts_html': 'You have %{count} attempts remaining.', - }, - }), - }, - ], - [ - DocumentCaptureReviewIssues, - { - ...DEFAULT_OPTIONS, - ...props, - }, - ], + const { getByText, getByLabelText, getByRole, getAllByRole } = render( + + + + + , ); - const { getByText, getByLabelText, getByRole, getAllByRole } = render(); + const h1 = screen.getByRole('heading', { name: 'doc_auth.headings.review_issues', level: 1 }); expect(h1).to.be.ok(); diff --git a/app/javascript/packs/document-capture.tsx b/app/javascript/packs/document-capture.tsx index fa3562e5804..f75d987e8b3 100644 --- a/app/javascript/packs/document-capture.tsx +++ b/app/javascript/packs/document-capture.tsx @@ -1,5 +1,4 @@ import { render } from 'react-dom'; -import { composeComponents } from '@18f/identity-compose-components'; import { DocumentCapture, DeviceContext, @@ -39,6 +38,7 @@ interface AppRootData { howToVerifyURL: string; previousStepUrl: string; docAuthSelfieDesktopTestMode: string; + accountUrl: string; locationsUrl: string; addressSearchUrl: string; sessionsUrl: string; @@ -120,93 +120,84 @@ try { parsedUsStatesTerritories = JSON.parse(usStatesTerritories); } catch (e) {} -const App = composeComponents( - [MarketingSiteContextProvider, { helpCenterRedirectURL, securityAndPrivacyHowItWorksURL }], - [DeviceContext.Provider, { value: device }], - [ - InPersonContext.Provider, - { - value: { - inPersonURL, - locationsURL, - addressSearchURL, - inPersonOutageMessageEnabled: inPersonOutageMessageEnabled === 'true', - inPersonOutageExpectedUpdateDate, - inPersonFullAddressEntryEnabled: inPersonFullAddressEntryEnabled === 'true', - optedInToInPersonProofing: optedInToInPersonProofing === 'true', - usStatesTerritories: parsedUsStatesTerritories, - skipDocAuth: skipDocAuth === 'true', - skipDocAuthFromHandoff: skipDocAuthFromHandoff === 'true', - howToVerifyURL: howToVerifyUrl, - previousStepURL: previousStepUrl, - }, - }, - ], - [AnalyticsContextProvider, { trackEvent }], - [ - AcuantContextProvider, - { - sdkSrc: acuantVersion && `/acuant/${acuantVersion}/AcuantJavascriptWebSdk.min.js`, - cameraSrc: acuantVersion && `/acuant/${acuantVersion}/AcuantCamera.min.js`, - passiveLivenessOpenCVSrc: acuantVersion && `/acuant/${acuantVersion}/opencv.min.js`, - passiveLivenessSrc: getSelfieCaptureEnabled() - ? acuantVersion && `/acuant/${acuantVersion}/AcuantPassiveLiveness.min.js` - : undefined, - credentials: getMetaContent('acuant-sdk-initialization-creds'), - endpoint: getMetaContent('acuant-sdk-initialization-endpoint'), - glareThreshold, - sharpnessThreshold, - }, - ], - [ - UploadContextProvider, - { - endpoint: String(appRoot.getAttribute('data-endpoint')), - statusEndpoint: String(appRoot.getAttribute('data-status-endpoint')), - statusPollInterval: Number(appRoot.getAttribute('data-status-poll-interval-ms')), - isMockClient, - formData, - flowPath, - }, - ], - [ - FlowContext.Provider, - { - value: { - accountURL, - cancelURL, - currentStep: 'document_capture', - }, - }, - ], - [ - ServiceProviderContextProvider, - { - value: getServiceProvider(), - }, - ], - [ - SelfieCaptureContext.Provider, - { - value: { - isSelfieCaptureEnabled: getSelfieCaptureEnabled(), - isSelfieDesktopTestMode: String(docAuthSelfieDesktopTestMode) === 'true', - }, - }, - ], - [ - FailedCaptureAttemptsContextProvider, - { - maxCaptureAttemptsBeforeNativeCamera: Number(maxCaptureAttemptsBeforeNativeCamera), - maxSubmissionAttemptsBeforeNativeCamera: Number(maxSubmissionAttemptsBeforeNativeCamera), - }, - ], - [ - DocumentCapture, - { - onStepChange: () => extendSession(sessionsURL), - }, - ], +render( + + + + + + + + + + + extendSession(sessionsURL)} /> + + + + + + + + + + , + appRoot, ); - -render(, appRoot); diff --git a/scripts/enforce-typescript-files.mjs b/scripts/enforce-typescript-files.mjs index 90341fe763f..f75d5f728bd 100755 --- a/scripts/enforce-typescript-files.mjs +++ b/scripts/enforce-typescript-files.mjs @@ -9,8 +9,6 @@ import glob from 'fast-glob'; // only ever shrink over time. Scripts which are loaded directly by Node.js should exist within // packages with a defined entrypoint. const LEGACY_FILE_EXCEPTIONS = [ - 'app/javascript/packages/compose-components/index.js', - 'app/javascript/packages/compose-components/index.spec.jsx', 'app/javascript/packages/device/index.js', 'app/javascript/packages/document-capture/index.js', 'app/javascript/packages/document-capture/components/acuant-capture-canvas.jsx', diff --git a/spec/javascript/packages/document-capture/components/documents-step-spec.tsx b/spec/javascript/packages/document-capture/components/documents-step-spec.tsx index 41bf799c1c6..a02b1b284ad 100644 --- a/spec/javascript/packages/document-capture/components/documents-step-spec.tsx +++ b/spec/javascript/packages/document-capture/components/documents-step-spec.tsx @@ -9,7 +9,6 @@ import { SelfieCaptureContext, } from '@18f/identity-document-capture'; import DocumentsStep from '@18f/identity-document-capture/components/documents-step'; -import { composeComponents } from '@18f/identity-compose-components'; import { render } from '../../../support/document-capture'; import { getFixtureFile } from '../../../support/file'; @@ -143,18 +142,24 @@ describe('document-capture/components/documents-step', () => { }); it('renders only with front, back when isSelfieCaptureEnabled is true', () => { - const App = composeComponents( - [ - SelfieCaptureContext.Provider, - { - value: { - isSelfieCaptureEnabled: true, - }, - }, - ], - [DocumentsStep], + const { getByRole, getByLabelText } = render( + + undefined} + errors={[]} + onError={() => undefined} + registerField={() => undefined} + unknownFieldErrors={[]} + toPreviousStep={() => undefined} + /> + , ); - const { getByRole, getByLabelText } = render(); const front = getByLabelText('doc_auth.headings.document_capture_front'); const back = getByLabelText('doc_auth.headings.document_capture_back'); diff --git a/spec/javascript/packages/document-capture/components/review-issues-step-spec.jsx b/spec/javascript/packages/document-capture/components/review-issues-step-spec.jsx index 08910f65fd4..986c46446b3 100644 --- a/spec/javascript/packages/document-capture/components/review-issues-step-spec.jsx +++ b/spec/javascript/packages/document-capture/components/review-issues-step-spec.jsx @@ -11,7 +11,6 @@ import { I18n } from '@18f/identity-i18n'; import { I18nContext } from '@18f/identity-react-i18n'; import ReviewIssuesStep from '@18f/identity-document-capture/components/review-issues-step'; import { toFormEntryError } from '@18f/identity-document-capture/services/upload'; -import { composeComponents } from '@18f/identity-compose-components'; import { render } from '../../../support/document-capture'; import { getFixtureFile } from '../../../support/file'; @@ -180,18 +179,11 @@ describe('document-capture/components/review-issues-step', () => { }); it('renders with front, back, and selfie inputs when isSelfieCaptureEnabled is true', async () => { - const App = composeComponents( - [ - SelfieCaptureContext.Provider, - { - value: { - isSelfieCaptureEnabled: true, - }, - }, - ], - [ReviewIssuesStep, DEFAULT_PROPS], + const { getByLabelText, queryByLabelText, getByRole } = render( + + + , ); - const { getByLabelText, queryByLabelText, getByRole } = render(); await userEvent.click(getByRole('button', { name: 'idv.failure.button.warning' }));