From 01edd06ea8f737ddaae624df78e29d4ea93c9c17 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Tue, 6 Aug 2024 14:06:40 -0500 Subject: [PATCH 01/17] VATEAM-87714: Add KISS configuration for Digital Forms (#2213) * Create postProcessDigitalForm function * Add nameAndDateOfBirth fragment * Create digitalForm GraphQL fragment * Import nameAndDateOfBirth into digitalForm fragment * Create digitalForm query object * Import digitalForm fragment into query object * Export postProcessDigitalForm as postProcess * Add Digital Forms to DATA_FILES array * Fix module imports * Fix typo * Adds blank line for consistent spacing. --------- Co-authored-by: Ryan Koch --- .../build/drupal/static-data-files/config.js | 12 ++++++++ .../static-data-files/config.unit.spec.js | 15 ++++++++++ .../fragments/digitalForm.graphql.js | 29 +++++++++++++++++++ .../digitalForm.graphql.unit.spec.js | 21 ++++++++++++++ .../fragments/nameAndDateOfBirth.graphql.js | 14 +++++++++ .../nameAndDateOfBirth.graphql.unit.spec.js | 14 +++++++++ .../static-data-files/digitalForm/index.js | 26 +++++++++++++++++ .../digitalForm/index.unit.spec.js | 22 ++++++++++++++ .../digitalForm/postProcessDigitalForm.js | 3 ++ .../postProcessDigitalForm.unit.spec.js | 12 ++++++++ 10 files changed, 168 insertions(+) create mode 100644 src/site/stages/build/drupal/static-data-files/config.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/index.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/config.js b/src/site/stages/build/drupal/static-data-files/config.js index 07dfec0733..1ce4b7cab8 100644 --- a/src/site/stages/build/drupal/static-data-files/config.js +++ b/src/site/stages/build/drupal/static-data-files/config.js @@ -1,3 +1,8 @@ +const { + query: queryDigitalForms, + postProcess: postProcessDigitalForm, +} = require('./digitalForm'); + const { query: queryVamcEhrSystem, postProcess: postProcessVamcEhrSystem, @@ -35,6 +40,13 @@ const DATA_FILE_PATH = 'data/cms'; * } */ const DATA_FILES = [ + { + description: 'Digital Forms', + filename: 'digital-forms.json', + query: queryDigitalForms, + queryType: 'graphql', + postProcess: postProcessDigitalForm, + }, { description: 'VAMC EHR System', filename: 'vamc-ehr.json', diff --git a/src/site/stages/build/drupal/static-data-files/config.unit.spec.js b/src/site/stages/build/drupal/static-data-files/config.unit.spec.js new file mode 100644 index 0000000000..11c8b34f49 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/config.unit.spec.js @@ -0,0 +1,15 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import { DATA_FILES } from './config'; + +describe('config', () => { + describe('DATA_FILES', () => { + it('includes Digital Forms', () => { + expect( + DATA_FILES.filter(dataFile => dataFile.description === 'Digital Forms') + .length, + ).to.eq(1); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js new file mode 100644 index 0000000000..e54079b532 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -0,0 +1,29 @@ +const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); + +/* + * + * The "Digital Form" Content Type in the VA.gov CMS + * + */ +module.exports = ` + ${nameAndDateOfBirth} + + fragment digitalForm on NodeDigitalForm { + nid + entityLabel + fieldVaFormNumber + fieldOmbNumber + fieldChapters { + entity { + entityId + type { + entity { + entityId + entityLabel + } + } + ...nameAndDateOfBirth + } + } + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js new file mode 100644 index 0000000000..3f8129cd94 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js @@ -0,0 +1,21 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import digitalForm from './digitalForm.graphql'; + +describe('digitalForm fragment', () => { + it('includes form fields', () => { + expect(digitalForm).to.have.string('nid'); + expect(digitalForm).to.have.string('entityLabel'); + expect(digitalForm).to.have.string('fieldVaFormNumber'); + expect(digitalForm).to.have.string('fieldOmbNumber'); + expect(digitalForm).to.have.string('fieldChapters'); + }); + + describe('chapter fragments', () => { + it('imports the nameAndDateOfBirth fragment', () => { + expect(digitalForm).to.have.string('fragment nameAndDateOfBirth'); + expect(digitalForm).to.have.string('...nameAndDateOfBirth'); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js new file mode 100644 index 0000000000..e27c73d00b --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js @@ -0,0 +1,14 @@ +/* + * + * The "Name and Date of Birth" Digital Form pattern. + * + * Pattern documentation: + * https://design.va.gov/patterns/ask-users-for/names + * + */ +module.exports = ` + fragment nameAndDateOfBirth on ParagraphDigitalFormNameAndDateOfBi { + fieldTitle + fieldIncludeDateOfBirth + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js new file mode 100644 index 0000000000..d2cf16bd17 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js @@ -0,0 +1,14 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import nameAndDateOfBirth from './nameAndDateOfBirth.graphql'; + +describe('nameAndDateOfBirth fragment', () => { + it('includes fieldTitle', () => { + expect(nameAndDateOfBirth).to.have.string('fieldTitle'); + }); + + it('includes fieldIncludeDateOfBirth', () => { + expect(nameAndDateOfBirth).to.have.string('fieldIncludeDateOfBirth'); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.js new file mode 100644 index 0000000000..eb989dbcaf --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/index.js @@ -0,0 +1,26 @@ +const digitalForm = require('./fragments/digitalForm.graphql'); +const { postProcessDigitalForm } = require('./postProcessDigitalForm'); + +const query = ` + ${digitalForm} + + query ($onlyPublishedContent: Boolean!) { + nodeQuery( + filter: { + conditions: [ + { field: "status", value: "1", enabled: $onlyPublishedContent }, + { field: "type", value: "digital_form" } + ] + } + ) { + entities { + ... digitalForm + } + } + } +`; + +module.exports = { + query, + postProcess: postProcessDigitalForm, +}; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js new file mode 100644 index 0000000000..d95a670227 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js @@ -0,0 +1,22 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import { query, postProcess } from './index'; + +describe('digitalForm', () => { + describe('query', () => { + it('returns digital_form entities', () => { + expect(query).to.have.string('digital_form'); + }); + it('imports the digitalForm fragment', () => { + expect(query).to.have.string('fragment digitalForm'); + expect(query).to.have.string('... digitalForm'); + }); + }); + + describe('postProcess', () => { + it('imports postProcessDigitalForm', () => { + expect(() => postProcess('test result')).to.not.throw(); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js new file mode 100644 index 0000000000..71fabf2199 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -0,0 +1,3 @@ +const postProcessDigitalForm = queryResult => queryResult; + +module.exports.postProcessDigitalForm = postProcessDigitalForm; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js new file mode 100644 index 0000000000..d0be9f34fc --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -0,0 +1,12 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; + +const { postProcessDigitalForm } = require('./postProcessDigitalForm'); + +describe('postProcessDigitalForm', () => { + it('returns queryResult with no changes', () => { + const queryResult = { data: { form: {} } }; + expect(postProcessDigitalForm(queryResult)).to.eq(queryResult); + }); +}); From fd225479c646aeb2d04abaa8bf15bcd90e78f265 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Sat, 10 Aug 2024 07:49:54 -0500 Subject: [PATCH 02/17] VATEAM-88634: Create a normalization layer for Digital Forms (#2215) * Add normalizeForms step to postProcessDigitalForm * Add subtitle to normalized form * Add OMB Number to normalized form * Normalize chapters for each form * Add additional fields for Name and Date of Birth step * Fix import spec * Remove redundant JSON parsing * Remove JSON conversion from returned value * Add formID and rename id to cmsId * Remove subTitle * Refactor normalizeForms method * Refactor normalizeChapters * Defend against malformed query responses * Remove unused import --- .../digitalForm/index.unit.spec.js | 32 +++- .../digitalForm/postProcessDigitalForm.js | 51 ++++- .../postProcessDigitalForm.unit.spec.js | 174 +++++++++++++++++- 3 files changed, 252 insertions(+), 5 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js index d95a670227..bd504fb47e 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js @@ -16,7 +16,37 @@ describe('digitalForm', () => { describe('postProcess', () => { it('imports postProcessDigitalForm', () => { - expect(() => postProcess('test result')).to.not.throw(); + const queryResult = { + data: { + nodeQuery: { + entities: [ + { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }, + ], + }, + }, + }; + + expect(() => postProcess(queryResult)).to.not.throw(); }); }); }); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 71fabf2199..3541cb8a8b 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -1,3 +1,52 @@ -const postProcessDigitalForm = queryResult => queryResult; +const { logDrupal } = require('../../utilities-drupal'); + +const extractAdditionalFields = entity => { + const additionalFields = {}; + + if (entity.type.entity.entityId === 'digital_form_name_and_date_of_bi') { + additionalFields.includeDateOfBirth = entity.fieldIncludeDateOfBirth; + } + + return additionalFields; +}; +const extractForms = resultObject => resultObject?.data?.nodeQuery?.entities; + +const normalizeChapter = ({ entity }) => { + return { + id: parseInt(entity.entityId, 10), + chapterTitle: entity.fieldTitle, + type: entity.type.entity.entityId, + pageTitle: entity.type.entity.entityLabel, + additionalFields: extractAdditionalFields(entity), + }; +}; + +const normalizeForm = (form, logger = logDrupal) => { + try { + return { + cmsId: form.nid, + formId: form.fieldVaFormNumber, + title: form.entityLabel, + ombNumber: form.fieldOmbNumber, + chapters: form.fieldChapters.map(normalizeChapter), + }; + } catch (error) { + logger(`There was an error with this form: ${error}`); + return {}; + } +}; + +const postProcessDigitalForm = (queryResult, logger = logDrupal) => { + // queryResult was already parsed by graphQLApiClient + const forms = extractForms(queryResult); + + // will be turned into JSON by writeProcessedDataFilesToCache + if (forms) { + return forms.map(form => normalizeForm(form, logger)); + } + + logger(`Malformed result query: ${queryResult}`); + return []; +}; module.exports.postProcessDigitalForm = postProcessDigitalForm; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index d0be9f34fc..d693ef648b 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -1,12 +1,180 @@ /* eslint-disable @department-of-veterans-affairs/axe-check-required */ import { expect } from 'chai'; +import sinon from 'sinon'; const { postProcessDigitalForm } = require('./postProcessDigitalForm'); describe('postProcessDigitalForm', () => { - it('returns queryResult with no changes', () => { - const queryResult = { data: { form: {} } }; - expect(postProcessDigitalForm(queryResult)).to.eq(queryResult); + context('with a well-formed query result', () => { + const queryResult = { + data: { + nodeQuery: { + entities: [ + { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }, + { + nid: 71004, + entityLabel: 'Form with Two Steps', + fieldVaFormNumber: '222222', + fieldOmbNumber: '1212-1212', + fieldChapters: [ + { + entity: { + entityId: '157906', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'First Step', + fieldIncludeDateOfBirth: true, + }, + }, + { + entity: { + entityId: '157907', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'Second Step', + fieldIncludeDateOfBirth: false, + }, + }, + ], + }, + ], + }, + }, + }; + let processedResult; + + beforeEach(() => { + processedResult = postProcessDigitalForm(queryResult); + }); + + it('returns a normalized JSON object', () => { + const testForm = processedResult[1]; + const testChapter = testForm.chapters[1]; + + expect(processedResult.length).to.eq(2); + expect(testForm.cmsId).to.eq(71004); + expect(testForm.formId).to.eq('222222'); + expect(testForm.title).to.eq('Form with Two Steps'); + expect(testForm.ombNumber).to.eq('1212-1212'); + expect(testForm.chapters.length).to.eq(2); + expect(testChapter.id).to.eq(157907); + expect(testChapter.chapterTitle).to.eq('Second Step'); + expect(testChapter.type).to.eq('digital_form_name_and_date_of_bi'); + expect(testChapter.pageTitle).to.eq('Name and Date of Birth'); + expect(Object.keys(testChapter.additionalFields).length).to.eq(1); + }); + + context('with a Name and Date of Birth step', () => { + it('includes the appropriate fields', () => { + const { additionalFields } = processedResult[1].chapters[1]; + + expect(additionalFields.includeDateOfBirth).to.eq(false); + }); + }); + }); + + context('with a malformed query result', () => { + let queryResult; + let processedResult; + let logger; + + beforeEach(() => { + logger = sinon.spy(); + }); + + context('when the entire query is bad', () => { + beforeEach(() => { + queryResult = { + wrongKey: 'oops! bad data!', + }; + processedResult = postProcessDigitalForm(queryResult, logger); + }); + + it('logs the error', () => { + expect(logger.calledOnce).to.eq(true); + }); + + it('returns an empty array', () => { + expect(processedResult.length).to.eq(0); + }); + }); + + context('when only one form is malformed', () => { + beforeEach(() => { + queryResult = { + data: { + nodeQuery: { + entities: [ + { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }, + { + nid: '71004', + entityLabel: 'This form has problems', + fieldVaFormNumber: 222222, + fieldChapters: 'no chapters', + }, + ], + }, + }, + }; + processedResult = postProcessDigitalForm(queryResult, logger); + }); + + it('logs the error', () => { + expect(logger.calledOnce).to.eq(true); + }); + + it('returns the other forms', () => { + expect(processedResult[0].cmsId).to.eq(71002); + }); + }); }); }); From 49ce1af2ae667eed6a4bb20c1873510c56c89515 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Thu, 29 Aug 2024 12:04:54 -0500 Subject: [PATCH 03/17] Add OMB info to Digital Form GraphQL query --- .../digitalForm/fragments/digitalForm.graphql.js | 4 ++++ .../digitalForm/fragments/digitalForm.graphql.unit.spec.js | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index e54079b532..78741337d3 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -13,6 +13,10 @@ module.exports = ` entityLabel fieldVaFormNumber fieldOmbNumber + fieldRespondentBurden + fieldExpirationDate { + value + } fieldChapters { entity { entityId diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js index 3f8129cd94..b31db07e1d 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js @@ -8,10 +8,15 @@ describe('digitalForm fragment', () => { expect(digitalForm).to.have.string('nid'); expect(digitalForm).to.have.string('entityLabel'); expect(digitalForm).to.have.string('fieldVaFormNumber'); - expect(digitalForm).to.have.string('fieldOmbNumber'); expect(digitalForm).to.have.string('fieldChapters'); }); + it('include OMB info', () => { + expect(digitalForm).to.have.string('fieldOmbNumber'); + expect(digitalForm).to.have.string('fieldRespondentBurden'); + expect(digitalForm).to.have.string('fieldExpirationDate'); + }); + describe('chapter fragments', () => { it('imports the nameAndDateOfBirth fragment', () => { expect(digitalForm).to.have.string('fragment nameAndDateOfBirth'); From 0cec64290abe51322a5e0dd0d6c8c6590a0e2b03 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Thu, 29 Aug 2024 13:26:58 -0500 Subject: [PATCH 04/17] Normalize OMB info --- .../digitalForm/postProcessDigitalForm.js | 11 +- .../postProcessDigitalForm.unit.spec.js | 157 +++++++++--------- 2 files changed, 88 insertions(+), 80 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 3541cb8a8b..d81b634f49 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -11,6 +11,11 @@ const extractAdditionalFields = entity => { }; const extractForms = resultObject => resultObject?.data?.nodeQuery?.entities; +const formatDate = dateString => + // Depending on what time zone our servers operate on, we may need to adjust + // this offset. + new Date(Date.parse(`${dateString}T04:00-05:00`)).toLocaleDateString(); + const normalizeChapter = ({ entity }) => { return { id: parseInt(entity.entityId, 10), @@ -27,7 +32,11 @@ const normalizeForm = (form, logger = logDrupal) => { cmsId: form.nid, formId: form.fieldVaFormNumber, title: form.entityLabel, - ombNumber: form.fieldOmbNumber, + ombInfo: { + expDate: formatDate(form.fieldExpirationDate.value), + ombNumber: form.fieldOmbNumber, + resBurden: form.fieldRespondentBurden, + }, chapters: form.fieldChapters.map(normalizeChapter), }; } catch (error) { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index d693ef648b..0e6588efea 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -6,67 +6,76 @@ import sinon from 'sinon'; const { postProcessDigitalForm } = require('./postProcessDigitalForm'); describe('postProcessDigitalForm', () => { + const oneStepEntity = { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldRespondentBurden: 48, + fieldExpirationDate: { + value: '2025-06-11', + }, + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }; + context('with a well-formed query result', () => { + const twoStepEntity = { + nid: 71004, + entityLabel: 'Form with Two Steps', + fieldVaFormNumber: '222222', + fieldOmbNumber: '1212-1212', + fieldRespondentBurden: 30, + fieldExpirationDate: { + value: '2027-01-29', + }, + fieldChapters: [ + { + entity: { + entityId: '157906', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'First Step', + fieldIncludeDateOfBirth: true, + }, + }, + { + entity: { + entityId: '157907', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'Second Step', + fieldIncludeDateOfBirth: false, + }, + }, + ], + }; + const queryResult = { data: { nodeQuery: { - entities: [ - { - nid: 71002, - entityLabel: 'Form with One Step', - fieldVaFormNumber: '11111', - fieldOmbNumber: '1111-1111', - fieldChapters: [ - { - entity: { - entityId: '157904', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'The Only Step', - fieldIncludeDateOfBirth: true, - }, - }, - ], - }, - { - nid: 71004, - entityLabel: 'Form with Two Steps', - fieldVaFormNumber: '222222', - fieldOmbNumber: '1212-1212', - fieldChapters: [ - { - entity: { - entityId: '157906', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'First Step', - fieldIncludeDateOfBirth: true, - }, - }, - { - entity: { - entityId: '157907', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'Second Step', - fieldIncludeDateOfBirth: false, - }, - }, - ], - }, - ], + entities: [oneStepEntity, twoStepEntity], }, }, }; @@ -84,7 +93,6 @@ describe('postProcessDigitalForm', () => { expect(testForm.cmsId).to.eq(71004); expect(testForm.formId).to.eq('222222'); expect(testForm.title).to.eq('Form with Two Steps'); - expect(testForm.ombNumber).to.eq('1212-1212'); expect(testForm.chapters.length).to.eq(2); expect(testChapter.id).to.eq(157907); expect(testChapter.chapterTitle).to.eq('Second Step'); @@ -93,6 +101,17 @@ describe('postProcessDigitalForm', () => { expect(Object.keys(testChapter.additionalFields).length).to.eq(1); }); + it('includes an OMB info object', () => { + const { ombInfo } = processedResult[1]; + const formattedDate = new Date( + Date.parse(`${twoStepEntity.fieldExpirationDate.value}T04:00-05:00`), + ).toLocaleDateString(); + + expect(ombInfo.ombNumber).to.eq(twoStepEntity.fieldOmbNumber); + expect(ombInfo.expDate).to.eq(formattedDate); + expect(ombInfo.resBurden).to.eq(twoStepEntity.fieldRespondentBurden); + }); + context('with a Name and Date of Birth step', () => { it('includes the appropriate fields', () => { const { additionalFields } = processedResult[1].chapters[1]; @@ -134,27 +153,7 @@ describe('postProcessDigitalForm', () => { data: { nodeQuery: { entities: [ - { - nid: 71002, - entityLabel: 'Form with One Step', - fieldVaFormNumber: '11111', - fieldOmbNumber: '1111-1111', - fieldChapters: [ - { - entity: { - entityId: '157904', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'The Only Step', - fieldIncludeDateOfBirth: true, - }, - }, - ], - }, + oneStepEntity, { nid: '71004', entityLabel: 'This form has problems', From 4d7dc20c9d8317bcbcefbe96f4da0125436dc2d7 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Fri, 6 Sep 2024 11:18:26 -0500 Subject: [PATCH 05/17] Remove Date object from formatDate --- .../digitalForm/postProcessDigitalForm.js | 9 +++++---- .../digitalForm/postProcessDigitalForm.unit.spec.js | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index d81b634f49..7e8c7e8ab2 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -11,10 +11,11 @@ const extractAdditionalFields = entity => { }; const extractForms = resultObject => resultObject?.data?.nodeQuery?.entities; -const formatDate = dateString => - // Depending on what time zone our servers operate on, we may need to adjust - // this offset. - new Date(Date.parse(`${dateString}T04:00-05:00`)).toLocaleDateString(); +const formatDate = dateString => { + const removeLeadingZero = s => s.replace(/^0+/, ''); + const [year, month, day] = dateString.split('-'); + return `${removeLeadingZero(month)}/${removeLeadingZero(day)}/${year}`; +}; const normalizeChapter = ({ entity }) => { return { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index 0e6588efea..6bb3cf08f9 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -33,6 +33,8 @@ describe('postProcessDigitalForm', () => { }; context('with a well-formed query result', () => { + const expDate = '2027-01-29'; + const twoStepEntity = { nid: 71004, entityLabel: 'Form with Two Steps', @@ -40,7 +42,7 @@ describe('postProcessDigitalForm', () => { fieldOmbNumber: '1212-1212', fieldRespondentBurden: 30, fieldExpirationDate: { - value: '2027-01-29', + value: expDate, }, fieldChapters: [ { @@ -103,9 +105,8 @@ describe('postProcessDigitalForm', () => { it('includes an OMB info object', () => { const { ombInfo } = processedResult[1]; - const formattedDate = new Date( - Date.parse(`${twoStepEntity.fieldExpirationDate.value}T04:00-05:00`), - ).toLocaleDateString(); + // expDate is 2027-01-29 + const formattedDate = '1/29/2027'; expect(ombInfo.ombNumber).to.eq(twoStepEntity.fieldOmbNumber); expect(ombInfo.expDate).to.eq(formattedDate); From 52edb5712f47128afef7822bae585aada3a6c852 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Thu, 12 Sep 2024 07:18:14 -0500 Subject: [PATCH 06/17] VATEAM-90733: Normalize OMB info fields (#2252) * Add OMB info to Digital Form GraphQL query * Normalize OMB info * Remove Date object from formatDate --- .../fragments/digitalForm.graphql.js | 4 + .../digitalForm.graphql.unit.spec.js | 7 +- .../digitalForm/postProcessDigitalForm.js | 12 +- .../postProcessDigitalForm.unit.spec.js | 158 +++++++++--------- 4 files changed, 100 insertions(+), 81 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index e54079b532..78741337d3 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -13,6 +13,10 @@ module.exports = ` entityLabel fieldVaFormNumber fieldOmbNumber + fieldRespondentBurden + fieldExpirationDate { + value + } fieldChapters { entity { entityId diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js index 3f8129cd94..b31db07e1d 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js @@ -8,10 +8,15 @@ describe('digitalForm fragment', () => { expect(digitalForm).to.have.string('nid'); expect(digitalForm).to.have.string('entityLabel'); expect(digitalForm).to.have.string('fieldVaFormNumber'); - expect(digitalForm).to.have.string('fieldOmbNumber'); expect(digitalForm).to.have.string('fieldChapters'); }); + it('include OMB info', () => { + expect(digitalForm).to.have.string('fieldOmbNumber'); + expect(digitalForm).to.have.string('fieldRespondentBurden'); + expect(digitalForm).to.have.string('fieldExpirationDate'); + }); + describe('chapter fragments', () => { it('imports the nameAndDateOfBirth fragment', () => { expect(digitalForm).to.have.string('fragment nameAndDateOfBirth'); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 3541cb8a8b..7e8c7e8ab2 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -11,6 +11,12 @@ const extractAdditionalFields = entity => { }; const extractForms = resultObject => resultObject?.data?.nodeQuery?.entities; +const formatDate = dateString => { + const removeLeadingZero = s => s.replace(/^0+/, ''); + const [year, month, day] = dateString.split('-'); + return `${removeLeadingZero(month)}/${removeLeadingZero(day)}/${year}`; +}; + const normalizeChapter = ({ entity }) => { return { id: parseInt(entity.entityId, 10), @@ -27,7 +33,11 @@ const normalizeForm = (form, logger = logDrupal) => { cmsId: form.nid, formId: form.fieldVaFormNumber, title: form.entityLabel, - ombNumber: form.fieldOmbNumber, + ombInfo: { + expDate: formatDate(form.fieldExpirationDate.value), + ombNumber: form.fieldOmbNumber, + resBurden: form.fieldRespondentBurden, + }, chapters: form.fieldChapters.map(normalizeChapter), }; } catch (error) { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index d693ef648b..6bb3cf08f9 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -6,67 +6,78 @@ import sinon from 'sinon'; const { postProcessDigitalForm } = require('./postProcessDigitalForm'); describe('postProcessDigitalForm', () => { + const oneStepEntity = { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldRespondentBurden: 48, + fieldExpirationDate: { + value: '2025-06-11', + }, + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }; + context('with a well-formed query result', () => { + const expDate = '2027-01-29'; + + const twoStepEntity = { + nid: 71004, + entityLabel: 'Form with Two Steps', + fieldVaFormNumber: '222222', + fieldOmbNumber: '1212-1212', + fieldRespondentBurden: 30, + fieldExpirationDate: { + value: expDate, + }, + fieldChapters: [ + { + entity: { + entityId: '157906', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'First Step', + fieldIncludeDateOfBirth: true, + }, + }, + { + entity: { + entityId: '157907', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'Second Step', + fieldIncludeDateOfBirth: false, + }, + }, + ], + }; + const queryResult = { data: { nodeQuery: { - entities: [ - { - nid: 71002, - entityLabel: 'Form with One Step', - fieldVaFormNumber: '11111', - fieldOmbNumber: '1111-1111', - fieldChapters: [ - { - entity: { - entityId: '157904', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'The Only Step', - fieldIncludeDateOfBirth: true, - }, - }, - ], - }, - { - nid: 71004, - entityLabel: 'Form with Two Steps', - fieldVaFormNumber: '222222', - fieldOmbNumber: '1212-1212', - fieldChapters: [ - { - entity: { - entityId: '157906', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'First Step', - fieldIncludeDateOfBirth: true, - }, - }, - { - entity: { - entityId: '157907', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'Second Step', - fieldIncludeDateOfBirth: false, - }, - }, - ], - }, - ], + entities: [oneStepEntity, twoStepEntity], }, }, }; @@ -84,7 +95,6 @@ describe('postProcessDigitalForm', () => { expect(testForm.cmsId).to.eq(71004); expect(testForm.formId).to.eq('222222'); expect(testForm.title).to.eq('Form with Two Steps'); - expect(testForm.ombNumber).to.eq('1212-1212'); expect(testForm.chapters.length).to.eq(2); expect(testChapter.id).to.eq(157907); expect(testChapter.chapterTitle).to.eq('Second Step'); @@ -93,6 +103,16 @@ describe('postProcessDigitalForm', () => { expect(Object.keys(testChapter.additionalFields).length).to.eq(1); }); + it('includes an OMB info object', () => { + const { ombInfo } = processedResult[1]; + // expDate is 2027-01-29 + const formattedDate = '1/29/2027'; + + expect(ombInfo.ombNumber).to.eq(twoStepEntity.fieldOmbNumber); + expect(ombInfo.expDate).to.eq(formattedDate); + expect(ombInfo.resBurden).to.eq(twoStepEntity.fieldRespondentBurden); + }); + context('with a Name and Date of Birth step', () => { it('includes the appropriate fields', () => { const { additionalFields } = processedResult[1].chapters[1]; @@ -134,27 +154,7 @@ describe('postProcessDigitalForm', () => { data: { nodeQuery: { entities: [ - { - nid: 71002, - entityLabel: 'Form with One Step', - fieldVaFormNumber: '11111', - fieldOmbNumber: '1111-1111', - fieldChapters: [ - { - entity: { - entityId: '157904', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'The Only Step', - fieldIncludeDateOfBirth: true, - }, - }, - ], - }, + oneStepEntity, { nid: '71004', entityLabel: 'This form has problems', From b64c733b627e85f08ebf8967e7f9c7d4b9f932e0 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Mon, 16 Sep 2024 14:07:01 -0500 Subject: [PATCH 07/17] Add Identification Information fragment --- .../identificationInformation.graphql.js | 14 ++++++++++++++ ...identificationInformation.graphql.unit.spec.js | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.js new file mode 100644 index 0000000000..8d583cf6d5 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.js @@ -0,0 +1,14 @@ +/* + * + * The "Identification Information" Digital Form pattern. + * + * Pattern documentation: + * https://design.va.gov/patterns/ask-users-for/social-security-number + * + */ +module.exports = ` + fragment identificationInformation on ParagraphDigitalFormIdentificationInfo { + fieldTitle + fieldIncludeVeteranSService + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js new file mode 100644 index 0000000000..3935815a3f --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js @@ -0,0 +1,15 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import identificationInformation from './identificationInformation.graphql'; + +describe('identificationInformation fragment', () => { + it('includes fieldTitle', () => { + expect(identificationInformation).to.have.string('fieldTitle'); + }); + it('includes fieldIncludeVeteranSService', () => { + expect(identificationInformation).to.have.string( + 'fieldIncludeVeteranSService', + ); + }); +}); From 62fdaabace3269bf9ba7e781e4a04d331df241b8 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Mon, 16 Sep 2024 14:12:07 -0500 Subject: [PATCH 08/17] Import identificationInformation fragment into digitalForm fragment --- .../digitalForm/fragments/digitalForm.graphql.js | 5 ++++- .../digitalForm/fragments/digitalForm.graphql.unit.spec.js | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index 78741337d3..925b8d9c87 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -1,4 +1,5 @@ -const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); +import identificationInformation from './identificationInformation.graphql'; +import nameAndDateOfBirth from './nameAndDateOfBirth.graphql'; /* * @@ -6,6 +7,7 @@ const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); * */ module.exports = ` + ${identificationInformation} ${nameAndDateOfBirth} fragment digitalForm on NodeDigitalForm { @@ -26,6 +28,7 @@ module.exports = ` entityLabel } } + ...identificationInformation ...nameAndDateOfBirth } } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js index b31db07e1d..1002b7046c 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js @@ -18,6 +18,11 @@ describe('digitalForm fragment', () => { }); describe('chapter fragments', () => { + it('imports the identificationInformation fragment', () => { + expect(digitalForm).to.have.string('fragment identificationInformation'); + expect(digitalForm).to.have.string('...identificationInformation'); + }); + it('imports the nameAndDateOfBirth fragment', () => { expect(digitalForm).to.have.string('fragment nameAndDateOfBirth'); expect(digitalForm).to.have.string('...nameAndDateOfBirth'); From ee1a69fb3d95e45dd22f8af0de3b681bb634751a Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Mon, 16 Sep 2024 15:02:25 -0500 Subject: [PATCH 09/17] Extract Identification Information fields --- .../digitalForm/postProcessDigitalForm.js | 5 +- .../postProcessDigitalForm.unit.spec.js | 46 +++++++++++++++---- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 7e8c7e8ab2..b010ed63d0 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -2,9 +2,12 @@ const { logDrupal } = require('../../utilities-drupal'); const extractAdditionalFields = entity => { const additionalFields = {}; + const { entityId } = entity.type.entity; - if (entity.type.entity.entityId === 'digital_form_name_and_date_of_bi') { + if (entityId === 'digital_form_name_and_date_of_bi') { additionalFields.includeDateOfBirth = entity.fieldIncludeDateOfBirth; + } else if (entityId === 'digital_form_identification_info') { + additionalFields.includeServiceNumber = entity.fieldIncludeVeteranSService; } return additionalFields; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index 6bb3cf08f9..d734efe58c 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -81,14 +81,10 @@ describe('postProcessDigitalForm', () => { }, }, }; - let processedResult; - - beforeEach(() => { - processedResult = postProcessDigitalForm(queryResult); - }); it('returns a normalized JSON object', () => { - const testForm = processedResult[1]; + const processedResult = postProcessDigitalForm(queryResult); + const [, testForm] = processedResult; const testChapter = testForm.chapters[1]; expect(processedResult.length).to.eq(2); @@ -104,7 +100,8 @@ describe('postProcessDigitalForm', () => { }); it('includes an OMB info object', () => { - const { ombInfo } = processedResult[1]; + const [, testForm] = postProcessDigitalForm(queryResult); + const { ombInfo } = testForm; // expDate is 2027-01-29 const formattedDate = '1/29/2027'; @@ -115,11 +112,44 @@ describe('postProcessDigitalForm', () => { context('with a Name and Date of Birth step', () => { it('includes the appropriate fields', () => { - const { additionalFields } = processedResult[1].chapters[1]; + const [, testForm] = postProcessDigitalForm(queryResult); + const { additionalFields } = testForm.chapters[1]; expect(additionalFields.includeDateOfBirth).to.eq(false); }); }); + + context('with an Identification Information step', () => { + let additionalFields; + + beforeEach(() => { + twoStepEntity.fieldChapters.push({ + entity: { + entityId: '160594', + type: { + entity: { + entityId: 'digital_form_identification_info', + entityLabel: 'Identification Information', + }, + }, + fieldTitle: 'Identification information', + fieldIncludeVeteranSService: true, + }, + }); + const [, testForm] = postProcessDigitalForm(queryResult); + [{ additionalFields }] = testForm.chapters.filter( + chapter => chapter.type === 'digital_form_identification_info', + ); + }); + + it('includes appropriate fields', () => { + expect(additionalFields.includeServiceNumber).to.eq(true); + }); + + it('does not include inappropriate fields', () => { + expect(additionalFields.includeDateOfBirth).to.eq(undefined); + }); + }); }); context('with a malformed query result', () => { From 9a6014e6d78fa0b15e331d54da6fced064b8062d Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Mon, 16 Sep 2024 15:05:42 -0500 Subject: [PATCH 10/17] Fix imports --- .../digitalForm/fragments/digitalForm.graphql.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index 925b8d9c87..7c47c8c381 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -1,5 +1,5 @@ -import identificationInformation from './identificationInformation.graphql'; -import nameAndDateOfBirth from './nameAndDateOfBirth.graphql'; +const identificationInformation = require('./identificationInformation.graphql'); +const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); /* * From 66f50484a869b022cbc657891e8012da87f74ae1 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Tue, 6 Aug 2024 14:06:40 -0500 Subject: [PATCH 11/17] VATEAM-87714: Add KISS configuration for Digital Forms (#2213) * Create postProcessDigitalForm function * Add nameAndDateOfBirth fragment * Create digitalForm GraphQL fragment * Import nameAndDateOfBirth into digitalForm fragment * Create digitalForm query object * Import digitalForm fragment into query object * Export postProcessDigitalForm as postProcess * Add Digital Forms to DATA_FILES array * Fix module imports * Fix typo * Adds blank line for consistent spacing. --------- Co-authored-by: Ryan Koch --- .../build/drupal/static-data-files/config.js | 12 ++++++++ .../static-data-files/config.unit.spec.js | 15 ++++++++++ .../fragments/digitalForm.graphql.js | 29 +++++++++++++++++++ .../digitalForm.graphql.unit.spec.js | 21 ++++++++++++++ .../fragments/nameAndDateOfBirth.graphql.js | 14 +++++++++ .../nameAndDateOfBirth.graphql.unit.spec.js | 14 +++++++++ .../static-data-files/digitalForm/index.js | 26 +++++++++++++++++ .../digitalForm/index.unit.spec.js | 22 ++++++++++++++ .../digitalForm/postProcessDigitalForm.js | 3 ++ .../postProcessDigitalForm.unit.spec.js | 12 ++++++++ 10 files changed, 168 insertions(+) create mode 100644 src/site/stages/build/drupal/static-data-files/config.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/index.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/config.js b/src/site/stages/build/drupal/static-data-files/config.js index 07dfec0733..1ce4b7cab8 100644 --- a/src/site/stages/build/drupal/static-data-files/config.js +++ b/src/site/stages/build/drupal/static-data-files/config.js @@ -1,3 +1,8 @@ +const { + query: queryDigitalForms, + postProcess: postProcessDigitalForm, +} = require('./digitalForm'); + const { query: queryVamcEhrSystem, postProcess: postProcessVamcEhrSystem, @@ -35,6 +40,13 @@ const DATA_FILE_PATH = 'data/cms'; * } */ const DATA_FILES = [ + { + description: 'Digital Forms', + filename: 'digital-forms.json', + query: queryDigitalForms, + queryType: 'graphql', + postProcess: postProcessDigitalForm, + }, { description: 'VAMC EHR System', filename: 'vamc-ehr.json', diff --git a/src/site/stages/build/drupal/static-data-files/config.unit.spec.js b/src/site/stages/build/drupal/static-data-files/config.unit.spec.js new file mode 100644 index 0000000000..11c8b34f49 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/config.unit.spec.js @@ -0,0 +1,15 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import { DATA_FILES } from './config'; + +describe('config', () => { + describe('DATA_FILES', () => { + it('includes Digital Forms', () => { + expect( + DATA_FILES.filter(dataFile => dataFile.description === 'Digital Forms') + .length, + ).to.eq(1); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js new file mode 100644 index 0000000000..e54079b532 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -0,0 +1,29 @@ +const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); + +/* + * + * The "Digital Form" Content Type in the VA.gov CMS + * + */ +module.exports = ` + ${nameAndDateOfBirth} + + fragment digitalForm on NodeDigitalForm { + nid + entityLabel + fieldVaFormNumber + fieldOmbNumber + fieldChapters { + entity { + entityId + type { + entity { + entityId + entityLabel + } + } + ...nameAndDateOfBirth + } + } + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js new file mode 100644 index 0000000000..3f8129cd94 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js @@ -0,0 +1,21 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import digitalForm from './digitalForm.graphql'; + +describe('digitalForm fragment', () => { + it('includes form fields', () => { + expect(digitalForm).to.have.string('nid'); + expect(digitalForm).to.have.string('entityLabel'); + expect(digitalForm).to.have.string('fieldVaFormNumber'); + expect(digitalForm).to.have.string('fieldOmbNumber'); + expect(digitalForm).to.have.string('fieldChapters'); + }); + + describe('chapter fragments', () => { + it('imports the nameAndDateOfBirth fragment', () => { + expect(digitalForm).to.have.string('fragment nameAndDateOfBirth'); + expect(digitalForm).to.have.string('...nameAndDateOfBirth'); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js new file mode 100644 index 0000000000..e27c73d00b --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.js @@ -0,0 +1,14 @@ +/* + * + * The "Name and Date of Birth" Digital Form pattern. + * + * Pattern documentation: + * https://design.va.gov/patterns/ask-users-for/names + * + */ +module.exports = ` + fragment nameAndDateOfBirth on ParagraphDigitalFormNameAndDateOfBi { + fieldTitle + fieldIncludeDateOfBirth + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js new file mode 100644 index 0000000000..d2cf16bd17 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js @@ -0,0 +1,14 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import nameAndDateOfBirth from './nameAndDateOfBirth.graphql'; + +describe('nameAndDateOfBirth fragment', () => { + it('includes fieldTitle', () => { + expect(nameAndDateOfBirth).to.have.string('fieldTitle'); + }); + + it('includes fieldIncludeDateOfBirth', () => { + expect(nameAndDateOfBirth).to.have.string('fieldIncludeDateOfBirth'); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.js new file mode 100644 index 0000000000..eb989dbcaf --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/index.js @@ -0,0 +1,26 @@ +const digitalForm = require('./fragments/digitalForm.graphql'); +const { postProcessDigitalForm } = require('./postProcessDigitalForm'); + +const query = ` + ${digitalForm} + + query ($onlyPublishedContent: Boolean!) { + nodeQuery( + filter: { + conditions: [ + { field: "status", value: "1", enabled: $onlyPublishedContent }, + { field: "type", value: "digital_form" } + ] + } + ) { + entities { + ... digitalForm + } + } + } +`; + +module.exports = { + query, + postProcess: postProcessDigitalForm, +}; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js new file mode 100644 index 0000000000..d95a670227 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js @@ -0,0 +1,22 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import { query, postProcess } from './index'; + +describe('digitalForm', () => { + describe('query', () => { + it('returns digital_form entities', () => { + expect(query).to.have.string('digital_form'); + }); + it('imports the digitalForm fragment', () => { + expect(query).to.have.string('fragment digitalForm'); + expect(query).to.have.string('... digitalForm'); + }); + }); + + describe('postProcess', () => { + it('imports postProcessDigitalForm', () => { + expect(() => postProcess('test result')).to.not.throw(); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js new file mode 100644 index 0000000000..71fabf2199 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -0,0 +1,3 @@ +const postProcessDigitalForm = queryResult => queryResult; + +module.exports.postProcessDigitalForm = postProcessDigitalForm; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js new file mode 100644 index 0000000000..d0be9f34fc --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -0,0 +1,12 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; + +const { postProcessDigitalForm } = require('./postProcessDigitalForm'); + +describe('postProcessDigitalForm', () => { + it('returns queryResult with no changes', () => { + const queryResult = { data: { form: {} } }; + expect(postProcessDigitalForm(queryResult)).to.eq(queryResult); + }); +}); From e3d84e6123470259626e967780a57979da201fb5 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Sat, 10 Aug 2024 07:49:54 -0500 Subject: [PATCH 12/17] VATEAM-88634: Create a normalization layer for Digital Forms (#2215) * Add normalizeForms step to postProcessDigitalForm * Add subtitle to normalized form * Add OMB Number to normalized form * Normalize chapters for each form * Add additional fields for Name and Date of Birth step * Fix import spec * Remove redundant JSON parsing * Remove JSON conversion from returned value * Add formID and rename id to cmsId * Remove subTitle * Refactor normalizeForms method * Refactor normalizeChapters * Defend against malformed query responses * Remove unused import --- .../digitalForm/index.unit.spec.js | 32 +++- .../digitalForm/postProcessDigitalForm.js | 51 ++++- .../postProcessDigitalForm.unit.spec.js | 174 +++++++++++++++++- 3 files changed, 252 insertions(+), 5 deletions(-) diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js index d95a670227..bd504fb47e 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js @@ -16,7 +16,37 @@ describe('digitalForm', () => { describe('postProcess', () => { it('imports postProcessDigitalForm', () => { - expect(() => postProcess('test result')).to.not.throw(); + const queryResult = { + data: { + nodeQuery: { + entities: [ + { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }, + ], + }, + }, + }; + + expect(() => postProcess(queryResult)).to.not.throw(); }); }); }); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 71fabf2199..3541cb8a8b 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -1,3 +1,52 @@ -const postProcessDigitalForm = queryResult => queryResult; +const { logDrupal } = require('../../utilities-drupal'); + +const extractAdditionalFields = entity => { + const additionalFields = {}; + + if (entity.type.entity.entityId === 'digital_form_name_and_date_of_bi') { + additionalFields.includeDateOfBirth = entity.fieldIncludeDateOfBirth; + } + + return additionalFields; +}; +const extractForms = resultObject => resultObject?.data?.nodeQuery?.entities; + +const normalizeChapter = ({ entity }) => { + return { + id: parseInt(entity.entityId, 10), + chapterTitle: entity.fieldTitle, + type: entity.type.entity.entityId, + pageTitle: entity.type.entity.entityLabel, + additionalFields: extractAdditionalFields(entity), + }; +}; + +const normalizeForm = (form, logger = logDrupal) => { + try { + return { + cmsId: form.nid, + formId: form.fieldVaFormNumber, + title: form.entityLabel, + ombNumber: form.fieldOmbNumber, + chapters: form.fieldChapters.map(normalizeChapter), + }; + } catch (error) { + logger(`There was an error with this form: ${error}`); + return {}; + } +}; + +const postProcessDigitalForm = (queryResult, logger = logDrupal) => { + // queryResult was already parsed by graphQLApiClient + const forms = extractForms(queryResult); + + // will be turned into JSON by writeProcessedDataFilesToCache + if (forms) { + return forms.map(form => normalizeForm(form, logger)); + } + + logger(`Malformed result query: ${queryResult}`); + return []; +}; module.exports.postProcessDigitalForm = postProcessDigitalForm; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index d0be9f34fc..d693ef648b 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -1,12 +1,180 @@ /* eslint-disable @department-of-veterans-affairs/axe-check-required */ import { expect } from 'chai'; +import sinon from 'sinon'; const { postProcessDigitalForm } = require('./postProcessDigitalForm'); describe('postProcessDigitalForm', () => { - it('returns queryResult with no changes', () => { - const queryResult = { data: { form: {} } }; - expect(postProcessDigitalForm(queryResult)).to.eq(queryResult); + context('with a well-formed query result', () => { + const queryResult = { + data: { + nodeQuery: { + entities: [ + { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }, + { + nid: 71004, + entityLabel: 'Form with Two Steps', + fieldVaFormNumber: '222222', + fieldOmbNumber: '1212-1212', + fieldChapters: [ + { + entity: { + entityId: '157906', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'First Step', + fieldIncludeDateOfBirth: true, + }, + }, + { + entity: { + entityId: '157907', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'Second Step', + fieldIncludeDateOfBirth: false, + }, + }, + ], + }, + ], + }, + }, + }; + let processedResult; + + beforeEach(() => { + processedResult = postProcessDigitalForm(queryResult); + }); + + it('returns a normalized JSON object', () => { + const testForm = processedResult[1]; + const testChapter = testForm.chapters[1]; + + expect(processedResult.length).to.eq(2); + expect(testForm.cmsId).to.eq(71004); + expect(testForm.formId).to.eq('222222'); + expect(testForm.title).to.eq('Form with Two Steps'); + expect(testForm.ombNumber).to.eq('1212-1212'); + expect(testForm.chapters.length).to.eq(2); + expect(testChapter.id).to.eq(157907); + expect(testChapter.chapterTitle).to.eq('Second Step'); + expect(testChapter.type).to.eq('digital_form_name_and_date_of_bi'); + expect(testChapter.pageTitle).to.eq('Name and Date of Birth'); + expect(Object.keys(testChapter.additionalFields).length).to.eq(1); + }); + + context('with a Name and Date of Birth step', () => { + it('includes the appropriate fields', () => { + const { additionalFields } = processedResult[1].chapters[1]; + + expect(additionalFields.includeDateOfBirth).to.eq(false); + }); + }); + }); + + context('with a malformed query result', () => { + let queryResult; + let processedResult; + let logger; + + beforeEach(() => { + logger = sinon.spy(); + }); + + context('when the entire query is bad', () => { + beforeEach(() => { + queryResult = { + wrongKey: 'oops! bad data!', + }; + processedResult = postProcessDigitalForm(queryResult, logger); + }); + + it('logs the error', () => { + expect(logger.calledOnce).to.eq(true); + }); + + it('returns an empty array', () => { + expect(processedResult.length).to.eq(0); + }); + }); + + context('when only one form is malformed', () => { + beforeEach(() => { + queryResult = { + data: { + nodeQuery: { + entities: [ + { + nid: 71002, + entityLabel: 'Form with One Step', + fieldVaFormNumber: '11111', + fieldOmbNumber: '1111-1111', + fieldChapters: [ + { + entity: { + entityId: '157904', + type: { + entity: { + entityId: 'digital_form_name_and_date_of_bi', + entityLabel: 'Name and Date of Birth', + }, + }, + fieldTitle: 'The Only Step', + fieldIncludeDateOfBirth: true, + }, + }, + ], + }, + { + nid: '71004', + entityLabel: 'This form has problems', + fieldVaFormNumber: 222222, + fieldChapters: 'no chapters', + }, + ], + }, + }, + }; + processedResult = postProcessDigitalForm(queryResult, logger); + }); + + it('logs the error', () => { + expect(logger.calledOnce).to.eq(true); + }); + + it('returns the other forms', () => { + expect(processedResult[0].cmsId).to.eq(71002); + }); + }); }); }); From 0166a1223721c3ac84ca17219a3ad92b6ab8437a Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Fri, 4 Oct 2024 15:01:34 -0500 Subject: [PATCH 13/17] VATEAM-92265: Normalize Address Digital Form pattern output (#2301) Normalizes the Address Paragraph type. --- .../digitalForm/fragments/address.graphql.js | 14 +++++++++++ .../fragments/address.graphql.unit.spec.js | 13 ++++++++++ .../fragments/digitalForm.graphql.js | 3 +++ .../digitalForm.graphql.unit.spec.js | 5 ++++ .../digitalForm/postProcessDigitalForm.js | 18 ++++++++++---- .../postProcessDigitalForm.unit.spec.js | 24 +++++++++++++++++++ 6 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.js new file mode 100644 index 0000000000..dda0b68f6d --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.js @@ -0,0 +1,14 @@ +/* + * + * The "Address" Digital Form pattern. + * + * Pattern documentation: + * https://design.va.gov/patterns/ask-users-for/addresses + * + */ +module.exports = ` + fragment address on ParagraphDigitalFormAddress { + fieldTitle + fieldMilitaryAddressCheckbox + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js new file mode 100644 index 0000000000..2e877feff0 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js @@ -0,0 +1,13 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import address from './address.graphql'; + +describe('address fragment', () => { + it('includes fieldTitle', () => { + expect(address).to.have.string('fieldTitle'); + }); + it('includes fieldMilitaryAddressCheckbox', () => { + expect(address).to.have.string('fieldMilitaryAddressCheckbox'); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index 7c47c8c381..53aab02b62 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -1,3 +1,4 @@ +const address = require('./address.graphql'); const identificationInformation = require('./identificationInformation.graphql'); const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); @@ -7,6 +8,7 @@ const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); * */ module.exports = ` + ${address} ${identificationInformation} ${nameAndDateOfBirth} @@ -28,6 +30,7 @@ module.exports = ` entityLabel } } + ...address ...identificationInformation ...nameAndDateOfBirth } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js index 1002b7046c..32d398a17f 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js @@ -18,6 +18,11 @@ describe('digitalForm fragment', () => { }); describe('chapter fragments', () => { + it('imports the address fragment', () => { + expect(digitalForm).to.have.string('fragment address'); + expect(digitalForm).to.have.string('...address'); + }); + it('imports the identificationInformation fragment', () => { expect(digitalForm).to.have.string('fragment identificationInformation'); expect(digitalForm).to.have.string('...identificationInformation'); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index b010ed63d0..191610a464 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -4,10 +4,20 @@ const extractAdditionalFields = entity => { const additionalFields = {}; const { entityId } = entity.type.entity; - if (entityId === 'digital_form_name_and_date_of_bi') { - additionalFields.includeDateOfBirth = entity.fieldIncludeDateOfBirth; - } else if (entityId === 'digital_form_identification_info') { - additionalFields.includeServiceNumber = entity.fieldIncludeVeteranSService; + switch (entityId) { + case 'digital_form_address': + additionalFields.militaryAddressCheckbox = + entity.fieldMilitaryAddressCheckbox; + break; + case 'digital_form_name_and_date_of_bi': + additionalFields.includeDateOfBirth = entity.fieldIncludeDateOfBirth; + break; + case 'digital_form_identification_info': + additionalFields.includeServiceNumber = + entity.fieldIncludeVeteranSService; + break; + default: + break; } return additionalFields; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js index d734efe58c..a9b4f60abc 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js @@ -119,6 +119,30 @@ describe('postProcessDigitalForm', () => { }); }); + context('with an Address step', () => { + it('includes appropriate fields', () => { + twoStepEntity.fieldChapters.push({ + entity: { + entityId: '161344', + type: { + entity: { + entityId: 'digital_form_address', + entityLabel: 'Digital Form: Address', + }, + }, + fieldTitle: 'Generated Address', + fieldMilitaryAddressCheckbox: false, + }, + }); + const [, testForm] = postProcessDigitalForm(queryResult); + const [{ additionalFields }] = testForm.chapters.filter( + chapter => chapter.type === 'digital_form_address', + ); + + expect(additionalFields.militaryAddressCheckbox).to.eq(false); + }); + }); + context('with an Identification Information step', () => { let additionalFields; From 02d5d1256f20c0865f6da1d263bc6ed23d777699 Mon Sep 17 00:00:00 2001 From: Derek Houck Date: Wed, 9 Oct 2024 11:38:45 -0500 Subject: [PATCH 14/17] VATEAM-94290: Remove "Digital Form:" from content-build output (#2304) Strip the "Digital Form: " prefix out of our content-build output. Move all digital form tests to a tests directory and extract the test entities into fixture files. --- .../digitalForm/index.unit.spec.js | 52 ---- .../digitalForm/postProcessDigitalForm.js | 2 +- .../postProcessDigitalForm.unit.spec.js | 234 ------------------ .../tests/fixtures/queryResult.json | 97 ++++++++ .../fragments/address.graphql.unit.spec.js | 2 +- .../digitalForm.graphql.unit.spec.js | 2 +- ...tificationInformation.graphql.unit.spec.js | 2 +- .../nameAndDateOfBirth.graphql.unit.spec.js | 2 +- .../digitalForm/tests/index.unit.spec.js | 23 ++ .../tests/postProcessDigitalForm.unit.spec.js | 144 +++++++++++ 10 files changed, 269 insertions(+), 291 deletions(-) delete mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js delete mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json rename src/site/stages/build/drupal/static-data-files/digitalForm/{ => tests}/fragments/address.graphql.unit.spec.js (86%) rename src/site/stages/build/drupal/static-data-files/digitalForm/{ => tests}/fragments/digitalForm.graphql.unit.spec.js (95%) rename src/site/stages/build/drupal/static-data-files/digitalForm/{ => tests}/fragments/identificationInformation.graphql.unit.spec.js (82%) rename src/site/stages/build/drupal/static-data-files/digitalForm/{ => tests}/fragments/nameAndDateOfBirth.graphql.unit.spec.js (83%) create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/tests/index.unit.spec.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js deleted file mode 100644 index bd504fb47e..0000000000 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/index.unit.spec.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable @department-of-veterans-affairs/axe-check-required */ - -import { expect } from 'chai'; -import { query, postProcess } from './index'; - -describe('digitalForm', () => { - describe('query', () => { - it('returns digital_form entities', () => { - expect(query).to.have.string('digital_form'); - }); - it('imports the digitalForm fragment', () => { - expect(query).to.have.string('fragment digitalForm'); - expect(query).to.have.string('... digitalForm'); - }); - }); - - describe('postProcess', () => { - it('imports postProcessDigitalForm', () => { - const queryResult = { - data: { - nodeQuery: { - entities: [ - { - nid: 71002, - entityLabel: 'Form with One Step', - fieldVaFormNumber: '11111', - fieldOmbNumber: '1111-1111', - fieldChapters: [ - { - entity: { - entityId: '157904', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'The Only Step', - fieldIncludeDateOfBirth: true, - }, - }, - ], - }, - ], - }, - }, - }; - - expect(() => postProcess(queryResult)).to.not.throw(); - }); - }); -}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 191610a464..6dcb84fa3b 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -35,7 +35,7 @@ const normalizeChapter = ({ entity }) => { id: parseInt(entity.entityId, 10), chapterTitle: entity.fieldTitle, type: entity.type.entity.entityId, - pageTitle: entity.type.entity.entityLabel, + pageTitle: entity.type.entity.entityLabel.replace('Digital Form: ', ''), additionalFields: extractAdditionalFields(entity), }; }; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js deleted file mode 100644 index a9b4f60abc..0000000000 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.unit.spec.js +++ /dev/null @@ -1,234 +0,0 @@ -/* eslint-disable @department-of-veterans-affairs/axe-check-required */ - -import { expect } from 'chai'; -import sinon from 'sinon'; - -const { postProcessDigitalForm } = require('./postProcessDigitalForm'); - -describe('postProcessDigitalForm', () => { - const oneStepEntity = { - nid: 71002, - entityLabel: 'Form with One Step', - fieldVaFormNumber: '11111', - fieldOmbNumber: '1111-1111', - fieldRespondentBurden: 48, - fieldExpirationDate: { - value: '2025-06-11', - }, - fieldChapters: [ - { - entity: { - entityId: '157904', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'The Only Step', - fieldIncludeDateOfBirth: true, - }, - }, - ], - }; - - context('with a well-formed query result', () => { - const expDate = '2027-01-29'; - - const twoStepEntity = { - nid: 71004, - entityLabel: 'Form with Two Steps', - fieldVaFormNumber: '222222', - fieldOmbNumber: '1212-1212', - fieldRespondentBurden: 30, - fieldExpirationDate: { - value: expDate, - }, - fieldChapters: [ - { - entity: { - entityId: '157906', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'First Step', - fieldIncludeDateOfBirth: true, - }, - }, - { - entity: { - entityId: '157907', - type: { - entity: { - entityId: 'digital_form_name_and_date_of_bi', - entityLabel: 'Name and Date of Birth', - }, - }, - fieldTitle: 'Second Step', - fieldIncludeDateOfBirth: false, - }, - }, - ], - }; - - const queryResult = { - data: { - nodeQuery: { - entities: [oneStepEntity, twoStepEntity], - }, - }, - }; - - it('returns a normalized JSON object', () => { - const processedResult = postProcessDigitalForm(queryResult); - const [, testForm] = processedResult; - const testChapter = testForm.chapters[1]; - - expect(processedResult.length).to.eq(2); - expect(testForm.cmsId).to.eq(71004); - expect(testForm.formId).to.eq('222222'); - expect(testForm.title).to.eq('Form with Two Steps'); - expect(testForm.chapters.length).to.eq(2); - expect(testChapter.id).to.eq(157907); - expect(testChapter.chapterTitle).to.eq('Second Step'); - expect(testChapter.type).to.eq('digital_form_name_and_date_of_bi'); - expect(testChapter.pageTitle).to.eq('Name and Date of Birth'); - expect(Object.keys(testChapter.additionalFields).length).to.eq(1); - }); - - it('includes an OMB info object', () => { - const [, testForm] = postProcessDigitalForm(queryResult); - const { ombInfo } = testForm; - // expDate is 2027-01-29 - const formattedDate = '1/29/2027'; - - expect(ombInfo.ombNumber).to.eq(twoStepEntity.fieldOmbNumber); - expect(ombInfo.expDate).to.eq(formattedDate); - expect(ombInfo.resBurden).to.eq(twoStepEntity.fieldRespondentBurden); - }); - - context('with a Name and Date of Birth step', () => { - it('includes the appropriate fields', () => { - const [, testForm] = postProcessDigitalForm(queryResult); - const { additionalFields } = testForm.chapters[1]; - - expect(additionalFields.includeDateOfBirth).to.eq(false); - }); - }); - - context('with an Address step', () => { - it('includes appropriate fields', () => { - twoStepEntity.fieldChapters.push({ - entity: { - entityId: '161344', - type: { - entity: { - entityId: 'digital_form_address', - entityLabel: 'Digital Form: Address', - }, - }, - fieldTitle: 'Generated Address', - fieldMilitaryAddressCheckbox: false, - }, - }); - const [, testForm] = postProcessDigitalForm(queryResult); - const [{ additionalFields }] = testForm.chapters.filter( - chapter => chapter.type === 'digital_form_address', - ); - - expect(additionalFields.militaryAddressCheckbox).to.eq(false); - }); - }); - - context('with an Identification Information step', () => { - let additionalFields; - - beforeEach(() => { - twoStepEntity.fieldChapters.push({ - entity: { - entityId: '160594', - type: { - entity: { - entityId: 'digital_form_identification_info', - entityLabel: 'Identification Information', - }, - }, - fieldTitle: 'Identification information', - fieldIncludeVeteranSService: true, - }, - }); - const [, testForm] = postProcessDigitalForm(queryResult); - [{ additionalFields }] = testForm.chapters.filter( - chapter => chapter.type === 'digital_form_identification_info', - ); - }); - - it('includes appropriate fields', () => { - expect(additionalFields.includeServiceNumber).to.eq(true); - }); - - it('does not include inappropriate fields', () => { - expect(additionalFields.includeDateOfBirth).to.eq(undefined); - }); - }); - }); - - context('with a malformed query result', () => { - let queryResult; - let processedResult; - let logger; - - beforeEach(() => { - logger = sinon.spy(); - }); - - context('when the entire query is bad', () => { - beforeEach(() => { - queryResult = { - wrongKey: 'oops! bad data!', - }; - processedResult = postProcessDigitalForm(queryResult, logger); - }); - - it('logs the error', () => { - expect(logger.calledOnce).to.eq(true); - }); - - it('returns an empty array', () => { - expect(processedResult.length).to.eq(0); - }); - }); - - context('when only one form is malformed', () => { - beforeEach(() => { - queryResult = { - data: { - nodeQuery: { - entities: [ - oneStepEntity, - { - nid: '71004', - entityLabel: 'This form has problems', - fieldVaFormNumber: 222222, - fieldChapters: 'no chapters', - }, - ], - }, - }, - }; - processedResult = postProcessDigitalForm(queryResult, logger); - }); - - it('logs the error', () => { - expect(logger.calledOnce).to.eq(true); - }); - - it('returns the other forms', () => { - expect(processedResult[0].cmsId).to.eq(71002); - }); - }); - }); -}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json new file mode 100644 index 0000000000..2d68902311 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json @@ -0,0 +1,97 @@ +{ + "data": { + "nodeQuery": { + "entities": [ + { + "nid": 71002, + "entityLabel": "Form with One Step", + "fieldVaFormNumber": "11111", + "fieldOmbNumber": "1111-1111", + "fieldRespondentBurden": 48, + "fieldExpirationDate": { + "value": "2025-06-11" + }, + "fieldChapters": [ + { + "entity": { + "entityId": "157904", + "type": { + "entity": { + "entityId": "digital_form_name_and_date_of_bi", + "entityLabel": "Digital Form: Name and Date of Birth" + } + }, + "fieldTitle": "The Only Step", + "fieldIncludeDateOfBirth": true + } + } + ] + }, + { + "nid": 71004, + "entityLabel": "Form with Two Steps", + "fieldVaFormNumber": "222222", + "fieldOmbNumber": "1212-1212", + "fieldRespondentBurden": 30, + "fieldExpirationDate": { + "value": "2027-01-29" + }, + "fieldChapters": [ + { + "entity": { + "entityId": "157906", + "type": { + "entity": { + "entityId": "digital_form_name_and_date_of_bi", + "entityLabel": "Digital Form: Name and Date of Birth" + } + }, + "fieldTitle": "First Step", + "fieldIncludeDateOfBirth": true + } + }, + { + "entity": { + "entityId": "157907", + "type": { + "entity": { + "entityId": "digital_form_name_and_date_of_bi", + "entityLabel": "Digital Form: Name and Date of Birth" + } + }, + "fieldTitle": "Second Step", + "fieldIncludeDateOfBirth": false + } + }, + { + "entity": { + "entityId": "161344", + "type": { + "entity": { + "entityId": "digital_form_address", + "entityLabel": "Digital Form: Address" + } + }, + "fieldTitle": "Generated Address", + "fieldMilitaryAddressCheckbox": false + } + }, + { + "entity": { + "entityId": "160594", + "type": { + "entity": { + "entityId": "digital_form_identification_info", + "entityLabel": "Digital Form: Identification Information" + } + }, + "fieldTitle": "Identification information", + "fieldIncludeVeteranSService": true + } + } + ] + } + ] + } + } +} diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/address.graphql.unit.spec.js similarity index 86% rename from src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js rename to src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/address.graphql.unit.spec.js index 2e877feff0..8acd9bf18f 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/address.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/address.graphql.unit.spec.js @@ -1,7 +1,7 @@ /* eslint-disable @department-of-veterans-affairs/axe-check-required */ import { expect } from 'chai'; -import address from './address.graphql'; +import address from '../../fragments/address.graphql'; describe('address fragment', () => { it('includes fieldTitle', () => { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js similarity index 95% rename from src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js rename to src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js index 32d398a17f..efd8fe9eef 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js @@ -1,7 +1,7 @@ /* eslint-disable @department-of-veterans-affairs/axe-check-required */ import { expect } from 'chai'; -import digitalForm from './digitalForm.graphql'; +import digitalForm from '../../fragments/digitalForm.graphql'; describe('digitalForm fragment', () => { it('includes form fields', () => { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/identificationInformation.graphql.unit.spec.js similarity index 82% rename from src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js rename to src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/identificationInformation.graphql.unit.spec.js index 3935815a3f..4806461c69 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/identificationInformation.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/identificationInformation.graphql.unit.spec.js @@ -1,7 +1,7 @@ /* eslint-disable @department-of-veterans-affairs/axe-check-required */ import { expect } from 'chai'; -import identificationInformation from './identificationInformation.graphql'; +import identificationInformation from '../../fragments/identificationInformation.graphql'; describe('identificationInformation fragment', () => { it('includes fieldTitle', () => { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/nameAndDateOfBirth.graphql.unit.spec.js similarity index 83% rename from src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js rename to src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/nameAndDateOfBirth.graphql.unit.spec.js index d2cf16bd17..a95de7b171 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/nameAndDateOfBirth.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/nameAndDateOfBirth.graphql.unit.spec.js @@ -1,7 +1,7 @@ /* eslint-disable @department-of-veterans-affairs/axe-check-required */ import { expect } from 'chai'; -import nameAndDateOfBirth from './nameAndDateOfBirth.graphql'; +import nameAndDateOfBirth from '../../fragments/nameAndDateOfBirth.graphql'; describe('nameAndDateOfBirth fragment', () => { it('includes fieldTitle', () => { diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/index.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/index.unit.spec.js new file mode 100644 index 0000000000..c38bedf07e --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/index.unit.spec.js @@ -0,0 +1,23 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import { query, postProcess } from '../index'; +import queryResult from './fixtures/queryResult.json'; + +describe('digitalForm', () => { + describe('query', () => { + it('returns digital_form entities', () => { + expect(query).to.have.string('digital_form'); + }); + it('imports the digitalForm fragment', () => { + expect(query).to.have.string('fragment digitalForm'); + expect(query).to.have.string('... digitalForm'); + }); + }); + + describe('postProcess', () => { + it('imports postProcessDigitalForm', () => { + expect(() => postProcess(queryResult)).to.not.throw(); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js new file mode 100644 index 0000000000..ac0a5db722 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js @@ -0,0 +1,144 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import sinon from 'sinon'; +import queryResult from './fixtures/queryResult.json'; + +const { postProcessDigitalForm } = require('../postProcessDigitalForm'); + +describe('postProcessDigitalForm', () => { + const [oneStepEntity, twoStepEntity] = queryResult.data.nodeQuery.entities; + + context('with a well-formed query result', () => { + let testForm; + + beforeEach(() => { + [, testForm] = postProcessDigitalForm(queryResult); + }); + + it('returns a normalized JSON object', () => { + const testChapter = testForm.chapters[1]; + + expect(testForm.cmsId).to.eq(71004); + expect(testForm.formId).to.eq('222222'); + expect(testForm.title).to.eq('Form with Two Steps'); + expect(testForm.chapters.length).to.eq( + twoStepEntity.fieldChapters.length, + ); + expect(testChapter.id).to.eq(157907); + expect(testChapter.chapterTitle).to.eq('Second Step'); + expect(testChapter.type).to.eq('digital_form_name_and_date_of_bi'); + expect(Object.keys(testChapter.additionalFields).length).to.eq(1); + }); + + it('includes an OMB info object', () => { + const { ombInfo } = testForm; + // towStepEntity.fieldExpirationDate is 2027-01-29 + const formattedDate = '1/29/2027'; + + expect(ombInfo.ombNumber).to.eq(twoStepEntity.fieldOmbNumber); + expect(ombInfo.expDate).to.eq(formattedDate); + expect(ombInfo.resBurden).to.eq(twoStepEntity.fieldRespondentBurden); + }); + + it('removes the "Digital Form" prefix', () => { + const [, testChapter] = testForm.chapters; + + expect(testChapter.pageTitle).to.eq('Name and Date of Birth'); + }); + + describe('additionalFields', () => { + let additionalFields; + + context('with a Name and Date of Birth step', () => { + it('includes the appropriate fields', () => { + additionalFields = testForm.chapters[1].additionalFields; + + expect(additionalFields.includeDateOfBirth).to.eq(false); + }); + }); + + context('with an Address step', () => { + it('includes appropriate fields', () => { + [{ additionalFields }] = testForm.chapters.filter( + chapter => chapter.type === 'digital_form_address', + ); + + expect(additionalFields.militaryAddressCheckbox).to.eq(false); + }); + }); + + context('with an Identification Information step', () => { + beforeEach(() => { + [{ additionalFields }] = testForm.chapters.filter( + chapter => chapter.type === 'digital_form_identification_info', + ); + }); + + it('includes appropriate fields', () => { + expect(additionalFields.includeServiceNumber).to.eq(true); + }); + + it('does not include inappropriate fields', () => { + expect(additionalFields.includeDateOfBirth).to.eq(undefined); + }); + }); + }); + }); + + context('with a malformed query result', () => { + let badQueryResult; + let processedResult; + let logger; + + beforeEach(() => { + logger = sinon.spy(); + }); + + context('when the entire query is bad', () => { + beforeEach(() => { + badQueryResult = { + wrongKey: 'oops! bad data!', + }; + processedResult = postProcessDigitalForm(badQueryResult, logger); + }); + + it('logs the error', () => { + expect(logger.calledOnce).to.eq(true); + }); + + it('returns an empty array', () => { + expect(processedResult.length).to.eq(0); + }); + }); + + context('when only one form is malformed', () => { + beforeEach(() => { + badQueryResult = { + data: { + nodeQuery: { + entities: [ + oneStepEntity, + { + nid: '71004', + entityLabel: 'This form has problems', + fieldVaFormNumber: 222222, + fieldChapters: 'no chapters', + }, + ], + }, + }, + }; + processedResult = postProcessDigitalForm(badQueryResult, logger); + }); + + it('logs the error', () => { + expect(logger.calledOnce).to.eq(true); + }); + + it('returns the other forms', () => { + expect(processedResult[0].cmsId).to.eq(71002); + }); + }); + }); +}); From a0310be18f74a0b4f84c9349401296b42251369b Mon Sep 17 00:00:00 2001 From: Derek Houck <12766168+derekhouck@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:59:34 -0500 Subject: [PATCH 15/17] VATEAM-93401: Normalize Phone and Email Digital Form pattern output (#2308) Normalizes the Phone and Email Address Paragraph type. --- .../fragments/digitalForm.graphql.js | 3 + .../fragments/phoneAndEmail.graphql.js | 14 +++++ .../digitalForm/postProcessDigitalForm.js | 28 ++++----- .../tests/fixtures/queryResult.json | 15 ++++- .../digitalForm.graphql.unit.spec.js | 23 ++++---- .../phoneAndEmail.graphql.unit.spec.js | 14 +++++ .../tests/postProcessDigitalForm.unit.spec.js | 57 +++++++------------ 7 files changed, 89 insertions(+), 65 deletions(-) create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/phoneAndEmail.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/phoneAndEmail.graphql.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index 53aab02b62..48095fc129 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -1,6 +1,7 @@ const address = require('./address.graphql'); const identificationInformation = require('./identificationInformation.graphql'); const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); +const phoneAndEmail = require('./phoneAndEmail.graphql'); /* * @@ -11,6 +12,7 @@ module.exports = ` ${address} ${identificationInformation} ${nameAndDateOfBirth} + ${phoneAndEmail} fragment digitalForm on NodeDigitalForm { nid @@ -33,6 +35,7 @@ module.exports = ` ...address ...identificationInformation ...nameAndDateOfBirth + ...phoneAndEmail } } } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/phoneAndEmail.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/phoneAndEmail.graphql.js new file mode 100644 index 0000000000..d47cdb2dab --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/phoneAndEmail.graphql.js @@ -0,0 +1,14 @@ +/* + * + * The "Phone and Email Address" Digital Form pattern. + * + * Pattern documentation: + * https://design.va.gov/patterns/ask-users-for/phone-numbers + * + */ +module.exports = ` +fragment phoneAndEmail on ParagraphDigitalFormPhoneAndEmail { + fieldTitle + fieldIncludeEmail +} +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 6dcb84fa3b..116145d7ad 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -1,26 +1,28 @@ const { logDrupal } = require('../../utilities-drupal'); const extractAdditionalFields = entity => { - const additionalFields = {}; const { entityId } = entity.type.entity; switch (entityId) { case 'digital_form_address': - additionalFields.militaryAddressCheckbox = - entity.fieldMilitaryAddressCheckbox; - break; - case 'digital_form_name_and_date_of_bi': - additionalFields.includeDateOfBirth = entity.fieldIncludeDateOfBirth; - break; + return { + militaryAddressCheckbox: entity.fieldMilitaryAddressCheckbox, + }; case 'digital_form_identification_info': - additionalFields.includeServiceNumber = - entity.fieldIncludeVeteranSService; - break; + return { + includeServiceNumber: entity.fieldIncludeVeteranSService, + }; + case 'digital_form_name_and_date_of_bi': + return { + includeDateOfBirth: entity.fieldIncludeDateOfBirth, + }; + case 'digital_form_phone_and_email': + return { + includeEmail: entity.fieldIncludeEmail, + }; default: - break; + return {}; } - - return additionalFields; }; const extractForms = resultObject => resultObject?.data?.nodeQuery?.entities; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json index 2d68902311..13db840918 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json @@ -29,7 +29,7 @@ }, { "nid": 71004, - "entityLabel": "Form with Two Steps", + "entityLabel": "Form with Many Steps", "fieldVaFormNumber": "222222", "fieldOmbNumber": "1212-1212", "fieldRespondentBurden": 30, @@ -88,6 +88,19 @@ "fieldTitle": "Identification information", "fieldIncludeVeteranSService": true } + }, + { + "entity": { + "entityId": "161351", + "type": { + "entity": { + "entityId": "digital_form_phone_and_email", + "entityLabel": "Digital Form: Phone and email address" + } + }, + "fieldTitle": "Generated Phone", + "fieldIncludeEmail": false + } } ] } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js index efd8fe9eef..9b1e86186a 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js @@ -18,19 +18,16 @@ describe('digitalForm fragment', () => { }); describe('chapter fragments', () => { - it('imports the address fragment', () => { - expect(digitalForm).to.have.string('fragment address'); - expect(digitalForm).to.have.string('...address'); - }); - - it('imports the identificationInformation fragment', () => { - expect(digitalForm).to.have.string('fragment identificationInformation'); - expect(digitalForm).to.have.string('...identificationInformation'); - }); - - it('imports the nameAndDateOfBirth fragment', () => { - expect(digitalForm).to.have.string('fragment nameAndDateOfBirth'); - expect(digitalForm).to.have.string('...nameAndDateOfBirth'); + [ + 'address', + 'identificationInformation', + 'nameAndDateOfBirth', + 'phoneAndEmail', + ].forEach(fragment => { + it(`imports the ${fragment} fragment`, () => { + expect(digitalForm).to.have.string(`fragment ${fragment}`); + expect(digitalForm).to.have.string(`...${fragment}`); + }); }); }); }); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/phoneAndEmail.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/phoneAndEmail.graphql.unit.spec.js new file mode 100644 index 0000000000..b8649ef9cd --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/phoneAndEmail.graphql.unit.spec.js @@ -0,0 +1,14 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import phoneAndEmail from '../../fragments/phoneAndEmail.graphql'; + +describe('phoneAndEmail fragment', () => { + it('includes fieldTitle', () => { + expect(phoneAndEmail).to.have.string('fieldTitle'); + }); + + it('includes fieldIncludeEmail', () => { + expect(phoneAndEmail).to.have.string('fieldIncludeEmail'); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js index ac0a5db722..1427dbc6fe 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js @@ -7,7 +7,7 @@ import queryResult from './fixtures/queryResult.json'; const { postProcessDigitalForm } = require('../postProcessDigitalForm'); describe('postProcessDigitalForm', () => { - const [oneStepEntity, twoStepEntity] = queryResult.data.nodeQuery.entities; + const [oneStepEntity, manyStepEntity] = queryResult.data.nodeQuery.entities; context('with a well-formed query result', () => { let testForm; @@ -21,9 +21,9 @@ describe('postProcessDigitalForm', () => { expect(testForm.cmsId).to.eq(71004); expect(testForm.formId).to.eq('222222'); - expect(testForm.title).to.eq('Form with Two Steps'); + expect(testForm.title).to.eq(manyStepEntity.entityLabel); expect(testForm.chapters.length).to.eq( - twoStepEntity.fieldChapters.length, + manyStepEntity.fieldChapters.length, ); expect(testChapter.id).to.eq(157907); expect(testChapter.chapterTitle).to.eq('Second Step'); @@ -36,9 +36,9 @@ describe('postProcessDigitalForm', () => { // towStepEntity.fieldExpirationDate is 2027-01-29 const formattedDate = '1/29/2027'; - expect(ombInfo.ombNumber).to.eq(twoStepEntity.fieldOmbNumber); + expect(ombInfo.ombNumber).to.eq(manyStepEntity.fieldOmbNumber); expect(ombInfo.expDate).to.eq(formattedDate); - expect(ombInfo.resBurden).to.eq(twoStepEntity.fieldRespondentBurden); + expect(ombInfo.resBurden).to.eq(manyStepEntity.fieldRespondentBurden); }); it('removes the "Digital Form" prefix', () => { @@ -48,39 +48,20 @@ describe('postProcessDigitalForm', () => { }); describe('additionalFields', () => { - let additionalFields; - - context('with a Name and Date of Birth step', () => { - it('includes the appropriate fields', () => { - additionalFields = testForm.chapters[1].additionalFields; - - expect(additionalFields.includeDateOfBirth).to.eq(false); - }); - }); - - context('with an Address step', () => { - it('includes appropriate fields', () => { - [{ additionalFields }] = testForm.chapters.filter( - chapter => chapter.type === 'digital_form_address', - ); - - expect(additionalFields.militaryAddressCheckbox).to.eq(false); - }); - }); - - context('with an Identification Information step', () => { - beforeEach(() => { - [{ additionalFields }] = testForm.chapters.filter( - chapter => chapter.type === 'digital_form_identification_info', - ); - }); - - it('includes appropriate fields', () => { - expect(additionalFields.includeServiceNumber).to.eq(true); - }); - - it('does not include inappropriate fields', () => { - expect(additionalFields.includeDateOfBirth).to.eq(undefined); + [ + ['digital_form_address', 'militaryAddressCheckbox', false], + ['digital_form_identification_info', 'includeServiceNumber', true], + ['digital_form_name_and_date_of_bi', 'includeDateOfBirth', true], + ['digital_form_phone_and_email', 'includeEmail', false], + ].forEach(([type, additionalField, value]) => { + context(`with a ${type} step`, () => { + it('includes the appropriate additional fields', () => { + const { additionalFields } = testForm.chapters.find( + chapter => chapter.type === type, + ); + + expect(additionalFields[additionalField]).to.eq(value); + }); }); }); }); From 00433c418f7122b0b9b3dd6f5d0651a4cfea8614 Mon Sep 17 00:00:00 2001 From: Derek Houck <12766168+derekhouck@users.noreply.github.com> Date: Mon, 4 Nov 2024 10:18:58 -0600 Subject: [PATCH 16/17] VATEAM-94709: Normalize Your Personal Information chapter (#2338) Normalizes the "Your personal information" Paragraph type. --- .../fragments/digitalForm.graphql.js | 9 +-- .../yourPersonalInformation.graphql.js | 28 +++++++++ .../digitalForm/postProcessDigitalForm.js | 45 ++++++++++---- .../tests/fixtures/queryResult.json | 60 +++++++++---------- .../digitalForm.graphql.unit.spec.js | 19 +++--- ...urPersonalInformation.graphql.unit.spec.js | 13 ++++ .../tests/postProcessDigitalForm.unit.spec.js | 46 ++++++++++++-- 7 files changed, 152 insertions(+), 68 deletions(-) create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/yourPersonalInformation.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/yourPersonalInformation.graphql.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index 48095fc129..9d5e0a3295 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -1,7 +1,6 @@ const address = require('./address.graphql'); -const identificationInformation = require('./identificationInformation.graphql'); -const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); const phoneAndEmail = require('./phoneAndEmail.graphql'); +const yourPersonalInformation = require('./yourPersonalInformation.graphql'); /* * @@ -10,9 +9,8 @@ const phoneAndEmail = require('./phoneAndEmail.graphql'); */ module.exports = ` ${address} - ${identificationInformation} - ${nameAndDateOfBirth} ${phoneAndEmail} + ${yourPersonalInformation} fragment digitalForm on NodeDigitalForm { nid @@ -33,9 +31,8 @@ module.exports = ` } } ...address - ...identificationInformation - ...nameAndDateOfBirth ...phoneAndEmail + ...yourPersonalInformation } } } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/yourPersonalInformation.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/yourPersonalInformation.graphql.js new file mode 100644 index 0000000000..a1785fcc87 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/yourPersonalInformation.graphql.js @@ -0,0 +1,28 @@ +const identificationInformation = require('./identificationInformation.graphql'); +const nameAndDateOfBirth = require('./nameAndDateOfBirth.graphql'); + +/* + * + * The "Your personal information" Digital Form pattern. + * + * Pattern documentation: + * https://github.com/department-of-veterans-affairs/vets-website/blob/0ae48c0b017a37d84f6ae425c67c332f4c67fb8b/src/applications/simple-forms/mock-simple-forms-patterns-v3/config/form.js#L40 + * + */ +module.exports = ` + ${identificationInformation} + ${nameAndDateOfBirth} + + fragment yourPersonalInformation on ParagraphDigitalFormYourPersonalInfo { + fieldNameAndDateOfBirth { + entity { + ...nameAndDateOfBirth + } + } + fieldIdentificationInformation { + entity { + ...identificationInformation + } + } + } +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 116145d7ad..51f5b9c202 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -8,14 +8,6 @@ const extractAdditionalFields = entity => { return { militaryAddressCheckbox: entity.fieldMilitaryAddressCheckbox, }; - case 'digital_form_identification_info': - return { - includeServiceNumber: entity.fieldIncludeVeteranSService, - }; - case 'digital_form_name_and_date_of_bi': - return { - includeDateOfBirth: entity.fieldIncludeDateOfBirth, - }; case 'digital_form_phone_and_email': return { includeEmail: entity.fieldIncludeEmail, @@ -32,13 +24,42 @@ const formatDate = dateString => { return `${removeLeadingZero(month)}/${removeLeadingZero(day)}/${year}`; }; +const stripPrefix = label => label.replace('Digital Form: ', ''); + const normalizeChapter = ({ entity }) => { - return { + const type = entity.type.entity.entityId; + const initialChapter = { id: parseInt(entity.entityId, 10), - chapterTitle: entity.fieldTitle, - type: entity.type.entity.entityId, - pageTitle: entity.type.entity.entityLabel.replace('Digital Form: ', ''), + type, + }; + + if (type === 'digital_form_your_personal_info') { + const identificationInformation = + entity.fieldIdentificationInformation.entity; + const nameAndDateOfBirth = entity.fieldNameAndDateOfBirth.entity; + + return { + ...initialChapter, + chapterTitle: stripPrefix(entity.type.entity.entityLabel), + pages: [ + { + pageTitle: nameAndDateOfBirth.fieldTitle, + includeDateOfBirth: nameAndDateOfBirth.fieldIncludeDateOfBirth, + }, + { + pageTitle: identificationInformation.fieldTitle, + includeServiceNumber: + identificationInformation.fieldIncludeVeteranSService, + }, + ], + }; + } + + return { + ...initialChapter, additionalFields: extractAdditionalFields(entity), + chapterTitle: entity.fieldTitle, + pageTitle: stripPrefix(entity.type.entity.entityLabel), }; }; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json index 13db840918..380b9cd1c5 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json @@ -14,15 +14,25 @@ "fieldChapters": [ { "entity": { - "entityId": "157904", + "entityId": "162008", "type": { "entity": { - "entityId": "digital_form_name_and_date_of_bi", - "entityLabel": "Digital Form: Name and Date of Birth" + "entityId": "digital_form_your_personal_info", + "entityLabel": "Digital Form: Your personal information" } }, - "fieldTitle": "The Only Step", - "fieldIncludeDateOfBirth": true + "fieldNameAndDateOfBirth": { + "entity": { + "fieldTitle": "Name", + "fieldIncludeDateOfBirth": true + } + }, + "fieldIdentificationInformation": { + "entity": { + "fieldTitle": "Identification information", + "fieldIncludeVeteranSService": false + } + } } } ] @@ -39,28 +49,25 @@ "fieldChapters": [ { "entity": { - "entityId": "157906", + "entityId": "162008", "type": { "entity": { - "entityId": "digital_form_name_and_date_of_bi", - "entityLabel": "Digital Form: Name and Date of Birth" + "entityId": "digital_form_your_personal_info", + "entityLabel": "Digital Form: Your personal information" } }, - "fieldTitle": "First Step", - "fieldIncludeDateOfBirth": true - } - }, - { - "entity": { - "entityId": "157907", - "type": { + "fieldNameAndDateOfBirth": { "entity": { - "entityId": "digital_form_name_and_date_of_bi", - "entityLabel": "Digital Form: Name and Date of Birth" + "fieldTitle": "Name and Date of Birth", + "fieldIncludeDateOfBirth": true } }, - "fieldTitle": "Second Step", - "fieldIncludeDateOfBirth": false + "fieldIdentificationInformation": { + "entity": { + "fieldTitle": "Identification information", + "fieldIncludeVeteranSService": false + } + } } }, { @@ -76,19 +83,6 @@ "fieldMilitaryAddressCheckbox": false } }, - { - "entity": { - "entityId": "160594", - "type": { - "entity": { - "entityId": "digital_form_identification_info", - "entityLabel": "Digital Form: Identification Information" - } - }, - "fieldTitle": "Identification information", - "fieldIncludeVeteranSService": true - } - }, { "entity": { "entityId": "161351", diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js index 9b1e86186a..78c19930df 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js @@ -18,16 +18,13 @@ describe('digitalForm fragment', () => { }); describe('chapter fragments', () => { - [ - 'address', - 'identificationInformation', - 'nameAndDateOfBirth', - 'phoneAndEmail', - ].forEach(fragment => { - it(`imports the ${fragment} fragment`, () => { - expect(digitalForm).to.have.string(`fragment ${fragment}`); - expect(digitalForm).to.have.string(`...${fragment}`); - }); - }); + ['address', 'phoneAndEmail', 'yourPersonalInformation'].forEach( + fragment => { + it(`imports the ${fragment} fragment`, () => { + expect(digitalForm).to.have.string(`fragment ${fragment}`); + expect(digitalForm).to.have.string(`...${fragment}`); + }); + }, + ); }); }); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/yourPersonalInformation.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/yourPersonalInformation.graphql.unit.spec.js new file mode 100644 index 0000000000..427c302077 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/yourPersonalInformation.graphql.unit.spec.js @@ -0,0 +1,13 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import yourPersonalInformation from '../../fragments/yourPersonalInformation.graphql'; + +describe('yourPersonalInformation fragment', () => { + ['identificationInformation', 'nameAndDateOfBirth'].forEach(fragment => { + it(`imports the ${fragment} fragment`, () => { + expect(yourPersonalInformation).to.have.string(`fragment ${fragment}`); + expect(yourPersonalInformation).to.have.string(`...${fragment}`); + }); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js index 1427dbc6fe..8db4c649aa 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js @@ -17,6 +17,7 @@ describe('postProcessDigitalForm', () => { }); it('returns a normalized JSON object', () => { + const queryChapter = manyStepEntity.fieldChapters[1].entity; const testChapter = testForm.chapters[1]; expect(testForm.cmsId).to.eq(71004); @@ -25,9 +26,9 @@ describe('postProcessDigitalForm', () => { expect(testForm.chapters.length).to.eq( manyStepEntity.fieldChapters.length, ); - expect(testChapter.id).to.eq(157907); - expect(testChapter.chapterTitle).to.eq('Second Step'); - expect(testChapter.type).to.eq('digital_form_name_and_date_of_bi'); + expect(testChapter.id).to.eq(Number(queryChapter.entityId)); + expect(testChapter.chapterTitle).to.eq(queryChapter.fieldTitle); + expect(testChapter.type).to.eq(queryChapter.type.entity.entityId); expect(Object.keys(testChapter.additionalFields).length).to.eq(1); }); @@ -44,14 +45,12 @@ describe('postProcessDigitalForm', () => { it('removes the "Digital Form" prefix', () => { const [, testChapter] = testForm.chapters; - expect(testChapter.pageTitle).to.eq('Name and Date of Birth'); + expect(testChapter.pageTitle).to.eq('Address'); }); describe('additionalFields', () => { [ ['digital_form_address', 'militaryAddressCheckbox', false], - ['digital_form_identification_info', 'includeServiceNumber', true], - ['digital_form_name_and_date_of_bi', 'includeDateOfBirth', true], ['digital_form_phone_and_email', 'includeEmail', false], ].forEach(([type, additionalField, value]) => { context(`with a ${type} step`, () => { @@ -65,6 +64,41 @@ describe('postProcessDigitalForm', () => { }); }); }); + + describe('Your personal information', () => { + let ypiChapter; + const queryYpi = manyStepEntity.fieldChapters[0].entity; + + beforeEach(() => { + ypiChapter = testForm.chapters.find( + chapter => chapter.type === 'digital_form_your_personal_info', + ); + }); + + it('includes the correct chapter title', () => { + expect(ypiChapter.chapterTitle).to.eq('Your personal information'); + }); + + it('includes a Name and Date of Birth page', () => { + const nameAndDateOfBirth = ypiChapter.pages[0]; + const queryNdob = queryYpi.fieldNameAndDateOfBirth.entity; + + expect(nameAndDateOfBirth.pageTitle).to.eq(queryNdob.fieldTitle); + expect(nameAndDateOfBirth.includeDateOfBirth).to.eq( + queryNdob.fieldIncludeDateOfBirth, + ); + }); + + it('includes an Identification information page', () => { + const identificationInformation = ypiChapter.pages[1]; + const queryIi = queryYpi.fieldIdentificationInformation.entity; + + expect(identificationInformation.pageTitle).to.eq(queryIi.fieldTitle); + expect(identificationInformation.includeServiceNumber).to.eq( + queryIi.fieldIncludeVeteranSService, + ); + }); + }); }); context('with a malformed query result', () => { From 56aee27580cfc85f5222079f418e5af328db28cb Mon Sep 17 00:00:00 2001 From: Derek Houck <12766168+derekhouck@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:46:01 -0600 Subject: [PATCH 17/17] VATEAM-93614: Normalize List and Loop pattern output (#2350) Normalizes the List & Loop Paragraph type. --- .../digitalForm/fragments/digitalForm.graphql.js | 3 +++ .../digitalForm/fragments/listLoop.graphql.js | 14 ++++++++++++++ .../digitalForm/postProcessDigitalForm.js | 4 ++++ .../digitalForm/tests/fixtures/queryResult.json | 13 +++++++++++++ .../fragments/digitalForm.graphql.unit.spec.js | 2 +- .../tests/fragments/listLoop.graphql.unit.spec.js | 14 ++++++++++++++ .../tests/postProcessDigitalForm.unit.spec.js | 1 + 7 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/fragments/listLoop.graphql.js create mode 100644 src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/listLoop.graphql.unit.spec.js diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js index 9d5e0a3295..f7710f1b18 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/digitalForm.graphql.js @@ -1,6 +1,7 @@ const address = require('./address.graphql'); const phoneAndEmail = require('./phoneAndEmail.graphql'); const yourPersonalInformation = require('./yourPersonalInformation.graphql'); +const listLoop = require('./listLoop.graphql'); /* * @@ -9,6 +10,7 @@ const yourPersonalInformation = require('./yourPersonalInformation.graphql'); */ module.exports = ` ${address} + ${listLoop} ${phoneAndEmail} ${yourPersonalInformation} @@ -31,6 +33,7 @@ module.exports = ` } } ...address + ...listLoop ...phoneAndEmail ...yourPersonalInformation } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/listLoop.graphql.js b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/listLoop.graphql.js new file mode 100644 index 0000000000..5e468b8aed --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/fragments/listLoop.graphql.js @@ -0,0 +1,14 @@ +/* + * + * The "List & Loop" Digital Form pattern. + * + * Pattern documentation: + * https://design.va.gov/patterns/ask-users-for/multiple-responses + * + */ +module.exports = ` +fragment listLoop on ParagraphDigitalFormListLoop { + fieldTitle + fieldOptional +} +`; diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js index 51f5b9c202..65758289fb 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/postProcessDigitalForm.js @@ -8,6 +8,10 @@ const extractAdditionalFields = entity => { return { militaryAddressCheckbox: entity.fieldMilitaryAddressCheckbox, }; + case 'digital_form_list_loop': + return { + optional: entity.fieldOptional, + }; case 'digital_form_phone_and_email': return { includeEmail: entity.fieldIncludeEmail, diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json index 380b9cd1c5..04172964aa 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fixtures/queryResult.json @@ -95,6 +95,19 @@ "fieldTitle": "Generated Phone", "fieldIncludeEmail": false } + }, + { + "entity": { + "entityId": "162026", + "type": { + "entity": { + "entityId": "digital_form_list_loop", + "entityLabel": "Digital Form: List & Loop" + } + }, + "fieldTitle": "Generated List & Loop", + "fieldOptional": false + } } ] } diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js index 78c19930df..deb370785c 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/digitalForm.graphql.unit.spec.js @@ -18,7 +18,7 @@ describe('digitalForm fragment', () => { }); describe('chapter fragments', () => { - ['address', 'phoneAndEmail', 'yourPersonalInformation'].forEach( + ['address', 'listLoop', 'phoneAndEmail', 'yourPersonalInformation'].forEach( fragment => { it(`imports the ${fragment} fragment`, () => { expect(digitalForm).to.have.string(`fragment ${fragment}`); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/listLoop.graphql.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/listLoop.graphql.unit.spec.js new file mode 100644 index 0000000000..aec33c7af2 --- /dev/null +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/fragments/listLoop.graphql.unit.spec.js @@ -0,0 +1,14 @@ +/* eslint-disable @department-of-veterans-affairs/axe-check-required */ + +import { expect } from 'chai'; +import listLoop from '../../fragments/listLoop.graphql'; + +describe('listLoop fragment', () => { + it('includes fieldTitle', () => { + expect(listLoop).to.have.string('fieldTitle'); + }); + + it('includes fieldOptional', () => { + expect(listLoop).to.have.string('fieldOptional'); + }); +}); diff --git a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js index 8db4c649aa..f353b98605 100644 --- a/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js +++ b/src/site/stages/build/drupal/static-data-files/digitalForm/tests/postProcessDigitalForm.unit.spec.js @@ -51,6 +51,7 @@ describe('postProcessDigitalForm', () => { describe('additionalFields', () => { [ ['digital_form_address', 'militaryAddressCheckbox', false], + ['digital_form_list_loop', 'optional', false], ['digital_form_phone_and_email', 'includeEmail', false], ].forEach(([type, additionalField, value]) => { context(`with a ${type} step`, () => {