We use the information you provide to help decide if you’re
eligible for a grant. To be eligible, you must have a qualifying
@@ -61,34 +46,17 @@ export default {
schema: {
type: 'object',
properties: {
- remarks: {
- type: 'object',
- properties: {
- respiratoryIllness: {
- type: 'boolean',
- },
- blindness: {
- type: 'boolean',
- },
- lossOfHands: {
- type: 'boolean',
- },
- lossOfLimbs: {
- type: 'boolean',
- },
- lossOfLegs: {
- type: 'boolean',
- },
- lossOfExtremity: {
- type: 'boolean',
- },
- burns: {
- type: 'boolean',
- },
- otherConditions: {
- type: 'string',
- },
- },
+ remarks: checkboxGroupSchema([
+ 'respiratoryIllness',
+ 'blindness',
+ 'lossOfHands',
+ 'lossOfLimbs',
+ 'lossOfLegs',
+ 'lossOfExtremity',
+ 'burns',
+ ]),
+ otherConditions: {
+ type: 'string',
},
'view:additionalInformation': {
type: 'object',
diff --git a/src/applications/simple-forms/26-4555/tests/e2e/4555-adapted-housing.cypress.spec.js b/src/applications/simple-forms/26-4555/tests/e2e/4555-adapted-housing.cypress.spec.js
index 091f7103ca6e..2cfba95c49bc 100644
--- a/src/applications/simple-forms/26-4555/tests/e2e/4555-adapted-housing.cypress.spec.js
+++ b/src/applications/simple-forms/26-4555/tests/e2e/4555-adapted-housing.cypress.spec.js
@@ -5,12 +5,16 @@ import featureToggles from '../../../shared/tests/e2e/fixtures/mocks/feature-tog
import mockSubmit from '../../../shared/tests/e2e/fixtures/mocks/application-submit.json';
import formConfig from '../../config/form';
import manifest from '../../manifest.json';
-import { reviewAndSubmitPageFlow } from '../../../shared/tests/e2e/helpers';
+import {
+ fillAddressWebComponentPattern,
+ reviewAndSubmitPageFlow,
+} from '../../../shared/tests/e2e/helpers';
const testConfig = createTestConfig(
{
dataPrefix: 'data',
dataSets: ['minimal-test', 'maximal-test'],
+ useWebComponentFields: true,
dataDir: path.join(__dirname, 'fixtures', 'data'),
pageHooks: {
introduction: ({ afterHook }) => {
@@ -23,23 +27,10 @@ const testConfig = createTestConfig(
cy.injectAxeThenAxeCheck();
afterHook(() => {
cy.get('@testData').then(data => {
- cy.fillPage();
- // fillPage doesn't catch state select, so select state manually
- cy.get('select#root_veteran_address_state').select(
- data.veteran.address.state,
+ fillAddressWebComponentPattern(
+ 'veteran_address',
+ data.veteran.address,
);
- if (data.veteran.address.city) {
- if (data.veteran.address.isMilitary) {
- // there is a select dropdown instead when military is checked
- cy.get('select#root_veteran_address_city').select(
- data.veteran.address.city,
- );
- } else {
- cy.get('#root_veteran_address_city').type(
- data.veteran.address.city,
- );
- }
- }
cy.axeCheck();
cy.findByText(/continue/i, { selector: 'button' }).click();
});
diff --git a/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/maximal-test.json b/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/maximal-test.json
index 77a2cb7d3afc..bd37b026528d 100644
--- a/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/maximal-test.json
+++ b/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/maximal-test.json
@@ -25,24 +25,14 @@
"previousHiApplication": {
"previousHiApplicationDate": "1999-02-04",
"previousHiApplicationAddress": {
- "street": "2222 Stone st",
- "street2": "Behind the big rock",
- "city": "Stoneville",
- "country": "USA",
- "state": "ID",
- "postalCode": "11111"
+ "city": "Atlanta"
},
"hasPreviousHiApplication": true
},
"previousSahApplication": {
"previousSahApplicationDate": "2000-06-10",
"previousSahApplicationAddress": {
- "street": "2222 Stone st.",
- "street2": "Behind the big rock",
- "city": "Stoneville",
- "country": "USA",
- "state": "ID",
- "postalCode": "11111"
+ "city": "Atlanta"
},
"hasPreviousSahApplication": true
},
@@ -56,7 +46,6 @@
"view:militaryBaseDescription": {},
"street": "1111 Rock st.",
"street2": "Apartment 2",
- "street3": "Left door on the right",
"city": "APO",
"state": "AA",
"postalCode": "11111"
diff --git a/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/minimal-test.json b/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/minimal-test.json
index 4d6874541619..aea7e73cd124 100644
--- a/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/minimal-test.json
+++ b/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/minimal-test.json
@@ -33,7 +33,8 @@
"fullName": {
"first": "Barnie",
"last": "Rubble"
- }
+ },
+ "dateOfBirth": "2000-07-10"
}
}
}
diff --git a/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/transformed/maximal-test.json b/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/transformed/maximal-test.json
index f46b6f5a6bbe..7763a622b382 100644
--- a/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/transformed/maximal-test.json
+++ b/src/applications/simple-forms/26-4555/tests/e2e/fixtures/data/transformed/maximal-test.json
@@ -16,24 +16,14 @@
"previousHiApplication": {
"previousHiApplicationDate": "1999-02-04",
"previousHiApplicationAddress": {
- "street": "2222 Stone st",
- "street2": "Behind the big rock",
- "city": "Stoneville",
- "country": "USA",
- "state": "ID",
- "postalCode": "11111"
+ "city": "Atlanta"
},
"hasPreviousHiApplication": true
},
"previousSahApplication": {
"previousSahApplicationDate": "2000-06-10",
"previousSahApplicationAddress": {
- "street": "2222 Stone st.",
- "street2": "Behind the big rock",
- "city": "Stoneville",
- "country": "USA",
- "state": "ID",
- "postalCode": "11111"
+ "city": "Atlanta"
},
"hasPreviousSahApplication": true
},
@@ -46,7 +36,6 @@
"country": "USA",
"street": "1111 Rock st.",
"street2": "Apartment 2",
- "street3": "Left door on the right",
"city": "APO",
"state": "AA",
"postalCode": "11111"
diff --git a/src/applications/simple-forms/26-4555/tests/pages/contactInformation1.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/contactInformation1.unit.spec.jsx
index c5a1de531e55..6280559bd1d2 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/contactInformation1.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/contactInformation1.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,35 +11,46 @@ const {
uiSchema,
} = formConfig.chapters.contactInformationChapter.pages.contactInformation1;
-describe('contact information page 1', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'contact information page 1';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(8);
- });
+const data = {};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 7;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 4;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(getByRole('combobox', { name: /country/i }).value).to.exist;
- expect(errors).to.have.lengthOf(4);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/contactInformation2.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/contactInformation2.unit.spec.jsx
index 8aa8f7d95c66..e894632e1715 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/contactInformation2.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/contactInformation2.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,34 +11,46 @@ const {
uiSchema,
} = formConfig.chapters.contactInformationChapter.pages.contactInformation2;
-describe('contact information page 2', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'contact information page 2';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(3);
- });
+const data = {};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 3;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 1;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(1);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/livingSituation1.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/livingSituation1.unit.spec.jsx
index 4b9461ec1921..934fabeb9488 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/livingSituation1.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/livingSituation1.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,38 +11,50 @@ const {
uiSchema,
} = formConfig.chapters.livingSituationChapter.pages.livingSituation1;
-describe('living situation page 1', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'living situation page 1';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(2);
- });
+const data = {
+ livingSituation: {
+ isInCareFacility: true,
+ },
+};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 1;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 0;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(1);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/livingSituation2.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/livingSituation2.unit.spec.jsx
index 60aa5c751ab0..4e8c8ce82144 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/livingSituation2.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/livingSituation2.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,42 +11,50 @@ const {
uiSchema,
} = formConfig.chapters.livingSituationChapter.pages.livingSituation2;
-describe('living situation page 2', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'living situation page 2';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(7);
- });
+const data = {
+ livingSituation: {
+ isInCareFacility: true,
+ },
+};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 7;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 0;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(4);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/personalInformation1.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/personalInformation1.unit.spec.jsx
index b220705e3a8a..cfba9f05c7dd 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/personalInformation1.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/personalInformation1.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,34 +11,40 @@ const {
uiSchema,
} = formConfig.chapters.personalInformationChapter.pages.personalInformation1;
-describe('personal information page 1', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'personal information page 1';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(7);
- });
+const expectedNumberOfWebComponentFields = 4;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+);
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentErrors = 3;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(2);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/personalInformation2.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/personalInformation2.unit.spec.jsx
index ecec433b3959..062e2926745f 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/personalInformation2.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/personalInformation2.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,34 +11,48 @@ const {
uiSchema,
} = formConfig.chapters.personalInformationChapter.pages.personalInformation2;
-describe('personal information page 2', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'personal information page 2';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(2);
- });
+const data = {
+ previousSahApplication: {},
+};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 2;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 1;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(1);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication1.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication1.unit.spec.jsx
index a7d59d65f819..14bd0d7d129a 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication1.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication1.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,34 +11,48 @@ const {
uiSchema,
} = formConfig.chapters.previousApplicationsChapter.pages.previousShaApplication1;
-describe('previous HI information page 1', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'previous SHA information page 1';
- expect(container.querySelectorAll('input, selected')).to.have.lengthOf(2);
- });
+const data = {
+ previousSahApplication: {},
+};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 1;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 1;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(1);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication2.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication2.unit.spec.jsx
index baf6d643c450..5a9cbd6ab73d 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication2.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/previousHiApplication2.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,43 +11,50 @@ const {
uiSchema,
} = formConfig.chapters.previousApplicationsChapter.pages.previousShaApplication2;
-describe('previous HI information page 2', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'previous SHA information page 2';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(9);
- });
+const data = {
+ previousHiApplication: {
+ hasPreviousHiApplication: true,
+ },
+};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 2;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 0;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(getByRole('combobox', { name: /country/i }).value).to.exist;
- expect(errors).to.have.lengthOf(4);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication1.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication1.unit.spec.jsx
index 57bf465e9b93..77dd50838667 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication1.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication1.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,34 +11,46 @@ const {
uiSchema,
} = formConfig.chapters.previousApplicationsChapter.pages.previousSahApplication1;
-describe('previous SAH application 1', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'previous SAH application 1';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(2);
- });
+const data = {};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 1;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 1;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(1);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication2.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication2.unit.spec.jsx
index a139d39a9ae5..439b6a8ea8f5 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication2.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/previousSahApplication2.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,43 +11,50 @@ const {
uiSchema,
} = formConfig.chapters.previousApplicationsChapter.pages.previousSahApplication2;
-describe('previous SAH information page 2', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'previous SAH information page 2';
- expect(container.querySelectorAll('input, select')).to.have.lengthOf(9);
- });
+const data = {
+ previousSahApplication: {
+ hasPreviousSahApplication: true,
+ },
+};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 2;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 0;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(getByRole('combobox', { name: /country/i }).value).to.exist;
- expect(errors).to.have.lengthOf(4);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/26-4555/tests/pages/remarks.unit.spec.jsx b/src/applications/simple-forms/26-4555/tests/pages/remarks.unit.spec.jsx
index 797462d0e412..c85b5f1f2e5c 100644
--- a/src/applications/simple-forms/26-4555/tests/pages/remarks.unit.spec.jsx
+++ b/src/applications/simple-forms/26-4555/tests/pages/remarks.unit.spec.jsx
@@ -1,7 +1,9 @@
-import React from 'react';
-import { expect } from 'chai';
-import { render } from '@testing-library/react';
-import { DefinitionTester } from 'platform/testing/unit/schemaform-utils';
+import {
+ testNumberOfErrorsOnSubmit,
+ testNumberOfErrorsOnSubmitForWebComponents,
+ testNumberOfFields,
+ testNumberOfWebComponentFields,
+} from '../../../shared/tests/pages/pageTests.spec';
import formConfig from '../../config/form';
const {
@@ -9,36 +11,46 @@ const {
uiSchema,
} = formConfig.chapters.additionalInformationChapter.pages.remarks;
-describe('remarks page', () => {
- it('should have appropriate number of fields', () => {
- const { container } = render(
- ,
- );
+const pageTitle = 'remarks page';
- expect(
- container.querySelectorAll('input, select, textarea'),
- ).to.have.lengthOf(8);
- });
+const data = {};
- it('should show the correct number of errors on submit', () => {
- const { getByRole, queryAllByRole } = render(
- ,
- );
+const expectedNumberOfWebComponentFields = 8;
+testNumberOfWebComponentFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfWebComponentErrors = 0;
+testNumberOfErrorsOnSubmitForWebComponents(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfWebComponentErrors,
+ pageTitle,
+ data,
+);
- getByRole('button', { name: /submit/i }).click();
- const errors = queryAllByRole('alert');
- expect(errors).to.have.lengthOf(0);
- });
-});
+const expectedNumberOfFields = 0;
+testNumberOfFields(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfFields,
+ pageTitle,
+ data,
+);
+
+const expectedNumberOfErrors = 0;
+testNumberOfErrorsOnSubmit(
+ formConfig,
+ schema,
+ uiSchema,
+ expectedNumberOfErrors,
+ pageTitle,
+ data,
+);
diff --git a/src/applications/simple-forms/mock-simple-forms-patterns/pages/mockSelect.js b/src/applications/simple-forms/mock-simple-forms-patterns/pages/mockSelect.js
index d4cf49aa8ffc..1bee2434b5a4 100644
--- a/src/applications/simple-forms/mock-simple-forms-patterns/pages/mockSelect.js
+++ b/src/applications/simple-forms/mock-simple-forms-patterns/pages/mockSelect.js
@@ -1,10 +1,10 @@
-import VaSelectField from 'platform/forms-system/src/js/web-component-fields/VaSelectField';
-import VaTextInputField from 'platform/forms-system/src/js/web-component-fields/VaTextInputField';
import {
+ selectSchema,
+ selectUI,
inlineTitleSchema,
inlineTitleUI,
titleUI,
-} from 'platform/forms-system/src/js/web-component-patterns/titlePattern';
+} from 'platform/forms-system/src/js/web-component-patterns';
/** @type {PageSchema} */
export default {
@@ -42,93 +42,22 @@ export default {
},
},
},
- 'view:wcTitle': inlineTitleUI('Web component'),
- wcOldSelectFirst: {
- 'ui:title': 'title - select web component',
- 'ui:webComponentField': VaSelectField,
- 'ui:description': 'description',
- 'ui:hint': 'hint',
- 'ui:required': () => true,
- 'ui:errorMessages': {
- required: 'This is a custom error message.',
- },
- 'ui:disabled': 'true',
- 'ui:options': {
- disabled: true,
- uswds: false,
- labels: {
- option1: 'Option 1',
- option2: 'Option 2',
- },
- },
- },
- wcOldText: {
- 'ui:title': 'title - text web component',
- 'ui:webComponentField': VaTextInputField,
- 'ui:description': 'description',
- 'ui:hint': 'hint',
- 'ui:errorMessages': {
- required: 'This is a custom error message.',
- },
- },
- wcOldSelectSecond: {
- 'ui:title': 'title - select web component 2',
- 'ui:webComponentField': VaSelectField,
- 'ui:description': 'description',
- 'ui:required': () => true,
- 'ui:errorMessages': {
- required: 'This is a custom error message.',
- },
- 'ui:disabled': 'true',
- 'ui:options': {
- disabled: true,
- uswds: false,
- labels: {
- option1: 'Option 1',
- option2: 'Option 2',
- },
- },
- },
'view:wcv3Title': inlineTitleUI('Web component v3'),
- wcv3Text: {
- 'ui:title': 'title - text web component',
- 'ui:webComponentField': VaTextInputField,
- 'ui:description': 'description',
- 'ui:hint': 'hint',
- 'ui:errorMessages': {
- required: 'This is a custom error message.',
- },
- },
- wcv3Select: {
- 'ui:title': 'title - select web component 2',
- 'ui:webComponentField': VaSelectField,
- 'ui:description': 'description',
- 'ui:required': () => true,
- 'ui:errorMessages': {
+ wcv3SelectSimple: selectUI('Select simple'),
+ wcv3SelectValues: selectUI({
+ title: 'Select web component using labels literally as the value',
+ errorMessages: {
required: 'This is a custom error message.',
},
- 'ui:disabled': 'true',
- 'ui:options': {
- disabled: true,
- labels: {
- option1: 'Option 1',
- option2: 'Option 2',
- },
+ }),
+ wcv3SelectKeyValues: selectUI({
+ title: 'Select web component using key/value labels',
+ hint: 'This is a hint',
+ labels: {
+ option1: 'Option 1',
+ option2: 'Option 2',
},
- },
- selectWCDisabled: {
- 'ui:title': 'title - select web component USWDS',
- 'ui:webComponentField': VaSelectField,
- 'ui:description': 'description',
- 'ui:disabled': 'true',
- 'ui:options': {
- hint: 'This is a hint',
- labels: {
- option1: 'Option 1',
- option2: 'Option 2',
- },
- },
- },
+ }),
},
schema: {
type: 'object',
@@ -141,31 +70,11 @@ export default {
type: 'string',
enum: ['option1', 'option2'],
},
- 'view:wcTitle': inlineTitleSchema,
- wcOldSelectFirst: {
- type: 'string',
- enum: ['option1', 'option2'],
- },
- wcOldText: {
- type: 'string',
- },
- wcOldSelectSecond: {
- type: 'string',
- enum: ['option1', 'option2'],
- },
'view:wcv3Title': inlineTitleSchema,
- wcv3Text: {
- type: 'string',
- },
- wcv3Select: {
- type: 'string',
- enum: ['option1', 'option2'],
- },
- selectWCDisabled: {
- type: 'string',
- enum: ['option1', 'option2'],
- },
+ wcv3SelectSimple: selectSchema(['Option 1', 'Option 2']),
+ wcv3SelectValues: selectSchema(['Option 1', 'Option 2']),
+ wcv3SelectKeyValues: selectSchema(['option1', 'option2']),
},
- required: [],
+ required: ['selectDefault', 'wcv3SelectSimple'],
},
};
diff --git a/src/applications/simple-forms/mock-simple-forms-patterns/tests/e2e/fixtures/data/default.json b/src/applications/simple-forms/mock-simple-forms-patterns/tests/e2e/fixtures/data/default.json
index 9910fb849df3..0b752897c371 100644
--- a/src/applications/simple-forms/mock-simple-forms-patterns/tests/e2e/fixtures/data/default.json
+++ b/src/applications/simple-forms/mock-simple-forms-patterns/tests/e2e/fixtures/data/default.json
@@ -9,9 +9,9 @@
"wcv3IsCurrentlyActiveDuty": true,
"amountOrNumber": "123",
"selectDefault": "option1",
- "wcOldSelectFirst": "option1",
- "wcOldSelectSecond": "option1",
- "wcv3Select": "option1",
+ "wcv3SelectSimple": "Option 1",
+ "wcv3SelectValues": "Option 1",
+ "wcv3SelectKeyValues": "option1",
"wcv3TextEmailNew": "abc@abc.com",
"rjsfCheckSimpleTextInput": "Lorem ipsum dolor sit amet",
"rjsfCheckRequiredCheckbox": true,
diff --git a/src/applications/simple-forms/mock-simple-forms-patterns/tests/pages/mockSelect.unit.spec.jsx b/src/applications/simple-forms/mock-simple-forms-patterns/tests/pages/mockSelect.unit.spec.jsx
index 90032cfb7d2d..a00b11129fec 100644
--- a/src/applications/simple-forms/mock-simple-forms-patterns/tests/pages/mockSelect.unit.spec.jsx
+++ b/src/applications/simple-forms/mock-simple-forms-patterns/tests/pages/mockSelect.unit.spec.jsx
@@ -10,7 +10,7 @@ const { schema, uiSchema } = formConfig.chapters.select.pages.select;
const pageTitle = 'mock select inputs';
-const expectedNumberOfWebComponentFields = 6;
+const expectedNumberOfWebComponentFields = 3;
testNumberOfWebComponentFields(
formConfig,
schema,
@@ -19,7 +19,7 @@ testNumberOfWebComponentFields(
pageTitle,
);
-const expectedNumberOfWebComponentErrors = 3;
+const expectedNumberOfWebComponentErrors = 1;
testNumberOfErrorsOnSubmitForWebComponents(
formConfig,
schema,
diff --git a/src/platform/forms-system/src/js/web-component-patterns/addressPattern.jsx b/src/platform/forms-system/src/js/web-component-patterns/addressPattern.jsx
index f50fb733a9c5..3c7e898254ed 100644
--- a/src/platform/forms-system/src/js/web-component-patterns/addressPattern.jsx
+++ b/src/platform/forms-system/src/js/web-component-patterns/addressPattern.jsx
@@ -203,13 +203,13 @@ export const updateFormDataAddress = (
* ```
* @param {{
* labels?: {
- * militaryCheckbox?: string
+ * militaryCheckbox?: string,
* street?: string,
* street2?: string,
* street3?: string,
- * }},
+ * },
* omit?: Array,
- * required?: Record boolean>
+ * required?: boolean | Record boolean>
* }} [options]
* @returns {UISchemaOptions}
*/
@@ -218,7 +218,10 @@ export function addressUI(options) {
let cityMaxLength = 100;
const omit = key => options?.omit?.includes(key);
- const customRequired = key => options?.required?.[key];
+ let customRequired = key => options?.required?.[key];
+ if (options?.required === false) {
+ customRequired = () => () => false;
+ }
/** @type {UISchemaOptions} */
const uiSchema = {};
@@ -564,9 +567,9 @@ export const addressSchema = options => {
* street?: string,
* street2?: string,
* street3?: string,
- * }},
+ * },
* omit?: Array,
- * required?: Record boolean>
+ * required?: boolean | Record boolean>
* }} [options]
* @returns {UISchemaOptions}
*/
diff --git a/src/platform/forms-system/src/js/web-component-patterns/index.js b/src/platform/forms-system/src/js/web-component-patterns/index.js
index 54d4290fe8c5..f4b9771c2666 100644
--- a/src/platform/forms-system/src/js/web-component-patterns/index.js
+++ b/src/platform/forms-system/src/js/web-component-patterns/index.js
@@ -8,6 +8,7 @@ export * from './phonePattern';
export * from './relationshipToVeteranPattern';
export * from './radioPattern';
export * from './arnPattern';
+export * from './selectPattern';
export * from './ssnPattern';
export * from './titlePattern';
export * from './yesNoPattern';
diff --git a/src/platform/forms-system/src/js/web-component-patterns/selectPattern.jsx b/src/platform/forms-system/src/js/web-component-patterns/selectPattern.jsx
new file mode 100644
index 000000000000..b14c58c2313c
--- /dev/null
+++ b/src/platform/forms-system/src/js/web-component-patterns/selectPattern.jsx
@@ -0,0 +1,72 @@
+import VaSelectField from '../web-component-fields/VaSelectField';
+
+/**
+ * Web component v3 uiSchema for generic select field
+ *
+ * ```js
+ * // uiSchema
+ * exampleSelect: selectUI('Select animal')
+ * exampleSelect: selectUI({
+ * title: 'Select animal',
+ * hint: 'This is a hint',
+ * })
+ *
+ * // schema:
+ * exampleSelect: selectSchema(['Cat', 'Dog', 'Octopus'])
+ *
+ * // or with labels defined:
+ * // uiSchema
+ * exampleSelect: selectSchema({
+ * title: 'Select animal',
+ * labels: {
+ * cat: 'Cat',
+ * dog: 'Dog',
+ * octopus: 'Octopus',
+ * },
+ * errorMessages: {
+ * required: 'Please select an animal',
+ * },
+ * })
+ *
+ * // schema
+ * exampleSelect: selectSchema(['cat', 'dog', 'octopus'])
+ * ```
+ *
+ * @param {string | UIOptions & {
+ * title?: UISchemaOptions['ui:title'],
+ * errorMessages?: UISchemaOptions['ui:errorMessages'],
+ * labelHeaderLevel?: UISchemaOptions['ui:options']['labelHeaderLevel'],
+ * hint?: string,
+ * labels?: UISchemaOptions['ui:options']['labels'],
+ * }} options
+ * @returns {UISchemaOptions}
+ */
+export const selectUI = options => {
+ const { title, description, errorMessages, ...uiOptions } =
+ typeof options === 'object' ? options : { title: options };
+
+ return {
+ 'ui:title': title,
+ 'ui:description': description,
+ 'ui:webComponentField': VaSelectField,
+ 'ui:options': {
+ ...uiOptions,
+ },
+ 'ui:errorMessages': errorMessages,
+ };
+};
+
+/**
+ * ```js
+ * exampleSelect: selectSchema(['Cat', 'Dog', 'Octopus'])
+ * exampleSelect: selectSchema(['cat', 'dog', 'octopus'])
+ * ```
+ * @param {string[]} labels
+ * @returns {SchemaOptions}
+ */
+export const selectSchema = labels => {
+ return {
+ type: 'string',
+ enum: labels,
+ };
+};
diff --git a/src/platform/forms-system/src/js/web-component-patterns/yesNoPattern.jsx b/src/platform/forms-system/src/js/web-component-patterns/yesNoPattern.jsx
index 7e92e89b6b72..8655f7cda45e 100644
--- a/src/platform/forms-system/src/js/web-component-patterns/yesNoPattern.jsx
+++ b/src/platform/forms-system/src/js/web-component-patterns/yesNoPattern.jsx
@@ -23,6 +23,7 @@ import YesNoField from '../web-component-fields/YesNoField';
* tile?: boolean,
* yesNoReverse?: boolean,
* hint?: string,
+ * errorMessages?: UISchemaOptions['ui:errorMessages'],
* labelHeaderLevel?: UISchemaOptions['ui:options']['labelHeaderLevel'],
* }} options - a string to use as the title or an object with options
* @returns {UISchemaOptions}
From 3a529e50e0c3ddf62a675124f1a34241474d7462 Mon Sep 17 00:00:00 2001
From: Brian Seek
Date: Wed, 28 Feb 2024 12:45:12 -0800
Subject: [PATCH 49/51] Fetch travel (#28223)
* created new hook and added loading page.
* passing facility type to endpoint.
* Added travel action and reducer.
* added mock data and refined actions and added selectors
* using selector for appointments.
* removed travel data hook and combined it with useGetCheckInData and updated reload.
* updated day-of fac type to match the default of null.
* updated reducer tests.
* Updated project README for travel-claim.
* refactored to be less complex.
---
src/applications/check-in/README.md | 12 +-
.../check-in/actions/travel-claim/index.js | 8 +
.../check-in/api/local-mock-api/index.js | 4 +
.../mocks/v2/check-in-data/get.js | 54 -----
.../mocks/v2/check-in-data/index.js | 2 -
.../api/local-mock-api/mocks/v2/shared/get.js | 101 +++++++++-
src/applications/check-in/api/versions/v2.js | 9 +-
.../components/layout/ReloadWrapper.jsx | 10 +-
.../CheckIn/DisplayMultipleAppointments.jsx | 4 +-
.../Confirmation/CheckInConfirmation.jsx | 2 +-
.../day-of/pages/LoadingPage/index.jsx | 3 +-
src/applications/check-in/day-of/routes.jsx | 2 +-
.../check-in/hooks/useGetCheckInData.jsx | 185 +++++++++++-------
.../pre-check-in/pages/Introduction/index.jsx | 4 +-
.../check-in/pre-check-in/routes.jsx | 2 +-
src/applications/check-in/reducers/index.js | 6 +
.../check-in/reducers/reducer.unit.spec.js | 1 +
.../check-in/reducers/travel-claim/index.js | 10 +
.../travel-claim.reducers.unit.spec.js | 55 ++++++
src/applications/check-in/selectors/index.js | 16 ++
.../check-in/selectors/selector.unit.spec.js | 26 +++
.../travel-claim/pages/LoadingPage/index.jsx | 55 ++++++
.../travel-claim/pages/travel-intro/index.jsx | 17 +-
.../travel-intro/travelIntro.unit.spec.js | 6 +-
.../check-in/travel-claim/routes.jsx | 17 +-
.../utils/navigation/travel-claim/index.js | 4 +
26 files changed, 463 insertions(+), 152 deletions(-)
create mode 100644 src/applications/check-in/actions/travel-claim/index.js
delete mode 100644 src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/get.js
create mode 100644 src/applications/check-in/reducers/travel-claim/index.js
create mode 100644 src/applications/check-in/reducers/travel-claim/travel-claim.reducers.unit.spec.js
create mode 100644 src/applications/check-in/travel-claim/pages/LoadingPage/index.jsx
diff --git a/src/applications/check-in/README.md b/src/applications/check-in/README.md
index 9d8296b917c1..b0bc4a7b6c66 100644
--- a/src/applications/check-in/README.md
+++ b/src/applications/check-in/README.md
@@ -14,10 +14,11 @@ Before you get started check [this page](https://depo-platform-documentation.scr
- run `yarn install`
- run `yarn workspace @department-of-veterans-affairs/applications-check-in install`
- turn on local mocks `yarn --cwd $( git rev-parse --show-toplevel ) mock-api --responses src/applications/check-in/api/local-mock-api/index.js`
- - start app `yarn --cwd $( git rev-parse --show-toplevel ) watch --env entry=check-in,pre-check-in`
+ - start app `yarn --cwd $( git rev-parse --show-toplevel ) watch --env entry=check-in,pre-check-in,travel-claim`
- visit the app:
- check-in `http://localhost:3001/health-care/appointment-check-in/?id=46bebc0a-b99c-464f-a5c5-560bc9eae287`
- pre-check-in `http://localhost:3001/health-care/appointment-pre-check-in/?id=46bebc0a-b99c-464f-a5c5-560bc9eae287`
+ - travel-claim `http://localhost:3001/my-health/appointment-travel-claim/?id=46bebc0a-b99c-464f-a5c5-560bc9eae287`
- Login using the mock user, Last name: `Smith` DOB: `04-07-1935`
## Mock UUIDs
@@ -44,6 +45,11 @@ There are several different mock UUIDs that can be used as a value for the `id`
- allDemographicsCurrentUUID: `e544c217-6fe8-44c5-915f-6c3d9908a678`
- onlyDemographicsCurrentUUID: `7397abc0-fb4d-4238-a3e2-32b0e47a1527` (NoK and Emergency Contact not current)
+### Travel-claim
+ - defaultUUID: `46bebc0a-b99c-464f-a5c5-560bc9eae287`
+ - multiApptSingleFacilityUUID: `d80ade2e-7a96-4a30-9edc-efc08b4d157d`
+ - multiApptMultiFacilityUUID: `8379d4b5-b9bc-4f3f-84a2-9cb9983a1af0`
+
## Design system
99% of the styling comes from the VA design system [component library](https://design.va.gov/components/) and [utility classes](https://design.va.gov/foundation/utilities/). For the remaining 1% of styling there is an scss file in the `sass` directory in the project root.
@@ -101,10 +107,12 @@ Merging your PR may mean merging to a feature branch. Always be aware that anyth
If you have any questions along the way be sure to ask in slack.
## How it works
-Check-in allows veterans to check into an appointment on the day of their appointment while physically at a VA clinic. The veteran texts `check-in` to `VEText` and gets returned a short-url that re-directs to the check-in application with a unique UUID for the appointment.
+Check-in allows veterans to check into an appointment on the day of their appointment while physically at a VA clinic. They also get the opportunity to file a mileage only travel-claim if they are eligible. The veteran texts `check-in` to `VEText` and gets returned a short-url that re-directs to the check-in application with a unique UUID for the appointment.
Pre-check-in allows veterans to pre-check into an appointment between 1 -7 days ahead of the appointment. This usually happens when the veteran is not at a VA clinic. The vet will receive a text from `VEText` with a short-url that re-directs to the pre-check-in application with a unique UUID for the appointment.
+Travel-claim allows veterans to file a mileage only travel claim on the day of the appointment they are filing for. The veteran texts `travel` to `VEText` and gets returned a short-url that re-directs to the travel-claim application with a unique UUID for the appointment.
+
## Generating screenshots with Cypress
We use Cypress to capture screenshots of each page of this application. The screenshot capturing is conditional on the env variable `with_screenshots` and won't run in CI. The following commands will generate screenshots in the `vets-website/cypress/screenshots` directory, these are to be run headless with out the Cypress GUI running.
diff --git a/src/applications/check-in/actions/travel-claim/index.js b/src/applications/check-in/actions/travel-claim/index.js
new file mode 100644
index 000000000000..d0d35fe30db4
--- /dev/null
+++ b/src/applications/check-in/actions/travel-claim/index.js
@@ -0,0 +1,8 @@
+export const RECEIVED_TRAVEL_DATA = 'RECEIVED_TRAVEL_DATA';
+
+export const receivedTravelData = payload => {
+ return {
+ type: RECEIVED_TRAVEL_DATA,
+ payload,
+ };
+};
diff --git a/src/applications/check-in/api/local-mock-api/index.js b/src/applications/check-in/api/local-mock-api/index.js
index e598e3f65f72..a1c78e4d6a7c 100644
--- a/src/applications/check-in/api/local-mock-api/index.js
+++ b/src/applications/check-in/api/local-mock-api/index.js
@@ -55,6 +55,10 @@ const responses = {
},
'GET /check_in/v2/patient_check_ins/:uuid': (req, res) => {
const { uuid } = req.params;
+ const { facilityType } = req.query;
+ if (facilityType === 'oh') {
+ return res.json(sharedData.get.createAppointmentsOH(uuid));
+ }
if (uuid === demographicsConfirmedUUID) {
const yesterday = dateFns.sub(new Date(), { days: -1 }).toISOString();
return res.json(
diff --git a/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/get.js b/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/get.js
deleted file mode 100644
index c2c0ae20433c..000000000000
--- a/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/get.js
+++ /dev/null
@@ -1,54 +0,0 @@
-const { mockDemographics, defaultUUID } = require('../shared/get');
-
-const createMockSuccessResponse = (
- data,
- hasBeenValidated,
- demographicsNeedsUpdate = false,
- demographicsConfirmedAt = null,
- nextOfKinNeedsUpdate = false,
- nextOfKinConfirmedAt = null,
- emergencyContactNeedsUpdate = false,
- emergencyContactConfirmedAt = null,
-) => {
- const rv = {
- id: data.id || defaultUUID,
- payload: {
- demographics: {
- mailingAddress: mockDemographics.mailingAddress,
- homeAddress: mockDemographics.homeAddress,
- homePhone: mockDemographics.homePhone,
- mobilePhone: mockDemographics.mobilePhone,
- workPhone: mockDemographics.workPhone,
- emailAddress: mockDemographics,
- },
- appointments: [
- {
- facility: 'LOMA LINDA VA CLINIC',
- clinicPhoneNumber: '5551234567',
- clinicFriendlyName: 'HEART CLINIC 1',
- clinicName: 'LOM ACC CLINIC TEST',
- appointmentIen: '0001',
- stationNo: '0001',
- },
- ],
- patientDemographicsStatus: {
- demographicsNeedsUpdate,
- demographicsConfirmedAt,
- nextOfKinNeedsUpdate,
- nextOfKinConfirmedAt,
- emergencyContactNeedsUpdate,
- emergencyContactConfirmedAt,
- },
- setECheckinStartedCalled: true,
- },
- };
- if (hasBeenValidated) {
- rv.payload.appointments[0].startTime = '2021-08-19T13:56:31';
- rv.payload.appointments[0].eligibility = 'ELIGIBLE';
- }
- return rv;
-};
-
-module.exports = {
- createMockSuccessResponse,
-};
diff --git a/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/index.js b/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/index.js
index 7b35e4be226a..01a1ced336e8 100644
--- a/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/index.js
+++ b/src/applications/check-in/api/local-mock-api/mocks/v2/check-in-data/index.js
@@ -1,9 +1,7 @@
-const get = require('./get');
const post = require('./post');
const patch = require('./patch');
module.exports = {
- get: { ...get },
post: { ...post },
patch: { ...patch },
};
diff --git a/src/applications/check-in/api/local-mock-api/mocks/v2/shared/get.js b/src/applications/check-in/api/local-mock-api/mocks/v2/shared/get.js
index b7284d42bbe9..d2d13b1f7c78 100644
--- a/src/applications/check-in/api/local-mock-api/mocks/v2/shared/get.js
+++ b/src/applications/check-in/api/local-mock-api/mocks/v2/shared/get.js
@@ -8,12 +8,17 @@ const {
const isoDateWithoutTimezoneFormat = "yyyy-LL-dd'T'HH:mm:ss";
const isoDateWithOffsetFormat = "yyyy-LL-dd'T'HH:mm:ss.SSSxxx";
-// check in UUIDS
const defaultUUID = '46bebc0a-b99c-464f-a5c5-560bc9eae287';
+
+// check in UUIDS
const aboutToExpireUUID = '25165847-2c16-4c8b-8790-5de37a7f427f';
const pacificTimezoneUUID = '6c72b801-74ac-47fe-82af-cfe59744b45f';
const allAppointmentTypesUUID = 'bb48c558-7b35-44ec-8ab7-32b7d49364fc';
+// travel-claim UUIDS
+const multiApptSingleFacilityUUID = 'd80ade2e-7a96-4a30-9edc-efc08b4d157d';
+const multiApptMultiFacilityUUID = '8379d4b5-b9bc-4f3f-84a2-9cb9983a1af0';
+
// Minutes before start time that the window for check-in starts.
const checkInStartWindowMinutes = 45;
@@ -268,9 +273,103 @@ const createMockNotFoundResponse = () => {
};
};
+const createAppointmentOH = ({
+ appointmentIen = '1111',
+ type = 'Endoscopy',
+ clinicPhoneNumber = '555-555-5555',
+ facility = 'Example Veterans Hospital',
+ facilityAddress = {
+ street1: '12345 Main St',
+ street2: 'Suite 100',
+ street3: 'Box #3',
+ city: 'Washington',
+ state: 'DC',
+ zip: '20002',
+ },
+ stationNo = '530',
+ clinicIen = '32216049',
+ clinicLocation = '',
+ doctorName = 'Dr. Smith',
+ kind = 'clinic',
+ startTime = new Date().toISOString(),
+ status = 'Confirmed',
+ timezone = 'America/Los_Angeles',
+} = {}) => {
+ return {
+ facility,
+ kind,
+ clinicPhoneNumber,
+ clinicFriendlyName: type,
+ clinicName: type,
+ appointmentIen,
+ startTime,
+ status,
+ stationNo,
+ clinicLocation,
+ clinicStopCodeName: type,
+ doctorName,
+ clinicIen,
+ facilityAddress,
+ timezone,
+ };
+};
+
+const createAppointmentsOH = (token = defaultUUID) => {
+ const appointments = [createAppointmentOH()];
+
+ if (token === multiApptSingleFacilityUUID) {
+ appointments.push(
+ createAppointmentOH({
+ appointmentIen: '2222',
+ startTime: dateFns.addHours(new Date(), 1).toISOString(),
+ type: 'Mental Health',
+ }),
+ );
+ }
+
+ if (token === multiApptMultiFacilityUUID) {
+ appointments.push(
+ createAppointmentOH({
+ appointmentIen: '2222',
+ startTime: dateFns.addHours(new Date(), 1).toISOString(),
+ type: 'Mental Health',
+ }),
+ createAppointmentOH({
+ appointmentIen: '1111',
+ startTime: dateFns.addHours(new Date(), 2).toISOString(),
+ type: 'Primary Care',
+ stationNo: '500',
+ facility: 'VA Facility 2',
+ }),
+ createAppointmentOH({
+ appointmentIen: '2222',
+ startTime: dateFns.addHours(new Date(), 3).toISOString(),
+ type: 'Anesthesiology',
+ stationNo: '500',
+ facility: 'VA Facility 2',
+ }),
+ createAppointmentOH({
+ appointmentIen: '6767',
+ startTime: dateFns.addHours(new Date(), 4).toISOString(),
+ type: 'Neurology',
+ station: '622',
+ facility: 'VA Facility 3',
+ }),
+ );
+ }
+ return {
+ id: token,
+ payload: {
+ appointments,
+ address: '1166 6th Avenue\n22\nNew York, NY 23423\nUS',
+ },
+ };
+};
+
module.exports = {
aboutToExpireUUID,
createAppointments,
+ createAppointmentsOH,
createAppointment,
defaultUUID,
mockDemographics,
diff --git a/src/applications/check-in/api/versions/v2.js b/src/applications/check-in/api/versions/v2.js
index 38b647362773..b32bdc133e50 100644
--- a/src/applications/check-in/api/versions/v2.js
+++ b/src/applications/check-in/api/versions/v2.js
@@ -56,9 +56,14 @@ const v2 = {
};
},
- getCheckInData: async token => {
+ getCheckInData: async (token, facilityType = null) => {
const url = '/check_in/v2/patient_check_ins/';
- const requestUrl = `${environment.API_URL}${url}${token}`;
+ let requestUrl = `${environment.API_URL}${url}${token}`;
+ if (facilityType) {
+ requestUrl = appendQuery(requestUrl, {
+ facilityType,
+ });
+ }
const json = await makeApiCallWithSentry(
apiRequest(requestUrl),
'get-lorota-data',
diff --git a/src/applications/check-in/components/layout/ReloadWrapper.jsx b/src/applications/check-in/components/layout/ReloadWrapper.jsx
index 3c1493deb245..3ba322cab5fe 100644
--- a/src/applications/check-in/components/layout/ReloadWrapper.jsx
+++ b/src/applications/check-in/components/layout/ReloadWrapper.jsx
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import { useSelector, useDispatch } from 'react-redux';
+import { APP_NAMES } from '../../utils/appConstants';
import { makeSelectCurrentContext, makeSelectForm } from '../../selectors';
import { setForm } from '../../actions/universal';
import { createSetSession } from '../../actions/authentication';
@@ -11,16 +12,17 @@ import { useGetCheckInData } from '../../hooks/useGetCheckInData';
import { useUpdateError } from '../../hooks/useUpdateError';
const ReloadWrapper = props => {
- const { children, router, isPreCheckIn } = props;
+ const { children, router, app } = props;
const location = window.location.pathname;
const { t } = useTranslation();
const dispatch = useDispatch();
+ // @TODO change this when useStorage gets refactored to no use isPreCheckIn
const {
getProgressState,
setProgressState,
getCurrentToken,
getPermissions,
- } = useStorage(isPreCheckIn);
+ } = useStorage(app === APP_NAMES.PRE_CHECK_IN);
const selectCurrentContext = useMemo(makeSelectCurrentContext, []);
const selectForm = useMemo(makeSelectForm, []);
const currentForm = useSelector(selectForm);
@@ -32,7 +34,7 @@ const ReloadWrapper = props => {
appointmentsOnly: true,
reload: true,
router,
- isPreCheckIn,
+ app,
},
);
const [refreshData, setRefreshData] = useState(true);
@@ -100,8 +102,8 @@ const ReloadWrapper = props => {
};
ReloadWrapper.propTypes = {
+ app: PropTypes.string.isRequired,
children: PropTypes.node,
- isPreCheckIn: PropTypes.bool,
router: PropTypes.object,
};
diff --git a/src/applications/check-in/day-of/pages/CheckIn/DisplayMultipleAppointments.jsx b/src/applications/check-in/day-of/pages/CheckIn/DisplayMultipleAppointments.jsx
index 36c8144788b9..3ed93e2eb184 100644
--- a/src/applications/check-in/day-of/pages/CheckIn/DisplayMultipleAppointments.jsx
+++ b/src/applications/check-in/day-of/pages/CheckIn/DisplayMultipleAppointments.jsx
@@ -6,7 +6,7 @@ import { focusElement } from '@department-of-veterans-affairs/platform-utilities
import { recordEvent } from '@department-of-veterans-affairs/platform-monitoring/exports';
import { useTranslation, Trans } from 'react-i18next';
import { useGetCheckInData } from '../../../hooks/useGetCheckInData';
-
+import { APP_NAMES } from '../../../utils/appConstants';
import BackButton from '../../../components/BackButton';
import AppointmentBlock from '../../../components/AppointmentBlock';
import { useFormRouting } from '../../../hooks/useFormRouting';
@@ -38,7 +38,7 @@ const DisplayMultipleAppointments = props => {
{
refreshNeeded: shouldRefresh,
appointmentsOnly: true,
- isPreCheckIn: false,
+ app: APP_NAMES.CHECK_IN,
},
);
diff --git a/src/applications/check-in/day-of/pages/Confirmation/CheckInConfirmation.jsx b/src/applications/check-in/day-of/pages/Confirmation/CheckInConfirmation.jsx
index b9772e86c33d..058e407d5a6d 100644
--- a/src/applications/check-in/day-of/pages/Confirmation/CheckInConfirmation.jsx
+++ b/src/applications/check-in/day-of/pages/Confirmation/CheckInConfirmation.jsx
@@ -35,7 +35,7 @@ const CheckInConfirmation = props => {
} = useGetCheckInData({
refreshNeeded: false,
appointmentsOnly: true,
- isPreCheckIn: false,
+ app: APP_NAMES.CHECK_IN,
});
const { updateError } = useUpdateError();
const { t } = useTranslation();
diff --git a/src/applications/check-in/day-of/pages/LoadingPage/index.jsx b/src/applications/check-in/day-of/pages/LoadingPage/index.jsx
index cdbc2df43bc5..a7b4861b0005 100644
--- a/src/applications/check-in/day-of/pages/LoadingPage/index.jsx
+++ b/src/applications/check-in/day-of/pages/LoadingPage/index.jsx
@@ -1,6 +1,7 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
+import { APP_NAMES } from '../../../utils/appConstants';
import { useGetCheckInData } from '../../../hooks/useGetCheckInData';
import { useFormRouting } from '../../../hooks/useFormRouting';
import { useUpdateError } from '../../../hooks/useUpdateError';
@@ -13,7 +14,7 @@ const LoadingPage = props => {
const { checkInDataError, isComplete } = useGetCheckInData({
refreshNeeded: true,
- isPreCheckIn: false,
+ app: APP_NAMES.CHECK_IN,
});
const { updateError } = useUpdateError();
diff --git a/src/applications/check-in/day-of/routes.jsx b/src/applications/check-in/day-of/routes.jsx
index 740b91f3dffd..2dae137cda3e 100644
--- a/src/applications/check-in/day-of/routes.jsx
+++ b/src/applications/check-in/day-of/routes.jsx
@@ -196,7 +196,7 @@ const createRoutesWithStore = () => {
if (route.reloadable) {
// If the page is able to restore state on reload add the wrapper.
return (
-
+
);
diff --git a/src/applications/check-in/hooks/useGetCheckInData.jsx b/src/applications/check-in/hooks/useGetCheckInData.jsx
index 9ef874a29274..9d6a64c61b3b 100644
--- a/src/applications/check-in/hooks/useGetCheckInData.jsx
+++ b/src/applications/check-in/hooks/useGetCheckInData.jsx
@@ -16,6 +16,8 @@ import {
additionalContext,
} from '../actions/day-of';
+import { receivedTravelData } from '../actions/travel-claim';
+
import {
preCheckinExpired,
appointmentWasCanceled,
@@ -34,7 +36,7 @@ const useGetCheckInData = ({
appointmentsOnly = false,
reload = false,
router,
- isPreCheckIn = false,
+ app,
}) => {
const [isLoading, setIsLoading] = useState(false);
const [isStale, setIsStale] = useState(refreshNeeded);
@@ -112,77 +114,119 @@ const useGetCheckInData = ({
},
[dispatch, reload],
);
+
+ const setTravelData = useCallback(
+ payload => {
+ batch(() => {
+ dispatch(receivedTravelData(payload));
+ });
+ },
+ [dispatch],
+ );
+ const fetchPreCheckIn = useCallback(
+ () => {
+ api.v2
+ .getPreCheckInData(token, reload)
+ .then(json => {
+ if (json.error) {
+ updateError('error-getting-pre-check-in-data');
+ return; // prevent a react no-op on an unmounted component
+ }
+ const { payload } = json;
+ setPreCheckInData(payload);
+
+ if (payload.appointments?.length > 0) {
+ if (appointmentStartTimePast15(payload.appointments)) {
+ updateError('pre-check-in-past-appointment');
+ return;
+ }
+ if (preCheckinExpired(payload.appointments)) {
+ updateError('pre-check-in-expired');
+ return;
+ }
+ }
+
+ if (appointmentWasCanceled(payload.appointments)) {
+ updateError('possible-canceled-appointment');
+ return;
+ }
+
+ if (allAppointmentsCanceled(payload.appointments)) {
+ updateError('appointment-canceled');
+ return;
+ }
+
+ if (preCheckinAlreadyCompleted(payload.appointments)) {
+ setPreCheckinComplete(window, true);
+ jumpToPage(URLS.COMPLETE);
+ }
+ })
+ .catch(e => {
+ if (e.errors && e?.errors[0]?.status === '404') {
+ updateError('uuid-not-found');
+ } else {
+ setCheckInDataError(true);
+ }
+ })
+ .finally(() => {
+ setIsStale(false);
+ setIsComplete(true);
+ setIsLoading(false);
+ });
+ },
+ [
+ jumpToPage,
+ reload,
+ setPreCheckInData,
+ setPreCheckinComplete,
+ token,
+ updateError,
+ ],
+ );
+
+ const fetchDayOfOrTravel = useCallback(
+ facilityType => {
+ api.v2
+ .getCheckInData(token, facilityType)
+ .then(json => {
+ if (app === 'travelClaim') {
+ setTravelData(json.payload);
+ } else {
+ setDayOfData(json.payload);
+ }
+ })
+ .catch(e => {
+ if (e.errors && e.errors[0]?.status === '404') {
+ updateError('uuid-not-found');
+ } else {
+ setCheckInDataError(true);
+ }
+ })
+ .finally(() => {
+ setIsStale(false);
+ setIsComplete(true);
+ setIsLoading(false);
+ });
+ },
+ [app, setDayOfData, setTravelData, token, updateError],
+ );
+
useLayoutEffect(
() => {
if (isStale && token && !isLoading) {
setIsLoading(true);
- if (isPreCheckIn) {
- api.v2
- .getPreCheckInData(token, reload)
- .then(json => {
- if (json.error) {
- updateError('error-getting-pre-check-in-data');
- return; // prevent a react no-op on an unmounted component
- }
- const { payload } = json;
- setPreCheckInData(payload);
-
- if (payload.appointments?.length > 0) {
- if (appointmentStartTimePast15(payload.appointments)) {
- updateError('pre-check-in-past-appointment');
- return;
- }
- if (preCheckinExpired(payload.appointments)) {
- updateError('pre-check-in-expired');
- return;
- }
- }
-
- if (appointmentWasCanceled(payload.appointments)) {
- updateError('possible-canceled-appointment');
- return;
- }
-
- if (allAppointmentsCanceled(payload.appointments)) {
- updateError('appointment-canceled');
- return;
- }
-
- if (preCheckinAlreadyCompleted(payload.appointments)) {
- setPreCheckinComplete(window, true);
- jumpToPage(URLS.COMPLETE);
- }
- })
- .catch(e => {
- if (e.errors && e?.errors[0]?.status === '404') {
- updateError('uuid-not-found');
- } else {
- setCheckInDataError(true);
- }
- })
- .finally(() => {
- setIsStale(false);
- setIsComplete(true);
- setIsLoading(false);
- });
- } else {
- api.v2
- .getCheckInData(token)
- .then(json => {
- setDayOfData(json.payload);
- })
- .catch(e => {
- if (e.errors && e.errors[0]?.status === '404') {
- updateError('uuid-not-found');
- } else {
- setCheckInDataError(true);
- }
- })
- .finally(() => {
- setIsStale(false);
- setIsComplete(true);
- setIsLoading(false);
- });
+ switch (app) {
+ case 'preCheckIn':
+ fetchPreCheckIn();
+ break;
+ case 'dayOf':
+ fetchDayOfOrTravel(null);
+ break;
+ case 'travelClaim':
+ fetchDayOfOrTravel('oh');
+ break;
+ default:
+ break;
}
}
},
@@ -192,11 +236,14 @@ const useGetCheckInData = ({
token,
isLoading,
reload,
- isPreCheckIn,
updateError,
jumpToPage,
setPreCheckInData,
setPreCheckinComplete,
+ app,
+ setTravelData,
+ fetchPreCheckIn,
+ fetchDayOfOrTravel,
],
);
diff --git a/src/applications/check-in/pre-check-in/pages/Introduction/index.jsx b/src/applications/check-in/pre-check-in/pages/Introduction/index.jsx
index c753b10cd519..3ff0ef0c2058 100644
--- a/src/applications/check-in/pre-check-in/pages/Introduction/index.jsx
+++ b/src/applications/check-in/pre-check-in/pages/Introduction/index.jsx
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
-
+import { APP_NAMES } from '../../../utils/appConstants';
import IntroductionDisplay from './IntroductionDisplay';
import { useGetCheckInData } from '../../../hooks/useGetCheckInData';
@@ -23,7 +23,7 @@ const Introduction = props => {
refreshNeeded: false,
reload: false,
router,
- isPreCheckIn: true,
+ app: APP_NAMES.PRE_CHECK_IN,
});
useEffect(
diff --git a/src/applications/check-in/pre-check-in/routes.jsx b/src/applications/check-in/pre-check-in/routes.jsx
index 1d748eab613a..e12f7588742c 100644
--- a/src/applications/check-in/pre-check-in/routes.jsx
+++ b/src/applications/check-in/pre-check-in/routes.jsx
@@ -125,7 +125,7 @@ const createRoutesWithStore = () => {
/* eslint-disable react/jsx-props-no-spreading */
if (route.reloadable) {
return (
-
+
);
diff --git a/src/applications/check-in/reducers/index.js b/src/applications/check-in/reducers/index.js
index 151be6d6f809..5db5075a6541 100644
--- a/src/applications/check-in/reducers/index.js
+++ b/src/applications/check-in/reducers/index.js
@@ -2,6 +2,7 @@ const initialState = {
appointments: [],
veteranData: {
demographics: {},
+ address: '',
},
context: {},
form: {
@@ -36,6 +37,10 @@ import {
additionalContextHandler,
} from './day-of';
+import { RECEIVED_TRAVEL_DATA } from '../actions/travel-claim';
+
+import { receivedTravelDataHandler } from './travel-claim';
+
import { setAppHandler, setErrorHandler, setFormHandler } from './universal';
import { INIT_FORM } from '../actions/navigation';
@@ -68,6 +73,7 @@ const handler = Object.freeze({
[SET_ERROR]: setErrorHandler,
[SET_FORM]: setFormHandler,
[ADDITIONAL_CONTEXT]: additionalContextHandler,
+ [RECEIVED_TRAVEL_DATA]: receivedTravelDataHandler,
default: state => {
return { ...state };
diff --git a/src/applications/check-in/reducers/reducer.unit.spec.js b/src/applications/check-in/reducers/reducer.unit.spec.js
index 508ebe5175dc..c406e8c295f0 100644
--- a/src/applications/check-in/reducers/reducer.unit.spec.js
+++ b/src/applications/check-in/reducers/reducer.unit.spec.js
@@ -12,6 +12,7 @@ describe('check in', () => {
appointments: [],
veteranData: {
demographics: {},
+ address: '',
},
context: {},
form: {
diff --git a/src/applications/check-in/reducers/travel-claim/index.js b/src/applications/check-in/reducers/travel-claim/index.js
new file mode 100644
index 000000000000..fb8c7dcef0cf
--- /dev/null
+++ b/src/applications/check-in/reducers/travel-claim/index.js
@@ -0,0 +1,10 @@
+const receivedTravelDataHandler = (state, action) => {
+ const { appointments, address } = JSON.parse(JSON.stringify(action.payload));
+ return {
+ ...state,
+ appointments,
+ veteranData: { ...state.veteranData, address },
+ };
+};
+
+export { receivedTravelDataHandler };
diff --git a/src/applications/check-in/reducers/travel-claim/travel-claim.reducers.unit.spec.js b/src/applications/check-in/reducers/travel-claim/travel-claim.reducers.unit.spec.js
new file mode 100644
index 000000000000..c5ca681f5e10
--- /dev/null
+++ b/src/applications/check-in/reducers/travel-claim/travel-claim.reducers.unit.spec.js
@@ -0,0 +1,55 @@
+import { expect } from 'chai';
+
+import { receivedTravelDataHandler } from './index';
+import { receivedTravelData } from '../../actions/travel-claim';
+
+import appReducer from '../index';
+
+describe('check in', () => {
+ describe('travel claim reducers', () => {
+ const data = {
+ appointments: [
+ {
+ startTime: '2021-08-19T13:56:31',
+ facility: 'LOMA LINDA VA CLINIC',
+ clinicPhoneNumber: '5551234567',
+ clinicFriendlyName: 'TEST CLINIC',
+ clinicName: 'LOM ACC CLINIC TEST',
+ },
+ ],
+ address: '111 fake st.',
+ };
+ describe('receivedTravelDataHandler', () => {
+ it('should create basic structure', () => {
+ const action = receivedTravelData(data);
+ const state = receivedTravelDataHandler({}, action);
+ expect(state.appointments).to.be.an('array');
+ expect(state.veteranData.address).to.be.a('string');
+ });
+ it('should set the correct values', () => {
+ const action = receivedTravelData(data);
+ const state = receivedTravelDataHandler({}, action);
+ expect(state.appointments[0].startTime).to.equal('2021-08-19T13:56:31');
+ expect(state.appointments[0].facility).to.equal('LOMA LINDA VA CLINIC');
+ expect(state.appointments[0].clinicPhoneNumber).to.equal('5551234567');
+ expect(state.appointments[0].clinicFriendlyName).to.equal(
+ 'TEST CLINIC',
+ );
+ expect(state.veteranData.address).to.equal('111 fake st.');
+ });
+ });
+ describe('reducer is called;', () => {
+ it('finds the correct handler', () => {
+ const action = receivedTravelData(data);
+ const state = appReducer.checkInData(undefined, action);
+ expect(state.appointments[0].startTime).to.equal('2021-08-19T13:56:31');
+ expect(state.appointments[0].facility).to.equal('LOMA LINDA VA CLINIC');
+ expect(state.appointments[0].clinicPhoneNumber).to.equal('5551234567');
+ expect(state.appointments[0].clinicFriendlyName).to.equal(
+ 'TEST CLINIC',
+ );
+ expect(state.veteranData.address).to.equal('111 fake st.');
+ });
+ });
+ });
+});
diff --git a/src/applications/check-in/selectors/index.js b/src/applications/check-in/selectors/index.js
index ee16d218ce67..a2ce82e5d44d 100644
--- a/src/applications/check-in/selectors/index.js
+++ b/src/applications/check-in/selectors/index.js
@@ -57,6 +57,20 @@ const selectError = createSelector(
const makeSelectError = () => selectError;
+const selectTravelClaimData = createSelector(
+ state => state.checkInData,
+ data => data.appointments,
+);
+
+const makeSelectTravelClaimData = () => selectTravelClaimData;
+
+const selectVeteranAddress = createSelector(
+ state => state.checkInData,
+ data => data.veteranData.address,
+);
+
+const makeSelectVeteranAddress = () => selectVeteranAddress;
+
export {
makeSelectCurrentContext,
makeSelectForm,
@@ -64,4 +78,6 @@ export {
makeSelectSeeStaffMessage,
makeSelectApp,
makeSelectError,
+ makeSelectTravelClaimData,
+ makeSelectVeteranAddress,
};
diff --git a/src/applications/check-in/selectors/selector.unit.spec.js b/src/applications/check-in/selectors/selector.unit.spec.js
index 5c7c38495fe9..e8555d52c859 100644
--- a/src/applications/check-in/selectors/selector.unit.spec.js
+++ b/src/applications/check-in/selectors/selector.unit.spec.js
@@ -7,6 +7,8 @@ import {
makeSelectSeeStaffMessage,
makeSelectApp,
makeSelectError,
+ makeSelectTravelClaimData,
+ makeSelectVeteranAddress,
} from './index';
describe('check-in', () => {
@@ -117,5 +119,29 @@ describe('check-in', () => {
});
});
});
+ describe('makeSelectTravelClaimData', () => {
+ const state = {
+ checkInData: {
+ appointments: ['appt 1', 'appt 2'],
+ },
+ };
+ it('returns appointments', () => {
+ const selectTravelClaimData = makeSelectTravelClaimData();
+ expect(selectTravelClaimData(state)).to.eql(['appt 1', 'appt 2']);
+ });
+ });
+ describe('makeSelectVeteranAddress', () => {
+ const state = {
+ checkInData: {
+ veteranData: {
+ address: 'test',
+ },
+ },
+ };
+ it('returns address', () => {
+ const selectVeteranAddress = makeSelectVeteranAddress();
+ expect(selectVeteranAddress(state)).to.eql('test');
+ });
+ });
});
});
diff --git a/src/applications/check-in/travel-claim/pages/LoadingPage/index.jsx b/src/applications/check-in/travel-claim/pages/LoadingPage/index.jsx
new file mode 100644
index 000000000000..415ccd6c3603
--- /dev/null
+++ b/src/applications/check-in/travel-claim/pages/LoadingPage/index.jsx
@@ -0,0 +1,55 @@
+import React, { useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+import PropTypes from 'prop-types';
+import { APP_NAMES } from '../../../utils/appConstants';
+import { useGetCheckInData } from '../../../hooks/useGetCheckInData';
+import { useFormRouting } from '../../../hooks/useFormRouting';
+import { useUpdateError } from '../../../hooks/useUpdateError';
+
+const LoadingPage = props => {
+ const { router } = props;
+ const { t } = useTranslation();
+
+ const { goToNextPage } = useFormRouting(router);
+
+ const { checkInDataError, isComplete } = useGetCheckInData({
+ refreshNeeded: true,
+ app: APP_NAMES.TRAVEL_CLAIM,
+ });
+
+ const { updateError } = useUpdateError();
+
+ useEffect(
+ () => {
+ if (checkInDataError) {
+ updateError('cant-retrieve-travel-claim-data');
+ }
+ },
+ [checkInDataError, updateError],
+ );
+
+ useEffect(
+ () => {
+ if (isComplete) {
+ goToNextPage();
+ }
+ },
+ [isComplete, goToNextPage],
+ );
+ window.scrollTo(0, 0);
+
+ return (
+
+
+
+ );
+};
+
+LoadingPage.propTypes = {
+ isSessionLoading: PropTypes.bool,
+ router: PropTypes.object,
+};
+
+export default LoadingPage;
diff --git a/src/applications/check-in/travel-claim/pages/travel-intro/index.jsx b/src/applications/check-in/travel-claim/pages/travel-intro/index.jsx
index 64a671e2dab9..340c41361be6 100644
--- a/src/applications/check-in/travel-claim/pages/travel-intro/index.jsx
+++ b/src/applications/check-in/travel-claim/pages/travel-intro/index.jsx
@@ -1,4 +1,5 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, useMemo } from 'react';
+import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { recordEvent } from '@department-of-veterans-affairs/platform-monitoring/exports';
@@ -7,15 +8,14 @@ import Wrapper from '../../../components/layout/Wrapper';
import { createAnalyticsSlug } from '../../../utils/analytics';
import { hasMultipleFacilities } from '../../../utils/appointment';
import { useFormRouting } from '../../../hooks/useFormRouting';
+import { makeSelectTravelClaimData } from '../../../selectors';
import TravelEligibilityAddtionalInfo from '../../../components/TravelEligibilityAdditionalInfo';
-// Appointments will come from redux this is temp
-import { singleFacility } from './testAppointments';
-
const TravelIntro = props => {
- const { router, appointments = singleFacility } = props;
+ const { router } = props;
const { t } = useTranslation();
-
+ const selectTravelClaimData = useMemo(makeSelectTravelClaimData, []);
+ const appointments = useSelector(selectTravelClaimData);
const { jumpToPage } = useFormRouting(router);
const nextPage = hasMultipleFacilities(appointments)
@@ -86,7 +86,10 @@ const TravelIntro = props => {
-
+
{t('set-up-direct-deposit')}
{t('set-up-direct-deposit-to-receive-travel-reimbursement')}
diff --git a/src/applications/check-in/travel-claim/pages/travel-intro/travelIntro.unit.spec.js b/src/applications/check-in/travel-claim/pages/travel-intro/travelIntro.unit.spec.js
index 24effa0a5493..3dfc8196a413 100644
--- a/src/applications/check-in/travel-claim/pages/travel-intro/travelIntro.unit.spec.js
+++ b/src/applications/check-in/travel-claim/pages/travel-intro/travelIntro.unit.spec.js
@@ -13,6 +13,7 @@ describe('travel-claim', () => {
describe('Intro page', () => {
it('links to select page if multiple facilites in payload', () => {
const push = sinon.spy();
+ store.appointments = multiFacility;
const component = render(
{
params: {},
}}
>
-
+
,
);
const link = component.getByTestId('file-claim-link');
@@ -31,6 +32,7 @@ describe('travel-claim', () => {
});
it('links to single page if one facility in payload', () => {
const push = sinon.spy();
+ store.appointments = singleFacility;
const component = render(
{
params: {},
}}
>
-
+
,
);
const link = component.getByTestId('file-claim-link');
diff --git a/src/applications/check-in/travel-claim/routes.jsx b/src/applications/check-in/travel-claim/routes.jsx
index 97efc56d25c1..948f8047bb7c 100644
--- a/src/applications/check-in/travel-claim/routes.jsx
+++ b/src/applications/check-in/travel-claim/routes.jsx
@@ -12,6 +12,7 @@ import ErrorBoundary from '../components/errors/ErrorBoundary';
import Validate from './pages/validate';
import Landing from './pages/landing';
+import LoadingPage from './pages/LoadingPage';
import TravelIntro from './pages/travel-intro';
import SelectAppointment from './pages/select-appointment';
import TravelMileage from './pages/travel-mileage';
@@ -29,12 +30,20 @@ const routes = [
path: URLS.VALIDATION_NEEDED,
component: Validate,
},
+ {
+ path: URLS.LOADING,
+ component: LoadingPage,
+ permissions: {
+ requireAuthorization: true,
+ },
+ },
{
path: URLS.TRAVEL_INTRO,
component: TravelIntro,
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
{
path: URLS.TRAVEL_SELECT,
@@ -42,6 +51,7 @@ const routes = [
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
{
path: URLS.TRAVEL_MILEAGE,
@@ -49,6 +59,7 @@ const routes = [
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
{
path: URLS.TRAVEL_VEHICLE,
@@ -56,6 +67,7 @@ const routes = [
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
{
path: URLS.TRAVEL_ADDRESS,
@@ -63,6 +75,7 @@ const routes = [
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
{
path: URLS.TRAVEL_REVIEW,
@@ -70,6 +83,7 @@ const routes = [
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
{
path: URLS.COMPLETE,
@@ -77,6 +91,7 @@ const routes = [
permissions: {
requireAuthorization: true,
},
+ reloadable: true,
},
];
@@ -114,7 +129,7 @@ const createRoutesWithStore = () => {
if (route.reloadable) {
// If the page is able to restore state on reload add the wrapper.
return (
-
+
);
diff --git a/src/applications/check-in/utils/navigation/travel-claim/index.js b/src/applications/check-in/utils/navigation/travel-claim/index.js
index f33de3b6cf96..345b28c95605 100644
--- a/src/applications/check-in/utils/navigation/travel-claim/index.js
+++ b/src/applications/check-in/utils/navigation/travel-claim/index.js
@@ -17,6 +17,10 @@ import { URLS } from '..';
const TRAVEL_PAY_FORM_PAGES = Object.freeze([
{
url: URLS.VERIFY,
+ order: 0,
+ },
+ {
+ url: URLS.LOADING,
order: 1,
},
{
From b2cf351fd338440790cd63de6b2086e8cde31bd7 Mon Sep 17 00:00:00 2001
From: mattwrightva <107576133+mattwrightva@users.noreply.github.com>
Date: Wed, 28 Feb 2024 14:23:44 -0700
Subject: [PATCH 50/51] MHV-52814: Styling of downtime notifications complete
(#28118)
* MHV-52814: Styling of downtime notifications complete
* MHV-52814: Unit test fixed
* MHV-52814: Bug and styling fixes
* MHV-52814: Title fix
* MHV-52814: Added conditional breadcrumbs
* MHV-52814: Tests for conditional breadcrumbs
* MHV-52814: Variable added
* MHV-52814: className fix
---------
Co-authored-by: Matthew Wright
---
.../mhv/medical-records/containers/App.jsx | 90 +++-
.../containers/LandingPage.jsx | 501 +++++++++---------
.../medical-records/sass/landing-page.scss | 12 +-
.../medical-records/sass/medical-records.scss | 4 +
.../tests/containers/App.unit.spec.jsx | 72 ++-
.../containers/LandingPage.unit.spec.jsx | 72 ++-
6 files changed, 460 insertions(+), 291 deletions(-)
diff --git a/src/applications/mhv/medical-records/containers/App.jsx b/src/applications/mhv/medical-records/containers/App.jsx
index d46ab9da15cb..d4c6f7278ca9 100644
--- a/src/applications/mhv/medical-records/containers/App.jsx
+++ b/src/applications/mhv/medical-records/containers/App.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useState, useRef } from 'react';
+import React, { useEffect, useState, useRef, useMemo } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
useLocation,
@@ -7,10 +7,13 @@ import {
import PropTypes from 'prop-types';
import { selectUser } from '@department-of-veterans-affairs/platform-user/selectors';
import { RequiredLoginView } from '@department-of-veterans-affairs/platform-user/RequiredLoginView';
+import { renderMHVDowntime } from '@department-of-veterans-affairs/mhv/exports';
import {
DowntimeNotification,
externalServices,
+ externalServiceStatus,
} from '@department-of-veterans-affairs/platform-monitoring/DowntimeNotification';
+import { getScheduledDowntime } from 'platform/monitoring/DowntimeNotification/actions';
import MrBreadcrumbs from '../components/MrBreadcrumbs';
import ScrollToTop from '../components/shared/ScrollToTop';
import PhrRefresh from '../components/shared/PhrRefresh';
@@ -44,6 +47,36 @@ const App = ({ children }) => {
const [paths, setPaths] = useState([]);
const location = useLocation();
const measuredRef = useRef();
+ const atLandingPage = location.pathname === '/';
+
+ const scheduledDowntimes = useSelector(
+ state => state.scheduledDowntime?.serviceMap || [],
+ );
+ const globalDowntime = useSelector(
+ state => state.scheduledDowntime?.globalDowntime,
+ );
+
+ const mhvMrDown = useMemo(
+ () => {
+ if (scheduledDowntimes.size > 0) {
+ return (
+ scheduledDowntimes?.get(externalServices.mhvMr)?.status ||
+ scheduledDowntimes?.get(externalServices.mhvPlatform)?.status ||
+ scheduledDowntimes?.get(externalServices.global)?.status ||
+ globalDowntime
+ );
+ }
+ return 'downtime status: ok';
+ },
+ [scheduledDowntimes, globalDowntime],
+ );
+
+ useEffect(
+ () => {
+ dispatch(getScheduledDowntime());
+ },
+ [dispatch],
+ );
const datadogRumConfig = {
applicationId: '04496177-4c70-4caf-9d1e-de7087d1d296',
@@ -182,28 +215,43 @@ const App = ({ children }) => {
ref={measuredRef}
className="vads-l-grid-container vads-u-padding-left--2"
>
-
-
-
- {showSideNav && (
- <>
-
-
- >
- )}
-
-
-
{children}
- {!showSideNav && (
-
- )}
+ {mhvMrDown === externalServiceStatus.down ? (
+ <>
+ {atLandingPage &&
}
+
+ Medical records
+
+
+ >
+ ) : (
+ <>
+
+
+ {showSideNav && (
+ <>
+
+
+ >
+ )}
+
+
+
{children}
+ {!showSideNav && (
+
+ )}
+
-
-
+ >
+ )}
diff --git a/src/applications/mhv/medical-records/containers/LandingPage.jsx b/src/applications/mhv/medical-records/containers/LandingPage.jsx
index d34ad57c42a5..95d7c4924a39 100644
--- a/src/applications/mhv/medical-records/containers/LandingPage.jsx
+++ b/src/applications/mhv/medical-records/containers/LandingPage.jsx
@@ -2,6 +2,11 @@ import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { focusElement } from '@department-of-veterans-affairs/platform-utilities/ui';
+import { renderMHVDowntime } from '@department-of-veterans-affairs/mhv/exports';
+import {
+ DowntimeNotification,
+ externalServices,
+} from '@department-of-veterans-affairs/platform-monitoring/DowntimeNotification';
import { setBreadcrumbs } from '../actions/breadcrumbs';
import FeedbackEmail from '../components/shared/FeedbackEmail';
import { mhvUrl } from '~/platform/site-wide/mhv/utilities';
@@ -34,271 +39,273 @@ const LandingPage = () => {
);
return (
- <>
-
-
-
- Medical records
-
-
- Review, print, and download your VA medical records.
-
-
- {displayNotes && (
-
-
- Care summaries and notes
-
-
- Get notes from your VA providers about your health and health
- care. This includes summaries of your stays in health facilities
- (called admission and discharge summaries).
-
-
- Go to your care summaries and notes
-
-
- )}
- {displayVaccines && (
-
-
- Vaccines
-
-
- Get a list of all vaccines (immunizations) in your VA medical
- records.
-
-
- Go to your vaccines
-
-
- )}
+
+
+
+ Medical records
+
+
+
+
+ Review, print, and download your VA medical records.
+
+
+ {displayNotes && (
- Allergies and reactions
+ Care summaries and notes
- Get a list of all allergies, reactions, and side effects in your VA
- medical records. This includes medication side effects (also called
- adverse drug reactions).
+ Get notes from your VA providers about your health and health care.
+ This includes summaries of your stays in health facilities (called
+ admission and discharge summaries).
-
- Go to your allergies and reactions
+
+ Go to your care summaries and notes
+ )}
+ {displayVaccines && (
- How to find your other medical records
-
-
- Right now, only some of your medical records are available here on
- VA.gov. Soon, you’ll be able to find these types of medical records
- on this page:
-
-
- - Lab and test results
- {!displayNotes && - Care summaries and notes
}
- {!displayVaccines && - Vaccines
}
- - Health conditions
- - Vitals
-
-
- To find your other medical records now, you’ll need to go back to
- the My HealtheVet website.
-
-
-
- Go to medical records on the My HealtheVet website
-
-
-
-
-
- What to know as you try out this tool
+ Vaccines
- We’re giving the trusted My HealtheVet medical records tool a new
- home here on VA.gov. And we need your feedback to help us keep
- making this tool better for you and all Veterans.
-
-
- Email your feedback and questions to us at .
-
-
- Note: You still
- have access to your medical records on the My HealtheVet website.
- You can go back to that site at any time.{' '}
-
- Go back to medical records on the My HealtheVet website
-
+ Get a list of all vaccines (immunizations) in your VA medical
+ records.
+
+ Go to your vaccines
+
+ )}
+
+
+ Allergies and reactions
+
+
+ Get a list of all allergies, reactions, and side effects in your VA
+ medical records. This includes medication side effects (also called
+ adverse drug reactions).
+
+
+ Go to your allergies and reactions
+
+
+
+
+ How to find your other medical records
+
+
+ Right now, only some of your medical records are available here on
+ VA.gov. Soon, you’ll be able to find these types of medical records on
+ this page:
+
+
+ - Lab and test results
+ {!displayNotes && - Care summaries and notes
}
+ {!displayVaccines && - Vaccines
}
+ - Health conditions
+ - Vitals
+
+
+ To find your other medical records now, you’ll need to go back to the
+ My HealtheVet website.
+
+
+
+ Go to medical records on the My HealtheVet website
+
+
+
+
+
+ What to know as you try out this tool
+
+
+ We’re giving the trusted My HealtheVet medical records tool a new home
+ here on VA.gov. And we need your feedback to help us keep making this
+ tool better for you and all Veterans.
+
+
+ Email your feedback and questions to us at .
+
+
+ Note: You still have
+ access to your medical records on the My HealtheVet website. You can
+ go back to that site at any time.{' '}
+
+ Go back to medical records on the My HealtheVet website
+
+
+
-
- Questions about this medical records tool
-
-
-
- What if I can’t find all my medical records?
-
-
- Right now, only some types of medical records are available here
- on VA.gov. And your records on VA.gov only include health
- information your VA providers have entered.
-
-
- To find other types of medical records
- —
- including health information you entered yourself
- —
- go to your medical records on the My HealtheVet website.
-
-
-
- Go to medical records on the My HealtheVet website
-
-
-
-
-
- How can I tell my care team that my health information has
- changed?
-
+
+ Questions about this medical records tool
+
+
+
+ What if I can’t find all my medical records?
+
+
+ Right now, only some types of medical records are available here
+ on VA.gov. And your records on VA.gov only include health
+ information your VA providers have entered.
+
+
+ To find other types of medical records
+ —
+ including health information you entered yourself
+ —
+ go to your medical records on the My HealtheVet website.
+
+
+
+ Go to medical records on the My HealtheVet website
+
+
+
+
+
+ How can I tell my care team that my health information has
+ changed?
+
-
- If you need to add or change health information in your records,
- you can tell your provider at your next appointment.
-
-
- Or you can send a secure message to your care team and ask them
- to update your records.
-
-
-
- Compose a message on the My HealtheVet website
-
-
-
-
-
- Will VA protect my personal health information?
-
-
- Yes. This is a secure website. We follow strict security
- policies and practices to protect your personal health
- information. Only you and your VA care team will have access to
- your records.
-
-
- If you print or download any records, you’ll need to take
- responsibility for protecting that information. If you’re on a
- public or shared computer, remember that downloading will save a
- copy of your records to the computer you’re using.
-
-
-
-
- What if I have more questions?
-
-
-
- For questions about health information in your records
-
-
-
- Send a secure message to your care team.
-
-
-
- Compose a message on the My HealtheVet website
-
-
-
- Only use messages for non-urgent needs. Your care team may take
- up to{' '}
+
+ If you need to add or change health information in your records,
+ you can tell your provider at your next appointment.
+
+
+ Or you can send a secure message to your care team and ask them to
+ update your records.
+
+
+
+ Compose a message on the My HealtheVet website
+
+
+
+
+
+ Will VA protect my personal health information?
+
+
+ Yes. This is a secure website. We follow strict security policies
+ and practices to protect your personal health information. Only
+ you and your VA care team will have access to your records.
+
+
+ If you print or download any records, you’ll need to take
+ responsibility for protecting that information. If you’re on a
+ public or shared computer, remember that downloading will save a
+ copy of your records to the computer you’re using.
+
+
+
+
+ What if I have more questions?
+
+
+
+ For questions about health information in your records
+
+
+
+ Send a secure message to your care team.
+
+
+
+ Compose a message on the My HealtheVet website
+
+
+
+ Only use messages for non-urgent needs. Your care team may take up
+ to{' '}
+ 3 business days{' '}
+ to reply.
+
+
+ If you need help sooner, use one of these urgent communication
+ options:
+
+
+ -
- 3 business days
+ If you’re in crisis or having thoughts of suicide,
{' '}
- to reply.
-
-
- If you need help sooner, use one of these urgent communication
- options:
-
-
- -
-
- If you’re in crisis or having thoughts of suicide,
- {' '}
- connect with our Veterans Crisis Line. We offer confidential
- support anytime, day or night.
-
-
-
-
- -
-
- If you think your life or health is in danger,
- {' '}
- call 911 or go to the nearest emergency room.
-
-
-
+ connect with our Veterans Crisis Line. We offer confidential
+ support anytime, day or night.
+
+
+
+
+ -
- For questions about how to use this tool
-
-
-
- Email us at .
-
-
-
-
-
- >
+ If you think your life or health is in danger,
+ {' '}
+ call 911 or go to the nearest emergency room.
+
+
+
+
+ For questions about how to use this tool
+
+
+
+ Email us at .
+
+
+
+
+
);
};
diff --git a/src/applications/mhv/medical-records/sass/landing-page.scss b/src/applications/mhv/medical-records/sass/landing-page.scss
index 2d6cddab0f03..7624f9b60cba 100644
--- a/src/applications/mhv/medical-records/sass/landing-page.scss
+++ b/src/applications/mhv/medical-records/sass/landing-page.scss
@@ -1,10 +1,8 @@
.landing-page {
- .section-link {
- a {
- color: $color-link-default;
- }
- a:visited {
- color: $color-link-default;
- }
+ a {
+ color: $color-link-default;
+ }
+ a:visited {
+ color: $color-link-default;
}
}
diff --git a/src/applications/mhv/medical-records/sass/medical-records.scss b/src/applications/mhv/medical-records/sass/medical-records.scss
index 48063941716a..67f67f80f437 100644
--- a/src/applications/mhv/medical-records/sass/medical-records.scss
+++ b/src/applications/mhv/medical-records/sass/medical-records.scss
@@ -127,3 +127,7 @@
font-family: Roboto Mono;
// font-family: monospace;
}
+
+va-loading-indicator {
+ margin: 200px auto;
+}
diff --git a/src/applications/mhv/medical-records/tests/containers/App.unit.spec.jsx b/src/applications/mhv/medical-records/tests/containers/App.unit.spec.jsx
index 689aed61feaf..e97e36eb1d8b 100644
--- a/src/applications/mhv/medical-records/tests/containers/App.unit.spec.jsx
+++ b/src/applications/mhv/medical-records/tests/containers/App.unit.spec.jsx
@@ -52,7 +52,7 @@ describe('App', () => {
// services: [backendServices.HEALTH_RECORDS],
},
},
- sm: {
+ mr: {
breadcrumbs: {
list: [],
},
@@ -173,7 +173,7 @@ describe('App', () => {
globalDowntime: true,
isReady: true,
isPending: false,
- serviceMap: downtime([]),
+ serviceMap: downtime(['global']),
dismissedDowntimeWarnings: [],
},
...initialState,
@@ -214,15 +214,18 @@ describe('App', () => {
path: `/`,
});
expect(
- screen.getByText('This tool is down for maintenance', {
+ screen.getByText('Maintenance on My HealtheVet', {
selector: 'h3',
exact: true,
}),
);
expect(
- screen.getByText('We’re making some updates to this tool', {
- exact: false,
- }),
+ screen.getByText(
+ 'We’re working on My HealtheVet. The maintenance will last 48 hours.',
+ {
+ exact: false,
+ },
+ ),
);
});
@@ -246,15 +249,18 @@ describe('App', () => {
path: `/`,
});
expect(
- screen.getByText('This tool is down for maintenance', {
+ screen.getByText('Maintenance on My HealtheVet', {
selector: 'h3',
exact: true,
}),
);
expect(
- screen.getByText('We’re making some updates to this tool', {
- exact: false,
- }),
+ screen.getByText(
+ 'We’re working on My HealtheVet. The maintenance will last 48 hours',
+ {
+ exact: false,
+ },
+ ),
);
});
@@ -278,7 +284,7 @@ describe('App', () => {
path: `/`,
});
const downtimeComponent = screen.queryByText(
- 'This tool is down for maintenance',
+ 'Maintenance on My HealtheVet',
{
selector: 'h3',
exact: true,
@@ -288,6 +294,50 @@ describe('App', () => {
});
});
+ it('renders breadcrumbs when downtime and at the landing page', () => {
+ const screen = renderWithStoreAndRouter(
, {
+ initialState: {
+ featureToggles: {
+ // eslint-disable-next-line camelcase
+ mhv_medical_records_to_va_gov_release: true,
+ },
+ scheduledDowntime: {
+ globalDowntime: null,
+ isReady: true,
+ isPending: false,
+ serviceMap: downtime(['mhv_mr']),
+ dismissedDowntimeWarnings: [],
+ },
+ ...initialState,
+ },
+ reducers: reducer,
+ path: `/`,
+ });
+ expect(screen.getByTestId('no-breadcrumbs')).to.exist;
+ });
+
+ it('does not render breadcrumbs when downtime and not at the landing page', () => {
+ const screen = renderWithStoreAndRouter(
, {
+ initialState: {
+ featureToggles: {
+ // eslint-disable-next-line camelcase
+ mhv_medical_records_to_va_gov_release: true,
+ },
+ scheduledDowntime: {
+ globalDowntime: null,
+ isReady: true,
+ isPending: false,
+ serviceMap: downtime(['mhv_mr']),
+ dismissedDowntimeWarnings: [],
+ },
+ ...initialState,
+ },
+ reducers: reducer,
+ path: `/vaccines`,
+ });
+ expect(screen.queryByTestId('no-breadcrumbs')).to.not.exist;
+ });
+
describe('Side Nav feature flag functionality', () => {
it('feature flag set to false', () => {
const screen = renderWithStoreAndRouter(
diff --git a/src/applications/mhv/medical-records/tests/containers/LandingPage.unit.spec.jsx b/src/applications/mhv/medical-records/tests/containers/LandingPage.unit.spec.jsx
index e279d7d55040..883b6357a1a5 100644
--- a/src/applications/mhv/medical-records/tests/containers/LandingPage.unit.spec.jsx
+++ b/src/applications/mhv/medical-records/tests/containers/LandingPage.unit.spec.jsx
@@ -1,17 +1,79 @@
import { expect } from 'chai';
import React from 'react';
import { renderWithStoreAndRouter } from '@department-of-veterans-affairs/platform-testing/react-testing-library-helpers';
-import { beforeEach } from 'mocha';
+import { createServiceMap } from '@department-of-veterans-affairs/platform-monitoring';
+import { addHours, format } from 'date-fns';
import LandingPage from '../../containers/LandingPage';
+import reducer from '../../reducers';
describe('Landing Page', () => {
- let screen;
+ const initialState = {
+ user: {
+ login: {
+ currentlyLoggedIn: true,
+ },
+ profile: {
+ // services: [backendServices.HEALTH_RECORDS],
+ },
+ },
+ mr: {
+ breadcrumbs: {
+ list: [],
+ },
+ },
+ };
- beforeEach(() => {
- screen = renderWithStoreAndRouter(
, {});
- });
+ const downtimeApproaching = maintenanceWindows => {
+ return createServiceMap(
+ maintenanceWindows.map(maintenanceWindow => {
+ return {
+ attributes: {
+ externalService: maintenanceWindow,
+ status: 'downtimeApproaching',
+ startTime: format(addHours(new Date(), 1), "yyyy-LL-dd'T'HH:mm:ss"),
+ endTime: format(addHours(new Date(), 3), "yyyy-LL-dd'T'HH:mm:ss"),
+ },
+ };
+ }),
+ );
+ };
it('renders without errors', () => {
+ const screen = renderWithStoreAndRouter(
, {});
expect(screen).to.exist;
});
+
+ it('displays downtimeNotification when downtimeApproaching is true', () => {
+ const customState = {
+ featureToggles: {},
+ scheduledDowntime: {
+ globalDowntime: null,
+ isReady: true,
+ isPending: false,
+ serviceMap: downtimeApproaching(['mhv_mr']),
+ dismissedDowntimeWarnings: [],
+ },
+ ...initialState,
+ };
+
+ const screen = renderWithStoreAndRouter(
, {
+ initialState: customState,
+ reducers: reducer,
+ });
+
+ expect(
+ screen.getByText('Upcoming maintenance on My HealtheVet', {
+ selector: 'h3',
+ exact: true,
+ }),
+ );
+ expect(
+ screen.getByText(
+ 'We’ll be working on My HealtheVet soon. The maintenance will last 2 hours',
+ {
+ exact: false,
+ },
+ ),
+ );
+ });
});
From ff199a70061961103b807ec94bb74b9efafdcd8f Mon Sep 17 00:00:00 2001
From: Aaron Ponce
Date: Wed, 28 Feb 2024 13:27:45 -0800
Subject: [PATCH 51/51] Update buttons to use VA web components and uswds
(#28215)
* Button Group Updates for FSR
* Fixed back/cancel and add/continue text and also fixed mobile stacking styles
* Button group cypress updates
---------
Co-authored-by: Joseph Lee
---
.../bankruptcy/BankruptcyDetails.jsx | 2 -
.../employment/EmploymentHistoryWidget.jsx | 4 +-
.../employment/EnhancedEmploymentRecord.jsx | 51 +++++---------
.../EnhancedSpouseEmploymentRecord.jsx | 19 +-----
.../SpouseEmploymentHistoryWidget.jsx | 5 +-
.../householdExpenses/CreditCardBill.jsx | 68 +++++++++----------
.../householdExpenses/InstallmentContract.jsx | 66 +++++++++---------
.../components/householdIncome/AddIncome.jsx | 38 +++++------
.../GrossMonthlyIncomeInput.jsx | 5 +-
.../PayrollDeductionChecklist.jsx | 5 +-
.../PayrollDeductionInputList.jsx | 38 +++++------
.../householdIncome/SpouseAddIncome.jsx | 39 ++++++-----
.../SpouseGrossMonthlyIncomeInput.jsx | 5 +-
.../SpousePayrollDeductionChecklist.jsx | 6 +-
.../SpousePayrollDeductionInputList.jsx | 39 +++++------
.../components/otherAssets/AddAsset.jsx | 38 +++++------
.../otherAssets/EnhancedVehicleRecord.jsx | 63 +++++++++--------
.../otherExpenses/AddOtherExpense.jsx | 34 +++++-----
.../utilityBills/AddUtilityBill.jsx | 39 ++++++-----
.../sass/financial-status-report.scss | 3 +
.../tests/e2e/efsr-5655.cypress.spec.js | 17 ++---
21 files changed, 268 insertions(+), 316 deletions(-)
diff --git a/src/applications/financial-status-report/components/bankruptcy/BankruptcyDetails.jsx b/src/applications/financial-status-report/components/bankruptcy/BankruptcyDetails.jsx
index 4c4fb6fcef38..d8fd58816cb0 100644
--- a/src/applications/financial-status-report/components/bankruptcy/BankruptcyDetails.jsx
+++ b/src/applications/financial-status-report/components/bankruptcy/BankruptcyDetails.jsx
@@ -181,7 +181,6 @@ const BankruptcyDetails = ({
/>
{contentBeforeButtons}
-
-
{contentAfterButtons}
);
diff --git a/src/applications/financial-status-report/components/employment/EmploymentHistoryWidget.jsx b/src/applications/financial-status-report/components/employment/EmploymentHistoryWidget.jsx
index abd0b7c4b651..968c5b21105d 100644
--- a/src/applications/financial-status-report/components/employment/EmploymentHistoryWidget.jsx
+++ b/src/applications/financial-status-report/components/employment/EmploymentHistoryWidget.jsx
@@ -16,7 +16,6 @@ const EmploymentHistoryWidget = props => {
const {
goToPath,
goForward,
- onReviewPage,
contentBeforeButtons,
contentAfterButtons,
} = props;
@@ -40,7 +39,6 @@ const EmploymentHistoryWidget = props => {
const navButtons = (
);
- const updateButton = ;
return (
);
diff --git a/src/applications/financial-status-report/components/employment/EnhancedEmploymentRecord.jsx b/src/applications/financial-status-report/components/employment/EnhancedEmploymentRecord.jsx
index 3450f574804f..78b1940637fe 100644
--- a/src/applications/financial-status-report/components/employment/EnhancedEmploymentRecord.jsx
+++ b/src/applications/financial-status-report/components/employment/EnhancedEmploymentRecord.jsx
@@ -13,6 +13,7 @@ import {
jobButtonConstants,
} from '../../utils/session';
import { BASE_EMPLOYMENT_RECORD } from '../../constants/index';
+import ButtonGroup from '../shared/ButtonGroup';
const RETURN_PATH = '/employment-history';
@@ -142,28 +143,15 @@ const EmploymentRecord = props => {
handleChange('isCurrent', value === 'true');
setCurrentlyWorksHere(value === 'true');
},
- getContinueButtonText: () => {
- if (
- employmentRecord.isCurrent ||
- getJobButton() === jobButtonConstants.FIRST_JOB
- ) {
- return 'Continue';
- }
-
- if (getJobButton() === jobButtonConstants.EDIT_JOB) {
- return 'Update employment record';
- }
- return 'Add employment record';
- },
getCancelButtonText: () => {
if (getJobButton() === jobButtonConstants.FIRST_JOB) {
return 'Back';
}
if (getJobButton() === jobButtonConstants.EDIT_JOB) {
- return 'Cancel Edit Entry';
+ return 'Cancel edit entry';
}
- return 'Cancel Add Entry';
+ return 'Cancel add entry';
},
};
@@ -233,24 +221,21 @@ const EmploymentRecord = props => {
uswds
/>
-
-
-
-
+
+
);
diff --git a/src/applications/financial-status-report/components/employment/EnhancedSpouseEmploymentRecord.jsx b/src/applications/financial-status-report/components/employment/EnhancedSpouseEmploymentRecord.jsx
index 91799f6fa1ad..b1e71f3265cb 100644
--- a/src/applications/financial-status-report/components/employment/EnhancedSpouseEmploymentRecord.jsx
+++ b/src/applications/financial-status-report/components/employment/EnhancedSpouseEmploymentRecord.jsx
@@ -143,28 +143,15 @@ const EmploymentRecord = props => {
handleChange('isCurrent', value === 'true');
setCurrentlyWorksHere(value === 'true');
},
- getContinueButtonText: () => {
- if (
- employmentRecord.isCurrent ||
- getJobButton() === jobButtonConstants.FIRST_JOB
- ) {
- return 'Continue';
- }
-
- if (getJobButton() === jobButtonConstants.EDIT_JOB) {
- return 'Update employment record';
- }
- return 'Add employment record';
- },
getCancelButtonText: () => {
if (getJobButton() === jobButtonConstants.FIRST_JOB) {
return 'Back';
}
if (getJobButton() === jobButtonConstants.EDIT_JOB) {
- return 'Cancel Edit Entry';
+ return 'Cancel edit entry';
}
- return 'Cancel Add Entry';
+ return 'Cancel add entry';
},
};
@@ -244,7 +231,7 @@ const EmploymentRecord = props => {
isSecondary: true,
},
{
- label: handlers.getContinueButtonText(),
+ label: 'Continue',
onClick: updateFormData,
isSubmitting: true,
},
diff --git a/src/applications/financial-status-report/components/employment/SpouseEmploymentHistoryWidget.jsx b/src/applications/financial-status-report/components/employment/SpouseEmploymentHistoryWidget.jsx
index 17deb617bf11..bb2878e8053b 100644
--- a/src/applications/financial-status-report/components/employment/SpouseEmploymentHistoryWidget.jsx
+++ b/src/applications/financial-status-report/components/employment/SpouseEmploymentHistoryWidget.jsx
@@ -15,7 +15,6 @@ const SpouseEmploymentHistoryWidget = props => {
const {
goToPath,
goForward,
- onReviewPage,
contentBeforeButtons,
contentAfterButtons,
} = props;
@@ -38,7 +37,7 @@ const SpouseEmploymentHistoryWidget = props => {
const navButtons = (
);
- const updateButton = ;
+
const emptyPrompt = `Select the ‘add additional job link to add another job. Select the continue button to move on to the next question.`;
return (
@@ -76,7 +75,7 @@ const SpouseEmploymentHistoryWidget = props => {
{contentBeforeButtons}
- {onReviewPage ? updateButton : navButtons}
+ {navButtons}
{contentAfterButtons}
);
diff --git a/src/applications/financial-status-report/components/householdExpenses/CreditCardBill.jsx b/src/applications/financial-status-report/components/householdExpenses/CreditCardBill.jsx
index 19a99572cbed..17d07e375715 100644
--- a/src/applications/financial-status-report/components/householdExpenses/CreditCardBill.jsx
+++ b/src/applications/financial-status-report/components/householdExpenses/CreditCardBill.jsx
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { setData } from 'platform/forms-system/src/js/actions';
import { isValidCurrency } from '../../utils/validations';
+import ButtonGroup from '../shared/ButtonGroup';
const defaultRecord = [
{
@@ -151,27 +152,26 @@ const CreditCardBill = props => {
},
};
+ const addCancelButtonsText =
+ creditCardBills.length === index ? 'Add' : 'Update';
+
const renderAddCancelButtons = () => {
return (
<>
-
-
+
>
);
};
@@ -179,22 +179,20 @@ const CreditCardBill = props => {
const renderContinueBackButtons = () => {
return (
<>
-
-
+
>
);
};
@@ -206,7 +204,7 @@ const CreditCardBill = props => {
{`${
creditCardBills.length === index ? 'Add' : 'Update'
- } a credit card bill`}
+ } credit card bill`}
Enter your credit card bill’s information.
diff --git a/src/applications/financial-status-report/components/householdExpenses/InstallmentContract.jsx b/src/applications/financial-status-report/components/householdExpenses/InstallmentContract.jsx
index 4b2679a8c82d..c5fc4056fce2 100644
--- a/src/applications/financial-status-report/components/householdExpenses/InstallmentContract.jsx
+++ b/src/applications/financial-status-report/components/householdExpenses/InstallmentContract.jsx
@@ -9,6 +9,7 @@ import {
import { parseISODate } from 'platform/forms-system/src/js/helpers';
import { isValidCurrency } from '../../utils/validations';
import ContractsExplainer from './ContractsExplainer';
+import ButtonGroup from '../shared/ButtonGroup';
const defaultRecord = [
{
@@ -187,27 +188,26 @@ const InstallmentContract = props => {
},
};
+ const addUpdateButtonsText =
+ installmentContracts.length === index ? 'Add' : 'Update';
+
const renderAddCancelButtons = () => {
return (
<>
-
-
+
>
);
};
@@ -215,22 +215,20 @@ const InstallmentContract = props => {
const renderContinueBackButtons = () => {
return (
<>
-
-
+
>
);
};
diff --git a/src/applications/financial-status-report/components/householdIncome/AddIncome.jsx b/src/applications/financial-status-report/components/householdIncome/AddIncome.jsx
index 4b16854be61d..4b7c6ef0b213 100644
--- a/src/applications/financial-status-report/components/householdIncome/AddIncome.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/AddIncome.jsx
@@ -6,6 +6,7 @@ import {
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
import { MAX_ASSET_NAME_LENGTH } from '../../constants/checkboxSelections';
+import ButtonGroup from '../shared/ButtonGroup';
const SUMMARY_PATH = '/other-income-summary';
const CHECKLIST_PATH = '/additional-income-checklist';
@@ -91,9 +92,12 @@ const AddIncome = ({ data, goToPath, setFormData }) => {
},
});
}
+ handlers.onSubmit(event);
},
};
+ const labelText = addlIncRecords.length === index ? 'Add' : 'Update';
+
return (
<>
>
diff --git a/src/applications/financial-status-report/components/householdIncome/GrossMonthlyIncomeInput.jsx b/src/applications/financial-status-report/components/householdIncome/GrossMonthlyIncomeInput.jsx
index 1a615d6acefb..63de0bb1c07f 100644
--- a/src/applications/financial-status-report/components/householdIncome/GrossMonthlyIncomeInput.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/GrossMonthlyIncomeInput.jsx
@@ -7,7 +7,7 @@ import { getJobIndex } from '../../utils/session';
import { isValidCurrency } from '../../utils/validations';
const GrossMonthlyIncomeInput = props => {
- const { goToPath, goBack, onReviewPage = false, setFormData } = props;
+ const { goToPath, goBack, setFormData } = props;
const editIndex = getJobIndex();
@@ -131,7 +131,6 @@ const GrossMonthlyIncomeInput = props => {
};
const navButtons = ;
- const updateButton = ;
return (
);
};
diff --git a/src/applications/financial-status-report/components/householdIncome/PayrollDeductionChecklist.jsx b/src/applications/financial-status-report/components/householdIncome/PayrollDeductionChecklist.jsx
index 219e84bb6d8c..c05aa74ced7f 100644
--- a/src/applications/financial-status-report/components/householdIncome/PayrollDeductionChecklist.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/PayrollDeductionChecklist.jsx
@@ -8,7 +8,7 @@ import Checklist from '../shared/CheckList';
import { BASE_EMPLOYMENT_RECORD } from '../../constants/index';
const PayrollDeductionChecklist = props => {
- const { goToPath, goBack, onReviewPage, setFormData } = props;
+ const { goToPath, goBack, setFormData } = props;
const editIndex = getJobIndex();
@@ -122,7 +122,6 @@ const PayrollDeductionChecklist = props => {
};
const navButtons = ;
- const updateButton = ;
const title = `Your job at ${employerName}`;
const prompt = 'Which of these payroll deductions do you pay for?';
@@ -142,7 +141,7 @@ const PayrollDeductionChecklist = props => {
the deductions that apply to you.
- {onReviewPage ? updateButton : navButtons}
+ {navButtons}
);
};
diff --git a/src/applications/financial-status-report/components/householdIncome/PayrollDeductionInputList.jsx b/src/applications/financial-status-report/components/householdIncome/PayrollDeductionInputList.jsx
index 970942f09ec3..3dcd5ca10099 100644
--- a/src/applications/financial-status-report/components/householdIncome/PayrollDeductionInputList.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/PayrollDeductionInputList.jsx
@@ -9,9 +9,10 @@ import {
} from '../../utils/session';
import { BASE_EMPLOYMENT_RECORD } from '../../constants/index';
import { isValidCurrency } from '../../utils/validations';
+import ButtonGroup from '../shared/ButtonGroup';
const PayrollDeductionInputList = props => {
- const { goToPath, goBack, onReviewPage = false, setFormData } = props;
+ const { goToPath, goBack, setFormData } = props;
const editIndex = getJobIndex();
@@ -143,26 +144,21 @@ const PayrollDeductionInputList = props => {
};
const navButtons = (
-
-
-
-
+
);
- const updateButton = ;
return (
);
};
diff --git a/src/applications/financial-status-report/components/householdIncome/SpouseAddIncome.jsx b/src/applications/financial-status-report/components/householdIncome/SpouseAddIncome.jsx
index a06edc636f61..31da11536fbb 100644
--- a/src/applications/financial-status-report/components/householdIncome/SpouseAddIncome.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/SpouseAddIncome.jsx
@@ -6,6 +6,7 @@ import {
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
import { MAX_ASSET_NAME_LENGTH } from '../../constants/checkboxSelections';
+import ButtonGroup from '../shared/ButtonGroup';
const SUMMARY_PATH = '/spouse-other-income-summary';
const CHECKLIST_PATH = '/spouse-additional-income-checklist';
@@ -94,9 +95,12 @@ const SpouseAddIncome = ({ data, goToPath, setFormData }) => {
},
});
}
+ handlers.onSubmit(event);
},
};
+ const labelText = spAddlIncome.length === index ? 'Add' : 'Update';
+
return (
<>
>
diff --git a/src/applications/financial-status-report/components/householdIncome/SpouseGrossMonthlyIncomeInput.jsx b/src/applications/financial-status-report/components/householdIncome/SpouseGrossMonthlyIncomeInput.jsx
index 0d6f8aac9e6d..51d2075a502a 100644
--- a/src/applications/financial-status-report/components/householdIncome/SpouseGrossMonthlyIncomeInput.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/SpouseGrossMonthlyIncomeInput.jsx
@@ -7,7 +7,7 @@ import { getJobIndex } from '../../utils/session';
import { isValidCurrency } from '../../utils/validations';
const SpouseGrossMonthlyIncomeInput = props => {
- const { goToPath, goBack, onReviewPage = false, setFormData } = props;
+ const { goToPath, goBack, setFormData } = props;
const editIndex = getJobIndex();
@@ -131,7 +131,6 @@ const SpouseGrossMonthlyIncomeInput = props => {
};
const navButtons = ;
- const updateButton = ;
return (
);
};
diff --git a/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionChecklist.jsx b/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionChecklist.jsx
index d749b65b53df..59e422c0aa3e 100644
--- a/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionChecklist.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionChecklist.jsx
@@ -8,7 +8,7 @@ import Checklist from '../shared/CheckList';
import { BASE_EMPLOYMENT_RECORD } from '../../constants/index';
const SpousePayrollDeductionChecklist = props => {
- const { goToPath, goBack, onReviewPage, setFormData } = props;
+ const { goToPath, goBack, setFormData } = props;
const editIndex = getJobIndex();
@@ -121,7 +121,7 @@ const SpousePayrollDeductionChecklist = props => {
};
const navButtons = ;
- const updateButton = ;
+
const title = `Your spouse’s job at ${employerName}`;
const prompt = 'Which of these payroll deductions does your spouse pay for?';
@@ -144,7 +144,7 @@ const SpousePayrollDeductionChecklist = props => {
spouse.
- {onReviewPage ? updateButton : navButtons}
+ {navButtons}
);
};
diff --git a/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionInputList.jsx b/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionInputList.jsx
index db9f04c94241..c6c1bff86fcb 100644
--- a/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionInputList.jsx
+++ b/src/applications/financial-status-report/components/householdIncome/SpousePayrollDeductionInputList.jsx
@@ -10,9 +10,10 @@ import {
} from '../../utils/session';
import { BASE_EMPLOYMENT_RECORD } from '../../constants/index';
import { isValidCurrency } from '../../utils/validations';
+import ButtonGroup from '../shared/ButtonGroup';
const SpousePayrollDeductionInputList = props => {
- const { goToPath, goBack, onReviewPage = false, setFormData } = props;
+ const { goToPath, goBack, setFormData } = props;
const editIndex = getJobIndex();
@@ -144,26 +145,21 @@ const SpousePayrollDeductionInputList = props => {
};
const navButtons = (
-
-
-
-
+
);
- const updateButton = ;
return (
);
};
@@ -256,5 +252,4 @@ SpousePayrollDeductionInputList.propTypes = {
goBack: PropTypes.func.isRequired,
goToPath: PropTypes.func.isRequired,
setFormData: PropTypes.func.isRequired,
- onReviewPage: PropTypes.bool,
};
diff --git a/src/applications/financial-status-report/components/otherAssets/AddAsset.jsx b/src/applications/financial-status-report/components/otherAssets/AddAsset.jsx
index a3b543a80877..c1c197236e21 100644
--- a/src/applications/financial-status-report/components/otherAssets/AddAsset.jsx
+++ b/src/applications/financial-status-report/components/otherAssets/AddAsset.jsx
@@ -6,6 +6,7 @@ import {
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
import { MAX_ASSET_NAME_LENGTH } from '../../constants/checkboxSelections';
+import ButtonGroup from '../shared/ButtonGroup';
const SUMMARY_PATH = '/other-assets-summary';
const CHECKLIST_PATH = '/other-assets-checklist';
@@ -84,12 +85,15 @@ const AddAsset = ({ data, goToPath, setFormData }) => {
},
});
}
+ handlers.onSubmit(event);
},
};
+ const labelText = otherAssets.length === index ? 'Add' : 'Update';
+
return (
<>
-
>
diff --git a/src/applications/financial-status-report/components/otherAssets/EnhancedVehicleRecord.jsx b/src/applications/financial-status-report/components/otherAssets/EnhancedVehicleRecord.jsx
index 8c0a84ab1ae4..459b0801c3c3 100644
--- a/src/applications/financial-status-report/components/otherAssets/EnhancedVehicleRecord.jsx
+++ b/src/applications/financial-status-report/components/otherAssets/EnhancedVehicleRecord.jsx
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { VaTextInput } from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
+import ButtonGroup from '../shared/ButtonGroup';
const defaultRecord = {
make: '',
@@ -118,25 +119,25 @@ const EnhancedVehicleRecord = ({ data, goToPath, setFormData }) => {
}
};
+ const labelText = automobiles.length === editIndex ? 'Add' : 'Update';
+
const renderAddCancelButtons = () => {
return (
<>
-
-
+
>
);
};
@@ -144,22 +145,20 @@ const EnhancedVehicleRecord = ({ data, goToPath, setFormData }) => {
const renderContinueBackButtons = () => {
return (
<>
-
-
+
>
);
};
diff --git a/src/applications/financial-status-report/components/otherExpenses/AddOtherExpense.jsx b/src/applications/financial-status-report/components/otherExpenses/AddOtherExpense.jsx
index c8daa6636f29..5ce250bd31ea 100644
--- a/src/applications/financial-status-report/components/otherExpenses/AddOtherExpense.jsx
+++ b/src/applications/financial-status-report/components/otherExpenses/AddOtherExpense.jsx
@@ -6,6 +6,7 @@ import {
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
import { MAX_OTHER_LIVING_NAME_LENGTH } from '../../constants/checkboxSelections';
+import ButtonGroup from '../shared/ButtonGroup';
const SUMMARY_PATH = '/other-expenses-summary';
const CHECKLIST_PATH = '/other-expenses-checklist';
@@ -91,6 +92,7 @@ const AddOtherExpense = ({ data, goToPath, setFormData }) => {
otherExpenses: newExpenses,
});
}
+ handlers.onSubmit(event);
},
};
@@ -99,6 +101,8 @@ const AddOtherExpense = ({ data, goToPath, setFormData }) => {
? 'Add your additional living expense'
: 'Update your living expense';
+ const labelText = otherExpenses.length === index ? 'Add' : 'Update';
+
return (
<>
diff --git a/src/applications/financial-status-report/components/utilityBills/AddUtilityBill.jsx b/src/applications/financial-status-report/components/utilityBills/AddUtilityBill.jsx
index 3d3c95223f21..e5bfe607150d 100644
--- a/src/applications/financial-status-report/components/utilityBills/AddUtilityBill.jsx
+++ b/src/applications/financial-status-report/components/utilityBills/AddUtilityBill.jsx
@@ -6,6 +6,7 @@ import {
} from '@department-of-veterans-affairs/component-library/dist/react-bindings';
import { isValidCurrency } from '../../utils/validations';
import { MAX_UTILITY_NAME_LENGTH } from '../../constants/checkboxSelections';
+import ButtonGroup from '../shared/ButtonGroup';
const SUMMARY_PATH = '/utility-bill-summary';
const CHECKLIST_PATH = '/utility-bill-checklist';
@@ -81,6 +82,7 @@ const AddUtilityBill = ({ data, goToPath, setFormData }) => {
utilityRecords: newUtility,
});
}
+ handlers.onSubmit(event);
},
};
@@ -89,6 +91,8 @@ const AddUtilityBill = ({ data, goToPath, setFormData }) => {
? 'Add your additional utility bill'
: 'Update your utility bill';
+ const labelText = utilityRecords.length === index ? 'Add' : 'Update';
+
return (
<>
>
diff --git a/src/applications/financial-status-report/sass/financial-status-report.scss b/src/applications/financial-status-report/sass/financial-status-report.scss
index 3cecf6df2931..39123d893ebd 100644
--- a/src/applications/financial-status-report/sass/financial-status-report.scss
+++ b/src/applications/financial-status-report/sass/financial-status-report.scss
@@ -387,9 +387,12 @@ $chapters: veteranInformationChapter, householdIncomeChapter,
.va-button-override va-button {
&::part(button) {
white-space: nowrap;
+ z-index: 1;
+ position: relative;
}
@media (max-width: $xsmall-screen) {
width: -webkit-fill-available;
+ margin-bottom: 1rem;
&::part(button) {
width: 100%;
}
diff --git a/src/applications/financial-status-report/tests/e2e/efsr-5655.cypress.spec.js b/src/applications/financial-status-report/tests/e2e/efsr-5655.cypress.spec.js
index 159004bdcf39..80ad1be6d844 100644
--- a/src/applications/financial-status-report/tests/e2e/efsr-5655.cypress.spec.js
+++ b/src/applications/financial-status-report/tests/e2e/efsr-5655.cypress.spec.js
@@ -239,8 +239,9 @@ const testConfig = createTestConfig(
.shadow()
.find('input')
.type('1500');
- cy.findAllByText(/Continue/i, { selector: 'button' })
- .first()
+ cy.get('va-button[data-testid="custom-button-group-button"]')
+ .shadow()
+ .find('button:contains("Continue")')
.click({ waitForAnimations: true });
});
},
@@ -388,8 +389,9 @@ const testConfig = createTestConfig(
.shadow()
.find('input')
.type('10');
- cy.findAllByText(/Continue/i, { selector: 'button' })
- .first()
+ cy.get('va-button[data-testid="custom-button-group-button"]')
+ .shadow()
+ .find('button:contains("Continue")')
.click();
// cy.get('.usa-button-primary').click();
});
@@ -451,10 +453,9 @@ const testConfig = createTestConfig(
.shadow()
.find('input')
.type('10');
- cy.findAllByText(/Continue/i, {
- selector: 'button',
- })
- .first()
+ cy.get('va-button[data-testid="custom-button-group-button"]')
+ .shadow()
+ .find('button:contains("Continue")')
.click();
// cy.get('.usa-button-primary').click();
});