From a27c6f532535353f0cc4359dcb958a27971c301c Mon Sep 17 00:00:00 2001
From: Chris Kim <42885441+chriskim2311@users.noreply.github.com>
Date: Thu, 11 Apr 2024 11:40:02 -0700
Subject: [PATCH] VACMS-16913: DUW questions 3 (#29030)
---
.../discharge-wizard/actions/index.js | 38 +++++++-
.../components/DischargeWizardApp.jsx | 3 +-
.../components/v2/BreadcrumbsV2.jsx | 22 +++++
.../components/v2/Homepage.jsx | 1 +
.../components/v2/questions/CourtMartial.jsx | 79 +++++++++++++++
.../v2/questions/DischargeMonth.jsx | 6 +-
.../components/v2/questions/DischargeType.jsx | 79 +++++++++++++++
.../components/v2/questions/DischargeYear.jsx | 4 +-
.../components/v2/questions/Intention.jsx | 79 +++++++++++++++
.../components/v2/questions/Reason.jsx | 95 +++++++++++++++++++
.../v2/questions/shared/Dropdown.jsx | 2 +-
.../v2/questions/shared/RadioGroup.jsx | 7 +-
.../constants/display-conditions.js | 73 ++++++++++++++
.../discharge-wizard/constants/index.js | 30 +++++-
.../constants/question-data-map.js | 38 +++++++-
.../reducers/v2/discharge-upgrade-wizard.js | 22 ++++-
src/applications/discharge-wizard/routes.jsx | 8 ++
.../sass/discharge-wizard.scss | 3 -
.../tests/v2/CourtMartial.unit.spec.js | 80 ++++++++++++++++
.../tests/v2/DischargeMonth.unit.spec.js | 25 +----
.../tests/v2/DischargeType.unit.spec.js | 80 ++++++++++++++++
.../tests/v2/DischargeYear.unit.spec.js | 25 +----
.../tests/v2/Intention.unit.spec.js | 80 ++++++++++++++++
.../tests/v2/Reason.unit.spec.js | 80 ++++++++++++++++
.../discharge-upgrade-wizard.cypress.spec.js | 57 +++++++++++
.../tests/v2/cypress/helpers.js | 55 +++++++++++
.../tests/v2/display-logic.unit.spec.js | 4 +-
.../utilities/display-logic-questions.js | 59 ++++++++----
.../utilities/page-navigation.js | 61 ++++++++++--
.../discharge-wizard/utilities/page-setup.js | 1 -
30 files changed, 1103 insertions(+), 93 deletions(-)
create mode 100644 src/applications/discharge-wizard/components/v2/BreadcrumbsV2.jsx
create mode 100644 src/applications/discharge-wizard/components/v2/questions/CourtMartial.jsx
create mode 100644 src/applications/discharge-wizard/components/v2/questions/DischargeType.jsx
create mode 100644 src/applications/discharge-wizard/components/v2/questions/Intention.jsx
create mode 100644 src/applications/discharge-wizard/components/v2/questions/Reason.jsx
create mode 100644 src/applications/discharge-wizard/constants/display-conditions.js
create mode 100644 src/applications/discharge-wizard/tests/v2/CourtMartial.unit.spec.js
create mode 100644 src/applications/discharge-wizard/tests/v2/DischargeType.unit.spec.js
create mode 100644 src/applications/discharge-wizard/tests/v2/Intention.unit.spec.js
create mode 100644 src/applications/discharge-wizard/tests/v2/Reason.unit.spec.js
create mode 100644 src/applications/discharge-wizard/tests/v2/cypress/discharge-upgrade-wizard.cypress.spec.js
create mode 100644 src/applications/discharge-wizard/tests/v2/cypress/helpers.js
diff --git a/src/applications/discharge-wizard/actions/index.js b/src/applications/discharge-wizard/actions/index.js
index 4e32d8121b5c..13034e9bbc0d 100644
--- a/src/applications/discharge-wizard/actions/index.js
+++ b/src/applications/discharge-wizard/actions/index.js
@@ -1,11 +1,15 @@
import {
DW_UPDATE_FIELD,
// v2 actions
+ DUW_UPDATE_FORM_STORE,
DUW_VIEWED_INTRO_PAGE,
DUW_UPDATE_SERVICE_BRANCH,
DUW_UPDATE_DISCHARGE_YEAR,
DUW_UPDATE_DISCHARGE_MONTH,
- DUW_UPDATE_FORM_STORE,
+ DUW_UPDATE_REASON,
+ DUW_UPDATE_DISCHARGE_TYPE,
+ DUW_UPDATE_COURT_MARTIAL,
+ DUW_UPDATE_INTENTION,
} from '../constants';
export const updateField = (key, value) => {
@@ -16,6 +20,13 @@ export const updateField = (key, value) => {
};
};
+export const updateFormStore = value => {
+ return {
+ type: DUW_UPDATE_FORM_STORE,
+ payload: value,
+ };
+};
+
export const updateIntroPageViewed = value => {
return {
type: DUW_VIEWED_INTRO_PAGE,
@@ -44,9 +55,30 @@ export const updateDischargeMonth = value => {
};
};
-export const updateFormStore = value => {
+export const updateReason = value => {
return {
- type: DUW_UPDATE_FORM_STORE,
+ type: DUW_UPDATE_REASON,
+ payload: value,
+ };
+};
+
+export const updateCourtMartial = value => {
+ return {
+ type: DUW_UPDATE_COURT_MARTIAL,
+ payload: value,
+ };
+};
+
+export const updateIntention = value => {
+ return {
+ type: DUW_UPDATE_INTENTION,
+ payload: value,
+ };
+};
+
+export const updateDischargeType = value => {
+ return {
+ type: DUW_UPDATE_DISCHARGE_TYPE,
payload: value,
};
};
diff --git a/src/applications/discharge-wizard/components/DischargeWizardApp.jsx b/src/applications/discharge-wizard/components/DischargeWizardApp.jsx
index 093b129b7fc5..48130a940c11 100644
--- a/src/applications/discharge-wizard/components/DischargeWizardApp.jsx
+++ b/src/applications/discharge-wizard/components/DischargeWizardApp.jsx
@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import environment from 'platform/utilities/environment';
import Breadcrumbs from './Breadcrumbs';
+import BreadcrumbsV2 from './v2/BreadcrumbsV2';
export default function DischargeWizardApp({ children }) {
const isProd = environment.isProduction();
@@ -16,7 +17,7 @@ export default function DischargeWizardApp({ children }) {
}
return (
);
diff --git a/src/applications/discharge-wizard/components/v2/BreadcrumbsV2.jsx b/src/applications/discharge-wizard/components/v2/BreadcrumbsV2.jsx
new file mode 100644
index 000000000000..263be14b8421
--- /dev/null
+++ b/src/applications/discharge-wizard/components/v2/BreadcrumbsV2.jsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import { VaBreadcrumbs } from '@department-of-veterans-affairs/web-components/react-bindings';
+
+const BreadcrumbsV2 = () => (
+
+);
+
+export default BreadcrumbsV2;
diff --git a/src/applications/discharge-wizard/components/v2/Homepage.jsx b/src/applications/discharge-wizard/components/v2/Homepage.jsx
index f1197ee02b17..ebe2e56d18d0 100644
--- a/src/applications/discharge-wizard/components/v2/Homepage.jsx
+++ b/src/applications/discharge-wizard/components/v2/Homepage.jsx
@@ -69,6 +69,7 @@ const HomePage = ({ router, setIntroPageViewed }) => {
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
diff --git a/src/applications/discharge-wizard/components/v2/questions/CourtMartial.jsx b/src/applications/discharge-wizard/components/v2/questions/CourtMartial.jsx
new file mode 100644
index 000000000000..33f0d71cc377
--- /dev/null
+++ b/src/applications/discharge-wizard/components/v2/questions/CourtMartial.jsx
@@ -0,0 +1,79 @@
+import React, { useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import {
+ QUESTION_MAP,
+ RESPONSES,
+ SHORT_NAME_MAP,
+} from '../../../constants/question-data-map';
+import RadioGroup from './shared/RadioGroup';
+import { updateCourtMartial } from '../../../actions';
+import { pageSetup } from '../../../utilities/page-setup';
+import { ROUTES } from '../../../constants';
+
+const CourtMartial = ({
+ formResponses,
+ setCourtMartial,
+ router,
+ viewedIntroPage,
+}) => {
+ const [formError, setFormError] = useState(false);
+ const shortName = SHORT_NAME_MAP.COURT_MARTIAL;
+ const H1 = QUESTION_MAP[shortName];
+ const courtMartial = formResponses[shortName];
+ const { COURT_MARTIAL_1, COURT_MARTIAL_2, COURT_MARTIAL_3 } = RESPONSES;
+
+ useEffect(
+ () => {
+ pageSetup(H1);
+ },
+ [H1],
+ );
+
+ useEffect(
+ () => {
+ if (!viewedIntroPage) {
+ router.push(ROUTES.HOME);
+ }
+ },
+ [router, viewedIntroPage],
+ );
+
+ return (
+
+ );
+};
+
+CourtMartial.propTypes = {
+ formResponses: PropTypes.object,
+ router: PropTypes.shape({
+ push: PropTypes.func,
+ }),
+ setCourtMartial: PropTypes.func,
+ viewedIntroPage: PropTypes.bool,
+};
+
+const mapStateToProps = state => ({
+ formResponses: state?.dischargeUpgradeWizard?.duwForm?.form,
+ viewedIntroPage: state?.dischargeUpgradeWizard?.duwForm?.viewedIntroPage,
+});
+
+const mapDispatchToProps = {
+ setCourtMartial: updateCourtMartial,
+};
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(CourtMartial);
diff --git a/src/applications/discharge-wizard/components/v2/questions/DischargeMonth.jsx b/src/applications/discharge-wizard/components/v2/questions/DischargeMonth.jsx
index dcda3a03f7af..d2dee067b73d 100644
--- a/src/applications/discharge-wizard/components/v2/questions/DischargeMonth.jsx
+++ b/src/applications/discharge-wizard/components/v2/questions/DischargeMonth.jsx
@@ -42,7 +42,11 @@ const DischargeMonth = ({
const dischargeMonth = formResponses[shortName];
const monthOptions = months.map(month => {
return (
-
);
diff --git a/src/applications/discharge-wizard/components/v2/questions/DischargeType.jsx b/src/applications/discharge-wizard/components/v2/questions/DischargeType.jsx
new file mode 100644
index 000000000000..1fa61cac530e
--- /dev/null
+++ b/src/applications/discharge-wizard/components/v2/questions/DischargeType.jsx
@@ -0,0 +1,79 @@
+import React, { useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import {
+ QUESTION_MAP,
+ RESPONSES,
+ SHORT_NAME_MAP,
+} from '../../../constants/question-data-map';
+import RadioGroup from './shared/RadioGroup';
+import { updateDischargeType } from '../../../actions';
+import { pageSetup } from '../../../utilities/page-setup';
+import { ROUTES } from '../../../constants';
+
+const DischargeType = ({
+ formResponses,
+ setDischargeType,
+ router,
+ viewedIntroPage,
+}) => {
+ const [formError, setFormError] = useState(false);
+ const shortName = SHORT_NAME_MAP.DISCHARGE_TYPE;
+ const H1 = QUESTION_MAP[shortName];
+ const dischargeType = formResponses[shortName];
+ const { DISCHARGE_TYPE_1, DISCHARGE_TYPE_2 } = RESPONSES;
+
+ useEffect(
+ () => {
+ pageSetup(H1);
+ },
+ [H1],
+ );
+
+ useEffect(
+ () => {
+ if (!viewedIntroPage) {
+ router.push(ROUTES.HOME);
+ }
+ },
+ [router, viewedIntroPage],
+ );
+
+ return (
+
+ );
+};
+
+DischargeType.propTypes = {
+ formResponses: PropTypes.object,
+ setDischargeType: PropTypes.func,
+ router: PropTypes.shape({
+ push: PropTypes.func,
+ }),
+ viewedIntroPage: PropTypes.bool,
+};
+
+const mapStateToProps = state => ({
+ formResponses: state?.dischargeUpgradeWizard?.duwForm?.form,
+ viewedIntroPage: state?.dischargeUpgradeWizard?.duwForm?.viewedIntroPage,
+});
+
+const mapDispatchToProps = {
+ setDischargeType: updateDischargeType,
+};
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(DischargeType);
diff --git a/src/applications/discharge-wizard/components/v2/questions/DischargeYear.jsx b/src/applications/discharge-wizard/components/v2/questions/DischargeYear.jsx
index ecd2db3921a0..3a67242cfc1f 100644
--- a/src/applications/discharge-wizard/components/v2/questions/DischargeYear.jsx
+++ b/src/applications/discharge-wizard/components/v2/questions/DischargeYear.jsx
@@ -44,7 +44,7 @@ const DischargeYear = ({
const yearOptions = range(currentYear - 1992).map(i => {
const year = currentYear - i;
return (
-
);
@@ -52,7 +52,7 @@ const DischargeYear = ({
const before1992Key = yearOptions.length + 1;
yearOptions.push(
- ,
);
diff --git a/src/applications/discharge-wizard/components/v2/questions/Intention.jsx b/src/applications/discharge-wizard/components/v2/questions/Intention.jsx
new file mode 100644
index 000000000000..ef2ea18a0ea4
--- /dev/null
+++ b/src/applications/discharge-wizard/components/v2/questions/Intention.jsx
@@ -0,0 +1,79 @@
+import React, { useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import {
+ QUESTION_MAP,
+ RESPONSES,
+ SHORT_NAME_MAP,
+} from '../../../constants/question-data-map';
+import RadioGroup from './shared/RadioGroup';
+import { updateIntention } from '../../../actions';
+import { pageSetup } from '../../../utilities/page-setup';
+import { ROUTES } from '../../../constants';
+
+const Intention = ({
+ formResponses,
+ setIntention,
+ router,
+ viewedIntroPage,
+}) => {
+ const [formError, setFormError] = useState(false);
+ const shortName = SHORT_NAME_MAP.INTENTION;
+ const H1 = QUESTION_MAP[shortName];
+ const intention = formResponses[shortName];
+ const { INTENTION_1, INTENTION_2 } = RESPONSES;
+
+ useEffect(
+ () => {
+ pageSetup(H1);
+ },
+ [H1],
+ );
+
+ useEffect(
+ () => {
+ if (!viewedIntroPage) {
+ router.push(ROUTES.HOME);
+ }
+ },
+ [router, viewedIntroPage],
+ );
+
+ return (
+
+ );
+};
+
+Intention.propTypes = {
+ formResponses: PropTypes.object,
+ router: PropTypes.shape({
+ push: PropTypes.func,
+ }),
+ setIntention: PropTypes.func,
+ viewedIntroPage: PropTypes.bool,
+};
+
+const mapStateToProps = state => ({
+ formResponses: state?.dischargeUpgradeWizard?.duwForm?.form,
+ viewedIntroPage: state?.dischargeUpgradeWizard?.duwForm?.viewedIntroPage,
+});
+
+const mapDispatchToProps = {
+ setIntention: updateIntention,
+};
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(Intention);
diff --git a/src/applications/discharge-wizard/components/v2/questions/Reason.jsx b/src/applications/discharge-wizard/components/v2/questions/Reason.jsx
new file mode 100644
index 000000000000..70c3378a63bf
--- /dev/null
+++ b/src/applications/discharge-wizard/components/v2/questions/Reason.jsx
@@ -0,0 +1,95 @@
+import React, { useEffect, useState } from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import {
+ QUESTION_MAP,
+ RESPONSES,
+ SHORT_NAME_MAP,
+} from '../../../constants/question-data-map';
+import RadioGroup from './shared/RadioGroup';
+import { updateReason } from '../../../actions';
+import { pageSetup } from '../../../utilities/page-setup';
+import { ROUTES } from '../../../constants';
+
+const Reason = ({ formResponses, setReason, router, viewedIntroPage }) => {
+ const [formError, setFormError] = useState(false);
+ const shortName = SHORT_NAME_MAP.REASON;
+ const H1 = QUESTION_MAP[shortName];
+ const reason = formResponses[shortName];
+ const hint =
+ 'Note: If more than one of these descriptions matches your situation, choose the one that started the events that led to your discharge. For example, if you sustained a traumatic brain injury, which led to posttraumatic stress disorder (PTSD), choose number 2.';
+ const {
+ REASON_1,
+ REASON_2,
+ REASON_3,
+ REASON_4,
+ REASON_5,
+ REASON_6,
+ REASON_7,
+ REASON_8,
+ } = RESPONSES;
+
+ useEffect(
+ () => {
+ pageSetup(H1);
+ },
+ [H1],
+ );
+
+ useEffect(
+ () => {
+ if (!viewedIntroPage) {
+ router.push(ROUTES.HOME);
+ }
+ },
+ [router, viewedIntroPage],
+ );
+
+ return (
+
+ );
+};
+
+Reason.propTypes = {
+ formResponses: PropTypes.object,
+ router: PropTypes.shape({
+ push: PropTypes.func,
+ }),
+ setReason: PropTypes.func,
+ viewedIntroPage: PropTypes.bool,
+};
+
+const mapStateToProps = state => ({
+ formResponses: state?.dischargeUpgradeWizard?.duwForm?.form,
+ viewedIntroPage: state?.dischargeUpgradeWizard?.duwForm?.viewedIntroPage,
+});
+
+const mapDispatchToProps = {
+ setReason: updateReason,
+};
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(Reason);
diff --git a/src/applications/discharge-wizard/components/v2/questions/shared/Dropdown.jsx b/src/applications/discharge-wizard/components/v2/questions/shared/Dropdown.jsx
index 6433f3fa53f7..435bbee4112d 100644
--- a/src/applications/discharge-wizard/components/v2/questions/shared/Dropdown.jsx
+++ b/src/applications/discharge-wizard/components/v2/questions/shared/Dropdown.jsx
@@ -61,7 +61,7 @@ const Dropdown = ({
}
setFormError(false);
- navigateForward(shortName, formValue, router);
+ navigateForward(shortName, formResponses, router);
}
};
diff --git a/src/applications/discharge-wizard/components/v2/questions/shared/RadioGroup.jsx b/src/applications/discharge-wizard/components/v2/questions/shared/RadioGroup.jsx
index a4f2a183e413..e90adfdd6ac6 100644
--- a/src/applications/discharge-wizard/components/v2/questions/shared/RadioGroup.jsx
+++ b/src/applications/discharge-wizard/components/v2/questions/shared/RadioGroup.jsx
@@ -19,6 +19,7 @@ const RadioGroup = ({
formError,
formResponses,
formValue,
+ hint,
H1,
responses,
router,
@@ -42,7 +43,7 @@ const RadioGroup = ({
}
setFormError(false);
- navigateForward(shortName, formValue, router, formResponses);
+ navigateForward(shortName, formResponses, router);
}
};
@@ -76,15 +77,14 @@ const RadioGroup = ({
);
});
};
-
return (
<>
onValueChange(e.detail.value)}
onLoad={applyFocus('duw-radio', headerHasFocused, setHeaderHasFocused)}
@@ -117,6 +117,7 @@ RadioGroup.propTypes = {
updateCleanedFormStore: PropTypes.func.isRequired,
valueSetter: PropTypes.func.isRequired,
formValue: PropTypes.string,
+ hint: PropTypes.string,
};
const mapDispatchToProps = {
diff --git a/src/applications/discharge-wizard/constants/display-conditions.js b/src/applications/discharge-wizard/constants/display-conditions.js
new file mode 100644
index 000000000000..8cf3eed25223
--- /dev/null
+++ b/src/applications/discharge-wizard/constants/display-conditions.js
@@ -0,0 +1,73 @@
+import { range } from 'lodash';
+import { RESPONSES } from './question-data-map';
+
+const get15YearsPast = () => `${new Date().getFullYear() - 15}`;
+const currentYear = new Date().getFullYear();
+const yearResponses = range(currentYear - 1992).map(i => {
+ const year = currentYear - i;
+ return year.toString();
+});
+const {
+ ARMY,
+ NAVY,
+ AIR_FORCE,
+ COAST_GUARD,
+ MARINE_CORPS,
+ REASON_1,
+ REASON_2,
+ REASON_3,
+ REASON_4,
+ REASON_5,
+ // REASON_8,
+ REASON_6,
+ REASON_7,
+ // INTENTION_1,
+ // INTENTION_2,
+ // COURT_MARTIAL_1,
+ // COURT_MARTIAL_2,
+ // COURT_MARTIAL_3,
+ // DISCHARGE_TYPE_1,
+ // DISCHARGE_TYPE_2,
+} = RESPONSES;
+
+export const DISPLAY_CONDITIONS = Object.freeze({
+ SERVICE_BRANCH: {},
+ DISCHARGE_YEAR: {
+ SERVICE_BRANCH: [ARMY, NAVY, AIR_FORCE, COAST_GUARD, MARINE_CORPS],
+ },
+ DISCHARGE_MONTH: {
+ SERVICE_BRANCH: [ARMY, NAVY, AIR_FORCE, COAST_GUARD, MARINE_CORPS],
+ DISCHARGE_YEAR: [get15YearsPast()],
+ },
+ REASON: {
+ SERVICE_BRANCH: [ARMY, NAVY, AIR_FORCE, COAST_GUARD, MARINE_CORPS],
+ DISCHARGE_YEAR: yearResponses,
+ DISCHARGE_MONTH: [],
+ },
+ DISCHARGE_TYPE: {
+ SERVICE_BRANCH: [ARMY, NAVY, AIR_FORCE, COAST_GUARD, MARINE_CORPS],
+ DISCHARGE_YEAR: yearResponses,
+ DISCHARGE_MONTH: [],
+ REASON: [REASON_3],
+ },
+ INTENTION: {
+ SERVICE_BRANCH: [ARMY, NAVY, AIR_FORCE, COAST_GUARD, MARINE_CORPS],
+ DISCHARGE_YEAR: yearResponses,
+ DISCHARGE_MONTH: [],
+ REASON: [REASON_1, REASON_2, REASON_3, REASON_4, REASON_6, REASON_7],
+ },
+ COURT_MARTIAL: {
+ SERVICE_BRANCH: [ARMY, NAVY, AIR_FORCE, COAST_GUARD, MARINE_CORPS],
+ DISCHARGE_YEAR: yearResponses,
+ DISCHARGE_MONTH: [],
+ REASON: [
+ REASON_5,
+ REASON_1,
+ REASON_2,
+ REASON_3,
+ REASON_4,
+ REASON_6,
+ REASON_7,
+ ],
+ },
+});
diff --git a/src/applications/discharge-wizard/constants/index.js b/src/applications/discharge-wizard/constants/index.js
index 195e85a34a53..d595a69a22bf 100644
--- a/src/applications/discharge-wizard/constants/index.js
+++ b/src/applications/discharge-wizard/constants/index.js
@@ -100,21 +100,33 @@ import { SHORT_NAME_MAP } from './question-data-map';
export const DUW_VIEWED_INTRO_PAGE =
'discharge-upgrade-wizard/DUW_VIEWED_INTRO_PAGE';
+export const DUW_UPDATE_FORM_STORE =
+ 'discharge-upgrade-wizard/DUW_UPDATE_FORM_STORE';
export const DUW_UPDATE_SERVICE_BRANCH =
'discharge-upgrade-wizard/DUW_UPDATE_SERVICE_BRANCH';
export const DUW_UPDATE_DISCHARGE_YEAR =
'discharge-upgrade-wizard/DUW_UPDATE_DISCHARGE_YEAR';
export const DUW_UPDATE_DISCHARGE_MONTH =
'discharge-upgrade-wizard/DUW_UPDATE_DISCHARGE_MONTH';
-export const DUW_UPDATE_FORM_STORE =
- 'discharge-upgrade-wizard/DUW_UPDATE_FORM_STORE';
+export const DUW_UPDATE_REASON = 'discharge-upgrade-wizard/DUW_UPDATE_REASON';
+export const DUW_UPDATE_DISCHARGE_TYPE =
+ 'discharge-upgrade-wizard/DUW_UPDATE_DISCHARGE_TYPE';
+export const DUW_UPDATE_COURT_MARTIAL =
+ 'discharge-upgrade-wizard/DUW_UPDATE_COURT_MARTIAL';
+export const DUW_UPDATE_INTENTION =
+ 'discharge-upgrade-wizard/DUW_UPDATE_INTENTION';
export const ROUTES = Object.freeze({
HOME: 'introduction',
SERVICE_BRANCH: 'service-branch',
DISCHARGE_YEAR: 'discharge-year',
DISCHARGE_MONTH: 'discharge-month',
- DISCHARGE_REASON: 'discharge-reason',
+ REASON: 'reason',
+ DISCHARGE_TYPE: 'discharge-type',
+ COURT_MARTIAL: 'court-martial',
+ INTENTION: 'intention',
+ PREVIOUS_APPLICATION: 'previous-application',
+ PREVIOUS_APPLICATION_TYPE: 'previous-application-type',
RESULT: 'result',
});
@@ -122,13 +134,23 @@ export const questionsToClearMap = Object.freeze({
SERVICE_BRANCH: [],
DISCHARGE_YEAR: [SHORT_NAME_MAP.DISCHARGE_MONTH],
DISCHARGE_MONTH: [],
- DISCHARGE_REASON: [],
+ REASON: [
+ SHORT_NAME_MAP.DISCHARGE_TYPE,
+ SHORT_NAME_MAP.COURT_MARTIAL,
+ SHORT_NAME_MAP.INTENTION,
+ SHORT_NAME_MAP.PREVIOUS_APPLICATION,
+ ],
+ DISCHARGE_TYPE: [],
+ COURT_MARTIAL: [],
+ INTENTION: [],
+ PREVIOUS_APPLICATION: [],
});
export const errorTextMap = Object.freeze({
SERVICE_BRANCH: 'Select a branch',
DISCHARGE_YEAR: 'Select a year',
DISCHARGE_MONTH: 'Select a month',
+ REASON: 'Select a reason',
});
export const labelTextMap = Object.freeze({
diff --git a/src/applications/discharge-wizard/constants/question-data-map.js b/src/applications/discharge-wizard/constants/question-data-map.js
index 5c91ed3cfa2c..f5186019f5b8 100644
--- a/src/applications/discharge-wizard/constants/question-data-map.js
+++ b/src/applications/discharge-wizard/constants/question-data-map.js
@@ -3,6 +3,11 @@ export const QUESTION_MAP = Object.freeze({
SERVICE_BRANCH: 'What was your branch of service?',
DISCHARGE_YEAR: 'What year were you discharged from the military?',
DISCHARGE_MONTH: 'What month were you discharged?',
+ REASON: 'Tell us why you want to change your discharge paperwork.',
+ DISCHARGE_TYPE: `What's your character of discharge?`,
+ INTENTION:
+ 'Do you want to change your name, discharge date, or something written in the "other remarks" section of your DD214?',
+ COURT_MARTIAL: 'Was your discharge the outcome of a general court-martial?',
});
export const SHORT_NAME_MAP = Object.freeze({
@@ -10,7 +15,12 @@ export const SHORT_NAME_MAP = Object.freeze({
SERVICE_BRANCH: 'SERVICE_BRANCH',
DISCHARGE_YEAR: 'DISCHARGE_YEAR',
DISCHARGE_MONTH: 'DISCHARGE_MONTH',
- DISCHARGE_REASON: 'DISCHARGE_REASON',
+ REASON: 'REASON',
+ DISCHARGE_TYPE: 'DISCHARGE_TYPE',
+ INTENTION: 'INTENTION',
+ COURT_MARTIAL: 'COURT_MARTIAL',
+ PREVIOUS_APPLICATION_TYPE: 'PREVIOUS_APPLICATION_TYPE',
+ PREVIOUS_APPLICATION: 'PREVIOUS_APPLICATION',
});
export const RESPONSES = Object.freeze({
@@ -19,4 +29,30 @@ export const RESPONSES = Object.freeze({
AIR_FORCE: 'Air Force',
COAST_GUARD: 'Coast Guard',
MARINE_CORPS: 'Marine Corps',
+ REASON_1:
+ 'I suffered from undiagnosed, misdiagnosed, or untreated posttraumatic stress disorder (PTSD), or another mental health condition, during my service. I was discharged for reasons related to this condition.',
+ REASON_2:
+ 'I suffered from an undiagnosed, misdiagnosed, or untreated traumatic brain injury (TBI) during my service. I was discharged for reasons related to this condition.',
+ REASON_3:
+ 'I was discharged due to my sexual orientation (including under the Don’t Ask, Don’t Tell policy).',
+ REASON_4:
+ 'I experienced sexual assault or harassment during my service. I was discharged for reasons related to this experience.',
+ REASON_5:
+ 'I’m transgender, and my discharge shows my birth name instead of my current name.',
+ REASON_8:
+ 'I received a DD215 that shows my discharge upgrade or correction. But I want an updated DD214.',
+ REASON_6: 'My discharge paperwork has another kind of error.',
+ REASON_7:
+ 'My discharge is unjust, and it isn’t related to any of the reasons listed here.',
+ INTENTION_1: `Yes, I want to change my name, discharge date, or something written in the "other remarks" section of my DD214. (This isn't common.)`,
+ INTENTION_2:
+ 'No, I want to change only my characterization of discharge, re-enlistment code, separation code, or narrative reason for discharge.',
+ COURT_MARTIAL_1:
+ 'Yes, my discharge was the outcome of a general court-martial.',
+ COURT_MARTIAL_2:
+ 'No, my discharge was administrative or the outcome of a special or summary court-martial.',
+ COURT_MARTIAL_3: `I'm not sure.`,
+ DISCHARGE_TYPE_1:
+ 'My discharge is honorable or general under honorable conditions. I want to change only my narrative reason for discharge, separation code, or re-enlistment code.',
+ DISCHARGE_TYPE_2: `My discharge isn't honorable or under honorable conditions.`,
});
diff --git a/src/applications/discharge-wizard/reducers/v2/discharge-upgrade-wizard.js b/src/applications/discharge-wizard/reducers/v2/discharge-upgrade-wizard.js
index 38fb9e671f9a..6b82023d4e53 100644
--- a/src/applications/discharge-wizard/reducers/v2/discharge-upgrade-wizard.js
+++ b/src/applications/discharge-wizard/reducers/v2/discharge-upgrade-wizard.js
@@ -3,13 +3,25 @@ import {
DUW_UPDATE_SERVICE_BRANCH,
DUW_UPDATE_DISCHARGE_YEAR,
DUW_UPDATE_DISCHARGE_MONTH,
+ DUW_UPDATE_REASON,
+ DUW_UPDATE_DISCHARGE_TYPE,
+ DUW_UPDATE_INTENTION,
+ DUW_UPDATE_COURT_MARTIAL,
DUW_UPDATE_FORM_STORE,
} from '../../constants';
import { SHORT_NAME_MAP } from '../../constants/question-data-map';
import { createFormStore, updateFormValue } from './utilities';
-const { SERVICE_BRANCH, DISCHARGE_YEAR, DISCHARGE_MONTH } = SHORT_NAME_MAP;
+const {
+ SERVICE_BRANCH,
+ DISCHARGE_YEAR,
+ DISCHARGE_MONTH,
+ REASON,
+ DISCHARGE_TYPE,
+ COURT_MARTIAL,
+ INTENTION,
+} = SHORT_NAME_MAP;
const initialState = {
currentPage: SHORT_NAME_MAP.HOME,
@@ -25,6 +37,14 @@ export default (state = initialState, action) => {
return updateFormValue(DISCHARGE_YEAR, state, action);
case DUW_UPDATE_DISCHARGE_MONTH:
return updateFormValue(DISCHARGE_MONTH, state, action);
+ case DUW_UPDATE_REASON:
+ return updateFormValue(REASON, state, action);
+ case DUW_UPDATE_DISCHARGE_TYPE:
+ return updateFormValue(DISCHARGE_TYPE, state, action);
+ case DUW_UPDATE_COURT_MARTIAL:
+ return updateFormValue(COURT_MARTIAL, state, action);
+ case DUW_UPDATE_INTENTION:
+ return updateFormValue(INTENTION, state, action);
case DUW_VIEWED_INTRO_PAGE:
return {
...state,
diff --git a/src/applications/discharge-wizard/routes.jsx b/src/applications/discharge-wizard/routes.jsx
index 5aa0f4ec161e..fb5bc002c3b2 100644
--- a/src/applications/discharge-wizard/routes.jsx
+++ b/src/applications/discharge-wizard/routes.jsx
@@ -10,6 +10,10 @@ import HomePage from './components/v2/Homepage';
import ServiceBranch from './components/v2/questions/ServiceBranch';
import DischargeYear from './components/v2/questions/DischargeYear';
import DischargeMonth from './components/v2/questions/DischargeMonth';
+import Reason from './components/v2/questions/Reason';
+import DischargeType from './components/v2/questions/DischargeType';
+import CourtMartial from './components/v2/questions/CourtMartial';
+import Intention from './components/v2/questions/Intention';
const envChildRoutes = environment.isProduction()
? [
@@ -27,6 +31,10 @@ const envChildRoutes = environment.isProduction()
{ path: 'service-branch', component: ServiceBranch },
{ path: 'discharge-year', component: DischargeYear },
{ path: 'discharge-month', component: DischargeMonth },
+ { path: 'reason', component: Reason },
+ { path: 'discharge-type', component: DischargeType },
+ { path: 'court-martial', component: CourtMartial },
+ { path: 'intention', component: Intention },
];
const routes = {
path: '/',
diff --git a/src/applications/discharge-wizard/sass/discharge-wizard.scss b/src/applications/discharge-wizard/sass/discharge-wizard.scss
index 7e48a838c16e..5326d8dcf1f9 100644
--- a/src/applications/discharge-wizard/sass/discharge-wizard.scss
+++ b/src/applications/discharge-wizard/sass/discharge-wizard.scss
@@ -119,7 +119,4 @@ $formation-image-path: "~@department-of-veterans-affairs/formation/assets/img";
}
.discharge-wizard-v2 {
//v2 styles
- #form-description {
- display: none;
- }
}
\ No newline at end of file
diff --git a/src/applications/discharge-wizard/tests/v2/CourtMartial.unit.spec.js b/src/applications/discharge-wizard/tests/v2/CourtMartial.unit.spec.js
new file mode 100644
index 000000000000..b1872f3f8d5f
--- /dev/null
+++ b/src/applications/discharge-wizard/tests/v2/CourtMartial.unit.spec.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { Provider } from 'react-redux';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+import sinon from 'sinon';
+import { ROUTES } from '../../constants';
+
+import CourtMartial from '../../components/v2/questions/CourtMartial';
+
+const mockStoreStandard = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: true,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const mockStoreNoIntroPage = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: false,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const pushStub = sinon.stub();
+
+const propsStandard = {
+ formResponses: {},
+ setCourtMartial: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: true,
+};
+
+const propsNoIntroPage = {
+ formResponses: {},
+ setCourtMartial: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: false,
+};
+
+describe('Court Martial Page', () => {
+ afterEach(() => {
+ pushStub.resetHistory();
+ });
+
+ it('should correctly load the court martial page in the standard flow', () => {
+ const screen = render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId('duw-court_martial')).to.exist;
+ });
+
+ it('should redirect to home when the intro page has not been viewed', () => {
+ render(
+
+
+ ,
+ );
+
+ expect(pushStub.withArgs(ROUTES.HOME).called).to.be.true;
+ });
+});
diff --git a/src/applications/discharge-wizard/tests/v2/DischargeMonth.unit.spec.js b/src/applications/discharge-wizard/tests/v2/DischargeMonth.unit.spec.js
index a12798db674a..cb071b6b2636 100644
--- a/src/applications/discharge-wizard/tests/v2/DischargeMonth.unit.spec.js
+++ b/src/applications/discharge-wizard/tests/v2/DischargeMonth.unit.spec.js
@@ -3,7 +3,6 @@ import { Provider } from 'react-redux';
import { render } from '@testing-library/react';
import { expect } from 'chai';
import sinon from 'sinon';
-import { RESPONSES } from '../../constants/question-data-map';
import { ROUTES } from '../../constants';
import DischargeMonth from '../../components/v2/questions/DischargeMonth';
@@ -12,11 +11,7 @@ const mockStoreStandard = {
getState: () => ({
dischargeUpgradeWizard: {
duwForm: {
- form: {
- SERVICE_BRANCH: null,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ form: {},
viewedIntroPage: true,
},
},
@@ -29,11 +24,7 @@ const mockStoreNoIntroPage = {
getState: () => ({
dischargeUpgradeWizard: {
duwForm: {
- form: {
- SERVICE_BRANCH: null,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ form: {},
viewedIntroPage: false,
},
},
@@ -45,11 +36,7 @@ const mockStoreNoIntroPage = {
const pushStub = sinon.stub();
const propsStandard = {
- formResponses: {
- SERVICE_BRANCH: RESPONSES.ARMY,
- DISCHARGE_YEAR: 2009,
- DISCHARGE_MONTH: null,
- },
+ formResponses: {},
setDischargeMonth: () => {},
router: {
push: pushStub,
@@ -58,11 +45,7 @@ const propsStandard = {
};
const propsNoIntroPage = {
- formResponses: {
- SERVICE_BRANCH: RESPONSES.ARMY,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ formResponses: {},
setDischargeMonth: () => {},
router: {
push: pushStub,
diff --git a/src/applications/discharge-wizard/tests/v2/DischargeType.unit.spec.js b/src/applications/discharge-wizard/tests/v2/DischargeType.unit.spec.js
new file mode 100644
index 000000000000..07e09c77ea10
--- /dev/null
+++ b/src/applications/discharge-wizard/tests/v2/DischargeType.unit.spec.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { Provider } from 'react-redux';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+import sinon from 'sinon';
+import { ROUTES } from '../../constants';
+
+import DischargeType from '../../components/v2/questions/DischargeType';
+
+const mockStoreStandard = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: true,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const mockStoreNoIntroPage = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: false,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const pushStub = sinon.stub();
+
+const propsStandard = {
+ formResponses: {},
+ setCourtMartial: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: true,
+};
+
+const propsNoIntroPage = {
+ formResponses: {},
+ setCourtMartial: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: false,
+};
+
+describe('Discharge Type Page', () => {
+ afterEach(() => {
+ pushStub.resetHistory();
+ });
+
+ it('should correctly load the discharge type page in the standard flow', () => {
+ const screen = render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId('duw-discharge_type')).to.exist;
+ });
+
+ it('should redirect to home when the intro page has not been viewed', () => {
+ render(
+
+
+ ,
+ );
+
+ expect(pushStub.withArgs(ROUTES.HOME).called).to.be.true;
+ });
+});
diff --git a/src/applications/discharge-wizard/tests/v2/DischargeYear.unit.spec.js b/src/applications/discharge-wizard/tests/v2/DischargeYear.unit.spec.js
index 46f9a0e4e293..6f70ee624de7 100644
--- a/src/applications/discharge-wizard/tests/v2/DischargeYear.unit.spec.js
+++ b/src/applications/discharge-wizard/tests/v2/DischargeYear.unit.spec.js
@@ -3,7 +3,6 @@ import { Provider } from 'react-redux';
import { render } from '@testing-library/react';
import { expect } from 'chai';
import sinon from 'sinon';
-import { RESPONSES } from '../../constants/question-data-map';
import { ROUTES } from '../../constants';
import DischargeYear from '../../components/v2/questions/DischargeYear';
@@ -12,11 +11,7 @@ const mockStoreStandard = {
getState: () => ({
dischargeUpgradeWizard: {
duwForm: {
- form: {
- SERVICE_BRANCH: null,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ form: {},
viewedIntroPage: true,
},
},
@@ -29,11 +24,7 @@ const mockStoreNoIntroPage = {
getState: () => ({
dischargeUpgradeWizard: {
duwForm: {
- form: {
- SERVICE_BRANCH: null,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ form: {},
viewedIntroPage: false,
},
},
@@ -45,11 +36,7 @@ const mockStoreNoIntroPage = {
const pushStub = sinon.stub();
const propsStandard = {
- formResponses: {
- SERVICE_BRANCH: RESPONSES.ARMY,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ formResponses: {},
setDischargeYear: () => {},
router: {
push: pushStub,
@@ -58,11 +45,7 @@ const propsStandard = {
};
const propsNoIntroPage = {
- formResponses: {
- SERVICE_BRANCH: RESPONSES.ARMY,
- DISCHARGE_YEAR: null,
- DISCHARGE_MONTH: null,
- },
+ formResponses: {},
setDischargeYear: () => {},
router: {
push: pushStub,
diff --git a/src/applications/discharge-wizard/tests/v2/Intention.unit.spec.js b/src/applications/discharge-wizard/tests/v2/Intention.unit.spec.js
new file mode 100644
index 000000000000..2fef8e61f881
--- /dev/null
+++ b/src/applications/discharge-wizard/tests/v2/Intention.unit.spec.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { Provider } from 'react-redux';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+import sinon from 'sinon';
+import { ROUTES } from '../../constants';
+
+import Intention from '../../components/v2/questions/Intention';
+
+const mockStoreStandard = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: true,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const mockStoreNoIntroPage = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: false,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const pushStub = sinon.stub();
+
+const propsStandard = {
+ formResponses: {},
+ setIntention: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: true,
+};
+
+const propsNoIntroPage = {
+ formResponses: {},
+ setIntention: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: false,
+};
+
+describe('Intention Page', () => {
+ afterEach(() => {
+ pushStub.resetHistory();
+ });
+
+ it('should correctly load the intention page in the standard flow', () => {
+ const screen = render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId('duw-intention')).to.exist;
+ });
+
+ it('should redirect to home when the intro page has not been viewed', () => {
+ render(
+
+
+ ,
+ );
+
+ expect(pushStub.withArgs(ROUTES.HOME).called).to.be.true;
+ });
+});
diff --git a/src/applications/discharge-wizard/tests/v2/Reason.unit.spec.js b/src/applications/discharge-wizard/tests/v2/Reason.unit.spec.js
new file mode 100644
index 000000000000..500b37bdb300
--- /dev/null
+++ b/src/applications/discharge-wizard/tests/v2/Reason.unit.spec.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import { Provider } from 'react-redux';
+import { render } from '@testing-library/react';
+import { expect } from 'chai';
+import sinon from 'sinon';
+import { ROUTES } from '../../constants';
+
+import Reason from '../../components/v2/questions/Reason';
+
+const mockStoreStandard = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: true,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const mockStoreNoIntroPage = {
+ getState: () => ({
+ dischargeUpgradeWizard: {
+ duwForm: {
+ form: {},
+ viewedIntroPage: false,
+ },
+ },
+ }),
+ subscribe: () => {},
+ dispatch: () => {},
+};
+
+const pushStub = sinon.stub();
+
+const propsStandard = {
+ formResponses: {},
+ setReason: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: true,
+};
+
+const propsNoIntroPage = {
+ formResponses: {},
+ setReason: () => {},
+ router: {
+ push: pushStub,
+ },
+ viewedIntroPage: false,
+};
+
+describe('Reason Page', () => {
+ afterEach(() => {
+ pushStub.resetHistory();
+ });
+
+ it('should correctly load the reason page in the standard flow', () => {
+ const screen = render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId('duw-reason')).to.exist;
+ });
+
+ it('should redirect to home when the intro page has not been viewed', () => {
+ render(
+
+
+ ,
+ );
+
+ expect(pushStub.withArgs(ROUTES.HOME).called).to.be.true;
+ });
+});
diff --git a/src/applications/discharge-wizard/tests/v2/cypress/discharge-upgrade-wizard.cypress.spec.js b/src/applications/discharge-wizard/tests/v2/cypress/discharge-upgrade-wizard.cypress.spec.js
new file mode 100644
index 000000000000..4701ebdd5688
--- /dev/null
+++ b/src/applications/discharge-wizard/tests/v2/cypress/discharge-upgrade-wizard.cypress.spec.js
@@ -0,0 +1,57 @@
+import * as h from './helpers';
+import { ROUTES } from '../../../constants';
+import { SHORT_NAME_MAP } from '../../../constants/question-data-map';
+
+xdescribe('Discharge Upgrade Wizard', () => {
+ describe('Base navigation', () => {
+ it('navigates through the flow forward successfully', () => {
+ cy.visit(`${h.ROOT}/introduction1`);
+
+ // Home
+ h.verifyUrl(`${ROUTES.HOME}1`);
+ cy.injectAxeThenAxeCheck();
+ h.clickStart();
+
+ // SERVICE_BRANCH
+ h.verifyUrl(ROUTES.SERVICE_BRANCH);
+ h.selectRadio(h.SERVICE_BRANCH_INPUT, 3);
+ h.clickContinue();
+
+ // DISCHARGE_YEAR
+ h.verifyUrl(ROUTES.DISCHARGE_YEAR);
+ h.selectDropdown(
+ h.DISCHARGE_YEAR_INPUT,
+ SHORT_NAME_MAP.DISCHARGE_YEAR,
+ h.get15YearsPast(),
+ );
+ h.clickContinue();
+
+ // DISCHARGE_MONTH
+ h.verifyUrl(ROUTES.DISCHARGE_MONTH);
+ h.selectDropdown(
+ h.DISCHARGE_MONTH_INPUT,
+ SHORT_NAME_MAP.DISCHARGE_MONTH,
+ 3,
+ );
+ h.clickContinue();
+
+ // DISCHARGE_REASON
+ h.verifyUrl(ROUTES.REASON);
+ h.selectRadio(h.REASON_INPUT, 3);
+ h.clickContinue();
+
+ // INTENTION
+ h.verifyUrl(ROUTES.INTENTION);
+ h.selectRadio(h.INTENTION_INPUT, 1);
+ h.clickContinue();
+
+ // COURT_MARTIAL
+ h.verifyUrl(ROUTES.COURT_MARTIAL);
+ h.selectRadio(h.COURT_MARTIAL_INPUT, 1);
+ h.clickContinue();
+
+ // PREVIOUS_APPLICATION
+ h.verifyUrl(ROUTES.PREVIOUS_APPLICATION);
+ });
+ });
+});
diff --git a/src/applications/discharge-wizard/tests/v2/cypress/helpers.js b/src/applications/discharge-wizard/tests/v2/cypress/helpers.js
new file mode 100644
index 000000000000..68468e168769
--- /dev/null
+++ b/src/applications/discharge-wizard/tests/v2/cypress/helpers.js
@@ -0,0 +1,55 @@
+export const ROOT = '/discharge-upgrade-instructions';
+export const START_ID = 'duw-start-form';
+
+export const SERVICE_BRANCH_INPUT = 'duw-service_branch';
+export const DISCHARGE_YEAR_INPUT = 'duw-discharge_year';
+export const DISCHARGE_MONTH_INPUT = 'duw-discharge_month';
+export const REASON_INPUT = 'duw-reason';
+export const INTENTION_INPUT = 'duw-intention';
+export const COURT_MARTIAL_INPUT = 'duw-court_martial';
+
+export const clickStart = () =>
+ cy
+ .findByTestId(START_ID)
+ .should('be.visible')
+ .click();
+
+export const verifyUrl = link => cy.url().should('contain', `${ROOT}/${link}`);
+
+export const get15YearsPast = () => (new Date().getFullYear() - 15).toString();
+
+export const verifyElement = selector =>
+ cy.findByTestId(selector).should('exist');
+
+export const selectRadio = (selector, index) =>
+ cy
+ .findByTestId(selector)
+ .should('exist')
+ .get('[data-testid=va-radio-option]')
+ .eq(index)
+ .click();
+
+export const selectDropdown = (selector, shortName, option) =>
+ cy
+ .findByTestId(selector)
+ .shadow()
+ .get(`select[name=${shortName}_dropdown]`)
+ .select(option, { force: true });
+
+export const clickBack = () =>
+ cy
+ .findByTestId('duw-buttonPair')
+ .shadow()
+ .get('va-button')
+ .first()
+ .should('be.visible')
+ .click();
+
+export const clickContinue = () =>
+ cy
+ .findByTestId('duw-buttonPair')
+ .shadow()
+ .get('va-button')
+ .eq(1)
+ .should('be.visible')
+ .click();
diff --git a/src/applications/discharge-wizard/tests/v2/display-logic.unit.spec.js b/src/applications/discharge-wizard/tests/v2/display-logic.unit.spec.js
index be557a29282d..dded20f127cb 100644
--- a/src/applications/discharge-wizard/tests/v2/display-logic.unit.spec.js
+++ b/src/applications/discharge-wizard/tests/v2/display-logic.unit.spec.js
@@ -7,14 +7,14 @@ import { RESPONSES, SHORT_NAME_MAP } from '../../constants/question-data-map';
describe('utilities: display logic', () => {
describe('navigateForward', () => {
describe('routing to discharge year', () => {
- const formValue = RESPONSES.ARMY;
+ const formResponses = { SERVICE_BRANCH: RESPONSES.ARMY };
const router = {
push: sinon.spy(),
};
it('SERVICE_BRANCH: should correctly route to the next question', () => {
- navigateForward(SHORT_NAME_MAP.SERVICE_BRANCH, formValue, router);
+ navigateForward(SHORT_NAME_MAP.SERVICE_BRANCH, formResponses, router);
expect(router.push.firstCall.calledWith(ROUTES.DISCHARGE_YEAR)).to.be
.true;
});
diff --git a/src/applications/discharge-wizard/utilities/display-logic-questions.js b/src/applications/discharge-wizard/utilities/display-logic-questions.js
index 09dbefb5ba0e..dc98449b7bb6 100644
--- a/src/applications/discharge-wizard/utilities/display-logic-questions.js
+++ b/src/applications/discharge-wizard/utilities/display-logic-questions.js
@@ -1,25 +1,44 @@
-import { ROUTES } from '../constants';
+import { DISPLAY_CONDITIONS } from '../constants/display-conditions';
import { SHORT_NAME_MAP } from '../constants/question-data-map';
-export const nextQuestionRoute = (currentQuestion, answer) => {
- let nextRoute;
+/** ================================================================
+ * Make a roadmap (in display order) of SHORT_NAMEs that display in the flow
+ *
+ */
+export const makeRoadmap = () => {
+ return Object.keys(SHORT_NAME_MAP);
+};
+
+/** ================================================================
+ * Check form responses to see if they match the requirements in DISPLAY_CONDITIONS
+ *
+ * @param {array} requiredResponses Example: [NO, NOT_SURE]
+ * @param {string} formResponse - answer in the store
+ */
+export const responseMatchesRequired = (requiredResponses, formResponse) => {
+ return requiredResponses?.includes(formResponse);
+};
+
+/** ================================================================
+ * Function for evaluating whether a question should display
+ *
+ * @param {string} SHORT_NAME - name for the current question
+ * @param {object} formResponses - all answers in the store
+ */
+export const displayConditionsMet = (SHORT_NAME, formResponses) => {
+ const displayConditionsForShortName = DISPLAY_CONDITIONS[SHORT_NAME];
+ const questionRequirements = Object.keys(displayConditionsForShortName);
+
+ for (const questionShortName of questionRequirements) {
+ const formResponse = formResponses?.[questionShortName];
+ const requiredResponses = displayConditionsForShortName[questionShortName];
- switch (currentQuestion) {
- case SHORT_NAME_MAP.SERVICE_BRANCH:
- nextRoute = SHORT_NAME_MAP.DISCHARGE_YEAR;
- break;
- case SHORT_NAME_MAP.DISCHARGE_YEAR:
- if (answer === `${new Date().getFullYear() - 15}`) {
- nextRoute = SHORT_NAME_MAP.DISCHARGE_MONTH;
- } else {
- nextRoute = SHORT_NAME_MAP.DISCHARGE_REASON;
- }
- break;
- case SHORT_NAME_MAP.DISCHARGE_MONTH:
- nextRoute = SHORT_NAME_MAP.DISCHARGE_REASON;
- break;
- default:
- return ROUTES.RESULTS;
+ if (
+ !responseMatchesRequired(requiredResponses, formResponse) &&
+ requiredResponses.length // This is for display conditions that can be any value ex: branch of service, year, month
+ ) {
+ return false;
+ }
}
- return nextRoute;
+ return true;
};
diff --git a/src/applications/discharge-wizard/utilities/page-navigation.js b/src/applications/discharge-wizard/utilities/page-navigation.js
index ebe108667f5b..cd13a893e6ea 100644
--- a/src/applications/discharge-wizard/utilities/page-navigation.js
+++ b/src/applications/discharge-wizard/utilities/page-navigation.js
@@ -1,12 +1,57 @@
-import { nextQuestionRoute } from './display-logic-questions';
-import { pushToRoute } from './shared';
-
-export const navigateForward = (SHORT_NAME, formValue, router) => {
- const nextRoute = nextQuestionRoute(SHORT_NAME, formValue);
-
- pushToRoute(nextRoute, router);
-};
+import { DISPLAY_CONDITIONS } from '../constants/display-conditions';
+import { displayConditionsMet, makeRoadmap } from './display-logic-questions';
+import { printErrorMessage, pushToRoute } from './shared';
export const navigateBackward = router => {
router.goBack();
};
+
+/** ================================================================
+ * Responsible for determining next question in flow, or redirecting to a results screen
+ *
+ * @param {string} SHORT_NAME - name for the current question
+ * @param {object} formResponses - all answers in the store
+ */
+export const navigateForward = (SHORT_NAME, formResponses, router) => {
+ const roadmap = makeRoadmap();
+
+ if (roadmap?.length) {
+ const CURRENT_INDEX = roadmap?.indexOf(SHORT_NAME);
+ const END_INDEX = roadmap?.length - 1;
+ let nextIndex = CURRENT_INDEX + 1;
+
+ if (CURRENT_INDEX === END_INDEX) {
+ // Results logic
+
+ return;
+ }
+
+ while (CURRENT_INDEX !== END_INDEX) {
+ const nextShortName = roadmap?.[nextIndex];
+
+ if (nextIndex > END_INDEX) {
+ // No questions after this one in the flow have their display conditions met
+ // Most likely a results page should show
+
+ // Results logic
+ return;
+ }
+
+ if (DISPLAY_CONDITIONS?.[nextShortName]) {
+ // Found entry in DISPLAY_CONDITIONS for next question
+ if (displayConditionsMet(nextShortName, formResponses)) {
+ pushToRoute(nextShortName, router);
+ return;
+ }
+
+ nextIndex += 1;
+ } else {
+ // No entry in DISPLAY_CONDITIONS for next question
+ printErrorMessage('Unable to determine next question to display');
+ return;
+ }
+ }
+ } else {
+ printErrorMessage('Unable to determine flow');
+ }
+};
diff --git a/src/applications/discharge-wizard/utilities/page-setup.js b/src/applications/discharge-wizard/utilities/page-setup.js
index 95fbba878a8d..83dde57d7537 100644
--- a/src/applications/discharge-wizard/utilities/page-setup.js
+++ b/src/applications/discharge-wizard/utilities/page-setup.js
@@ -53,7 +53,6 @@ export const pageSetup = H1 => {
export const applyErrorFocus = id => {
const element = document.getElementById(id);
- // focusElement(element)
const tabindex = element.getAttribute('tabindex');
if (element.tabIndex !== 0) {
element.setAttribute('tabindex', '-1');