Skip to content

Commit

Permalink
MCR-3826 ensuring Q&A sidenav renders where expected (#2252)
Browse files Browse the repository at this point in the history
* added testing to verify presence of sidenav on submission summary page

* adding form page routes to sidenav

* moved top level edit route into sidenav route

* removed redirect logic causing endless loop, adjusted logic in isSelectedLink func to handle all edit form pages, side nav is now present and functional across all edit form pages, just needs a touch of styling

* Address Sidenav crash and style bug

* removed tests we no longer need

* The sideNav should not be visible to a state user if the submission is a draft that has never been submitted

* cypress re-run

* adding fetch to cypress test

* cypress fixes

---------

Co-authored-by: Hana Worku <hana@truss.works>
  • Loading branch information
ruizajtruss and haworku authored Feb 20, 2024
1 parent 6316a7e commit e7d21ed
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 132 deletions.
6 changes: 6 additions & 0 deletions services/app-web/src/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ const STATE_SUBMISSION_SUMMARY_ROUTES: RouteTWithUnknown[] = [
const QUESTION_RESPONSE_SHOW_SIDEBAR_ROUTES: RouteTWithUnknown[] = [
'SUBMISSIONS_QUESTIONS_AND_ANSWERS',
'SUBMISSIONS_SUMMARY',
'SUBMISSIONS_TYPE',
'SUBMISSIONS_CONTRACT_DETAILS',
'SUBMISSIONS_RATE_DETAILS',
'SUBMISSIONS_CONTACTS',
'SUBMISSIONS_DOCUMENTS',
'SUBMISSIONS_REVIEW_SUBMIT',
]

/*
Expand Down
8 changes: 4 additions & 4 deletions services/app-web/src/pages/App/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ const StateUserRoutes = ({
path={RoutesRecord.SUBMISSIONS_SUMMARY}
element={<SubmissionSummary />}
/>
<Route
path={RoutesRecord.SUBMISSIONS_EDIT_TOP_LEVEL}
element={<StateSubmissionForm />}
/>
</Route>
<Route
path={RoutesRecord.SUBMISSIONS_REVISION}
element={<SubmissionRevisionSummary />}
/>
<Route
path={RoutesRecord.SUBMISSIONS_EDIT_TOP_LEVEL}
element={<StateSubmissionForm />}
/>
{UniversalRoutes}
{stageName !== 'prod' && (
<Route
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export const StateSubmissionForm = (): React.ReactElement => {
latestRevision.unlockInfo || undefined

return (
<>
<div>
<div className={styles.stepIndicator}>
<DynamicStepIndicator
formPages={activeFormPages(formDataFromLatestRevision)}
Expand Down Expand Up @@ -334,6 +334,6 @@ export const StateSubmissionForm = (): React.ReactElement => {
<Route path="*" element={<Error404 />} />
</Routes>
</FormContainer>
</>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
mockDraftHealthPlanPackage,
mockQuestionsPayload,
mockSubmittedHealthPlanPackage,
mockUnlockedHealthPlanPackage,
mockValidCMSUser,
} from '../../testHelpers/apolloMocks'

Expand Down Expand Up @@ -360,98 +359,6 @@ describe('SubmissionSideNav', () => {
expect(await screen.findByText('System error')).toBeInTheDocument()
})

it('DRAFT redirects a state user to beginning of form', async () => {
let testLocation: Location
const pkg = mockDraftHealthPlanPackage()

renderWithProviders(
<Routes>
<Route element={<SubmissionSideNav />}>
<Route
path={
RoutesRecord.SUBMISSIONS_QUESTIONS_AND_ANSWERS
}
element={<QuestionResponse />}
/>
<Route
path={RoutesRecord.SUBMISSIONS_SUMMARY}
element={<SubmissionSummary />}
/>
</Route>
</Routes>,
{
apolloProvider: {
mocks: [
fetchCurrentUserMock({
statusCode: 200,
}),
fetchStateHealthPlanPackageWithQuestionsMockSuccess(
{
id: '15',
stateSubmission: pkg,
}
),
],
},
routerProvider: {
route: '/submissions/15',
},
location: (location) => (testLocation = location),
featureFlags: { 'cms-questions': true },
}
)

await waitFor(() =>
expect(testLocation.pathname).toBe(`/submissions/15/edit/type`)
)
})

it('UNLOCKED redirects a state user to beginning of form', async () => {
let testLocation: Location
const pkg = mockUnlockedHealthPlanPackage()

renderWithProviders(
<Routes>
<Route element={<SubmissionSideNav />}>
<Route
path={
RoutesRecord.SUBMISSIONS_QUESTIONS_AND_ANSWERS
}
element={<QuestionResponse />}
/>
<Route
path={RoutesRecord.SUBMISSIONS_SUMMARY}
element={<SubmissionSummary />}
/>
</Route>
</Routes>,
{
apolloProvider: {
mocks: [
fetchCurrentUserMock({
statusCode: 200,
}),
fetchStateHealthPlanPackageWithQuestionsMockSuccess(
{
id: '15',
stateSubmission: pkg,
}
),
],
},
routerProvider: {
route: '/submissions/15',
},
location: (location) => (testLocation = location),
featureFlags: { 'cms-questions': true },
}
)

await waitFor(() =>
expect(testLocation.pathname).toBe(`/submissions/15/edit/type`)
)
})

it('DRAFT displays an error to a CMS user', async () => {
const pkg = mockDraftHealthPlanPackage()

Expand Down
62 changes: 39 additions & 23 deletions services/app-web/src/pages/SubmissionSideNav/SubmissionSideNav.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Link, SideNav, GridContainer, Icon } from '@trussworks/react-uswds'
import { NavLink } from 'react-router-dom'
import styles from './SubmissionSideNav.module.scss'
import { useParams, useLocation, useNavigate, Outlet } from 'react-router-dom'
import { useParams, useLocation, Outlet } from 'react-router-dom'
import { useAuth } from '../../contexts/AuthContext'
import {
QUESTION_RESPONSE_SHOW_SIDEBAR_ROUTES,
RouteT,
RoutesRecord,
STATE_SUBMISSION_FORM_ROUTES,
} from '../../constants/routes'
import { getRouteName } from '../../routeHelpers'
import { useFetchHealthPlanPackageWithQuestionsWrapper } from '../../gqlHelpers'
Expand Down Expand Up @@ -54,7 +54,6 @@ export const SubmissionSideNav = () => {
}
const { loggedInUser } = useAuth()
const { pathname } = useLocation()
const navigate = useNavigate()
const ldClient = useLDClient()

const routeName = getRouteName(pathname)
Expand All @@ -64,11 +63,13 @@ export const SubmissionSideNav = () => {
featureFlags.CMS_QUESTIONS.defaultValue
)

const showSidebar =
showQuestionResponse &&
QUESTION_RESPONSE_SHOW_SIDEBAR_ROUTES.includes(routeName)
const isSelectedLink = (route: RouteT): string => {
return routeName === route ? 'usa-current' : ''
const isSelectedLink = (route: string | string[]): string => {
//We pass an array of the form routes in order to display the sideNav on all of the pages
if (typeof route != 'string') {
return route.includes(routeName) ? 'usa-current' : ''
} else {
return routeName === route ? 'usa-current' : ''
}
}

const { result: fetchResult } =
Expand Down Expand Up @@ -107,7 +108,15 @@ export const SubmissionSideNav = () => {

const submissionStatus = pkg.status

//The sideNav should not be visible to a state user if the submission is a draft that has never been submitted
const showSidebar =
showQuestionResponse &&
submissionStatus !== 'DRAFT' &&
pkg.initiallySubmittedAt !== null &&
QUESTION_RESPONSE_SHOW_SIDEBAR_ROUTES.includes(routeName)

const isCMSUser = loggedInUser?.role === 'CMS_USER'
const isStateUser = loggedInUser?.role === 'STATE_USER'
const isAdminUser = loggedInUser?.role === 'ADMIN_USER'
const isHelpdeskUser = loggedInUser?.role === 'HELPDESK_USER'
const isBusinessOwnerUser = loggedInUser?.role === 'BUSINESSOWNER_USER'
Expand All @@ -120,19 +129,14 @@ export const SubmissionSideNav = () => {
return <GenericErrorPage />
}

// State users should not see the submission summary page for DRAFT or UNLOCKED, it should redirect them to the edit flow.
if (
!(isCMSUser || isAdminUser || isHelpdeskUser || isBusinessOwnerUser) &&
(submissionStatus === 'DRAFT' || submissionStatus === 'UNLOCKED')
) {
navigate(`/submissions/${id}/edit/type`)
}

// Current Revision is the last SUBMITTED revision, SubmissionSummary doesn't display data that is currently being edited
// Since we've already bounced on DRAFT packages, this _should_ exist.
const edge = pkg.revisions.find((rEdge) => rEdge.node.submitInfo)
// Current Revision is either the last submitted revision (cms users) or the most recent revision (for state users looking submission form)
const edge =
(submissionStatus === 'UNLOCKED' || submissionStatus === 'DRAFT') &&
loggedInUser.role === 'STATE_USER'
? pkg.revisions[0]
: pkg.revisions.find((rEdge) => rEdge.node.submitInfo)
if (!edge) {
const errMsg = `No currently submitted revision for this package: ${pkg.id}, programming error. `
const errMsg = `Not able to determine current revision for sidebar: ${pkg.id}, programming error.`
recordJSException(errMsg)
return <GenericErrorPage />
}
Expand All @@ -159,6 +163,7 @@ export const SubmissionSideNav = () => {
className={
showSidebar ? styles.backgroundSidebar : styles.backgroundForm
}
data-testid="submission-side-nav"
>
<GridContainer className={styles.container}>
{showSidebar && (
Expand All @@ -182,13 +187,24 @@ export const SubmissionSideNav = () => {
<SideNav
items={[
<Link
to={`/submissions/${id}`}
to={
isStateUser &&
submissionStatus === 'UNLOCKED'
? `/submissions/${id}/edit/review-and-submit`
: `/submissions/${id}`
}
asCustom={NavLink}
className={isSelectedLink(
'SUBMISSIONS_SUMMARY'
isStateUser &&
submissionStatus === 'UNLOCKED'
? STATE_SUBMISSION_FORM_ROUTES
: 'SUBMISSIONS_SUMMARY'
)}
>
Submission summary
{isStateUser &&
submissionStatus === 'UNLOCKED'
? 'Submission'
: 'Submission summary'}
</Link>,
<Link
to={`/submissions/${id}/question-and-answers`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
mockValidUser,
mockStateSubmission,
mockSubmittedHealthPlanPackage,
mockValidStateUser,
} from '../../testHelpers/apolloMocks'
import { renderWithProviders } from '../../testHelpers/jestHelpers'
import { SubmissionSummary } from './SubmissionSummary'
Expand Down Expand Up @@ -433,6 +434,72 @@ describe('SubmissionSummary', () => {
).toBeInTheDocument()
})

it('renders the sidenav for CMS users', async () => {
renderWithProviders(
<Routes>
<Route element={<SubmissionSideNav />}>
<Route
path={RoutesRecord.SUBMISSIONS_SUMMARY}
element={<SubmissionSummary />}
/>
</Route>
</Routes>,
{
apolloProvider: {
mocks: [
fetchCurrentUserMock({
user: mockValidCMSUser(),
statusCode: 200,
}),
fetchStateHealthPlanPackageWithQuestionsMockSuccess({
id: '1337',
}),
],
},
routerProvider: {
route: '/submissions/1337',
},
}
)

expect(
await screen.findByTestId('submission-side-nav')
).toBeInTheDocument()
})

it('renders the sidenav for State users', async () => {
renderWithProviders(
<Routes>
<Route element={<SubmissionSideNav />}>
<Route
path={RoutesRecord.SUBMISSIONS_SUMMARY}
element={<SubmissionSummary />}
/>
</Route>
</Routes>,
{
apolloProvider: {
mocks: [
fetchCurrentUserMock({
user: mockValidStateUser(),
statusCode: 200,
}),
fetchStateHealthPlanPackageWithQuestionsMockSuccess({
id: '1337',
}),
],
},
routerProvider: {
route: '/submissions/1337',
},
}
)

expect(
await screen.findByTestId('submission-side-nav')
).toBeInTheDocument()
})

describe('Submission package data display', () => {
it('renders the OLD data for an unlocked submission for CMS user, ignoring unsubmitted changes from state user', async () => {
const pkg = mockUnlockedHealthPlanPackage()
Expand Down
12 changes: 2 additions & 10 deletions services/cypress/support/navigateCommands.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { aliasQuery, aliasMutation } from '../utils/graphql-test-utils'

type FormButtonKey =
| 'CONTINUE_FROM_START_NEW'
| 'CONTINUE'
Expand All @@ -13,8 +11,6 @@ const buttonsWithLabels: FormButtons = {
BACK: 'Back',
}

const isSubmissionEditUrl = /submissions\/([0-9a-fA-F-]+)\/edit/

Cypress.Commands.add(
'navigateFormByButtonClick',
(buttonKey: FormButtonKey, waitForLoad = true) => {
Expand All @@ -34,7 +30,7 @@ Cypress.Commands.add(
} else if (buttonKey === 'CONTINUE_FROM_START_NEW') {
if (waitForLoad) {
cy.wait('@createHealthPlanPackageMutation', { timeout: 50_000 })
cy.wait('@fetchHealthPlanPackageQuery')
cy.wait('@fetchHealthPlanPackageWithQuestionsQuery')
}
cy.findByTestId('state-submission-form-page').should('exist')
} else if (buttonKey === 'CONTINUE') {
Expand All @@ -54,11 +50,7 @@ Cypress.Commands.add(
(url: string, waitForLoad = true) => {
cy.visit(url)
if (waitForLoad) {
if(isSubmissionEditUrl.test(url)) {
cy.wait('@fetchHealthPlanPackageQuery', { timeout: 50_000 })
} else {
cy.wait('@fetchHealthPlanPackageWithQuestionsQuery', { timeout: 50_000 })
}
cy.wait('@fetchHealthPlanPackageWithQuestionsQuery', { timeout: 50_000 })
}
}
)

0 comments on commit e7d21ed

Please sign in to comment.