diff --git a/services/app-web/src/components/Banner/DocumentWarningBanner/DocumentWarningBanner.tsx b/services/app-web/src/components/Banner/DocumentWarningBanner/DocumentWarningBanner.tsx index 01de757041..802ac72c71 100644 --- a/services/app-web/src/components/Banner/DocumentWarningBanner/DocumentWarningBanner.tsx +++ b/services/app-web/src/components/Banner/DocumentWarningBanner/DocumentWarningBanner.tsx @@ -1,13 +1,13 @@ import React, { useEffect } from 'react' import { Alert } from '@trussworks/react-uswds' -import { useStringConstants } from '../../../hooks/useStringConstants' + import classnames from 'classnames' import { useTealium } from '../../../hooks' +import { ContactSupportLink } from '../../ErrorAlert/ContactSupportLink' export const DocumentWarningBanner = ({ className, }: React.HTMLAttributes): React.ReactElement => { - const stringConstants = useStringConstants() const { logAlertImpressionEvent } = useTealium() useEffect(() => { @@ -20,7 +20,6 @@ export const DocumentWarningBanner = ({ }) }, [logAlertImpressionEvent]) - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT return ( - - email the help desk. - + ) } diff --git a/services/app-web/src/components/Banner/GenericApiErrorBanner/GenericApiErrorBanner.tsx b/services/app-web/src/components/Banner/GenericApiErrorBanner/GenericApiErrorBanner.tsx index 6a04b47913..7eacd9ddbc 100644 --- a/services/app-web/src/components/Banner/GenericApiErrorBanner/GenericApiErrorBanner.tsx +++ b/services/app-web/src/components/Banner/GenericApiErrorBanner/GenericApiErrorBanner.tsx @@ -1,70 +1,22 @@ -import React, { useEffect } from 'react' -import styles from '../Banner.module.scss' -import { Alert } from '@trussworks/react-uswds' -import { ERROR_MESSAGES } from '../../../constants/errors' -import { useStringConstants } from '../../../hooks/useStringConstants' -import { LinkWithLogging } from '../../TealiumLogging/Link' -import { useTealium } from '../../../hooks' +import React from 'react' +import { ErrorAlertFailedRequest } from '../../ErrorAlert' +import { ErrorAlertValidationError } from '../../ErrorAlert/ErrorAlertValidationError' export type GenericApiErrorProps = { heading?: string message?: string - suggestion?: string + validationFail?: boolean } export const GenericApiErrorBanner = ({ heading, message, - suggestion, + validationFail = false, }: GenericApiErrorProps): React.ReactElement => { - const stringConstants = useStringConstants() - const { logAlertImpressionEvent } = useTealium() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT - - useEffect(() => { - logAlertImpressionEvent({ - error_type: 'system', - error_message: - 'Please refresh your browser and if you continue to experience an error let us know.', - type: 'error', - extension: 'react-uswds', - }) - }, [logAlertImpressionEvent]) - + if (validationFail){ + return + } return ( - -
-

- {message || ERROR_MESSAGES.generic_error} -

-

- {suggestion ? ( - {suggestion} - ) : ( - <> - - Please refresh your browser and if you continue - to experience an error,  - - - let us know. - - - )} -

-
-
+ ) } diff --git a/services/app-web/src/components/ErrorAlert/ContactSupportLink.tsx b/services/app-web/src/components/ErrorAlert/ContactSupportLink.tsx new file mode 100644 index 0000000000..7d135e3b83 --- /dev/null +++ b/services/app-web/src/components/ErrorAlert/ContactSupportLink.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { useStringConstants } from '../../hooks/useStringConstants' +import { LinkWithLogging } from '../TealiumLogging/Link' + +type ContactSupportLinkProps = { + alternateText?: string + className?: string +} + +export const ContactSupportLink = ({ + alternateText, + className +}: ContactSupportLinkProps): React.ReactElement => { + const stringConstants = useStringConstants() + const displayText = alternateText?? 'email the help desk' + return ( + + {displayText} + + ) +} diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlert.stories.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlert.stories.tsx index 88f01aa707..ed780f8ad2 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlert.stories.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlert.stories.tsx @@ -4,6 +4,8 @@ import { ErrorAlertFailedRequest } from './ErrorAlertFailedRequest' import { ErrorAlertSessionExpired } from './ErrorAlertSessionExpired' import { ErrorAlertSignIn } from './ErrorAlertSignIn' import { ErrorAlertSiteUnavailable } from './ErrorAlertSiteUnavailable' +import { ErrorAlertScheduledMaintenance } from './ErrorAlertScheduledMaintenance' +import { ErrorAlertValidationError } from './ErrorAlertValidationError' export default { title: 'Components/ErrorAlert', @@ -14,19 +16,21 @@ const Template: StoryFn = (args) => export const Default = Template.bind({}) -export const CustomStylesWithLetUsKnowLink = Template.bind({}) -CustomStylesWithLetUsKnowLink.args = { +export const CustomStylesWithContactSupportLink = Template.bind({}) +CustomStylesWithContactSupportLink.args = { message: - 'Here is an error alert with extra padding and a light gray background. If you see anything odd,', + 'Here is an error alert with extra padding and a light gray background.', style: { backgroundColor: '#F0F0F0', padding: '2em' }, - appendLetUsKnow: true, + remediation: 'DEFAULT' } // List of application context-specific error alert components for quick reference. export const ListOfApplicationErrorAlerts = (): React.ReactElement => (
+ +
diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlert.test.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlert.test.tsx index d05745ae78..685ba99920 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlert.test.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlert.test.tsx @@ -1,6 +1,7 @@ import { screen } from '@testing-library/react' import { ErrorAlert } from './ErrorAlert' import { renderWithProviders } from '../../testHelpers' +import { useStringConstants } from '../../hooks/useStringConstants' test('renders default content when no props present', () => { renderWithProviders() @@ -31,6 +32,9 @@ test('renders custom message', async () => { expect( screen.queryByText("We're having trouble loading this page.") ).toBeNull() + expect( + screen.getByText(/Something else went wrong/) + ).not.toHaveStyle('font-weight: bold') }) test('renders with custom styles', async () => { @@ -41,3 +45,26 @@ test('renders with custom styles', async () => { await expect(screen.getByText(testText)).toBeInTheDocument() expect(screen.queryByTestId('error-alert')).toHaveClass('test-class') }) +test('displays email support link mailto link with default remediation', () =>{ + const stringConstants = useStringConstants() + renderWithProviders( + ) + const feedbackLink = screen.getByRole('link', { + name: `email the help desk`, + }) + expect(feedbackLink).toHaveAttribute( + 'href', + stringConstants.MAIL_TO_SUPPORT_HREF + ) +}) + +test('displays message with bold text when withEmphasis is used', () =>{ + renderWithProviders( + ) + expect( + screen.queryByText("We're having trouble loading this page.") + ).toHaveStyle('font-weight: bold') + expect( + screen.queryByText("email the help desk") + ).not.toHaveStyle('font-weight: bold') +}) \ No newline at end of file diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlert.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlert.tsx index b3ad253c4b..28447521a7 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlert.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlert.tsx @@ -2,42 +2,49 @@ import classnames from 'classnames' import React, { useEffect } from 'react' import styles from './ErrorAlert.module.scss' import { Alert } from '@trussworks/react-uswds' -import { useStringConstants } from '../../hooks/useStringConstants' -import { LinkWithLogging } from '../TealiumLogging/Link' import { useTealium } from '../../hooks' import { extractText } from '../TealiumLogging/tealiamLoggingHelpers' +import { ErrorRemediation, RemediationType } from './ErrorRemediations' export type ErrorAlertProps = { - message?: React.ReactNode - heading?: string - calltoAction?: React.ReactNode - appendLetUsKnow?: boolean + heading?: string // Has a default for generic error + message?: React.ReactNode // Has a default for generic error. + withEmphasis?: boolean + remediation?: RemediationType } & React.JSX.IntrinsicElements['div'] +/* + Error alert is main error display in the application. + It is used for variety of purposes including API error handling and displaying full page messages during maintainece. + + A heading and a message is always displayed with fallbacks to a generic system error. + + An optional remediation message may displayed in a second paragraph. Remediation includes specific instructions about what the user can do to + fix the errors, such as refreshing page or contacting support. A mailto link to contact the help desk is often included in the remediation message as well. + + If the alert is displayed withEmphasis, the message is defined into two paragraphs, the first paragraph is displayed bold. +*/ + export const ErrorAlert = ({ - message, - heading, - appendLetUsKnow = false, + heading = 'System error', + message = "We're having trouble loading this page.", + remediation, + withEmphasis, className, ...divProps }: ErrorAlertProps): React.ReactElement => { - const stringConstants = useStringConstants() const { logAlertImpressionEvent } = useTealium() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT const classes = classnames(styles.messageBodyText, className) - const showLink = appendLetUsKnow || !message // our default message includes the link - const defaultMessage = - "We're having trouble loading this page. Please refresh your browser and if you continue to experience an error," - const logErrorMessage = `${message ? extractText(message) : defaultMessage} email ${MAIL_TO_SUPPORT}` + const loggingErrorMessage = extractText(message) useEffect(() => { logAlertImpressionEvent({ error_type: 'system', - error_message: logErrorMessage, + error_message: loggingErrorMessage, type: 'error', extension: 'react-uswds', }) - }, [logAlertImpressionEvent, logErrorMessage]) + }, [loggingErrorMessage, logAlertImpressionEvent]) return ( - {message || defaultMessage} - - {showLink && ( - -  email{' '} - - {MAIL_TO_SUPPORT} - - - )} +
+ {withEmphasis ? ( + <> +

+ {message} +

+

+ +

+ + ) : ( +

+ {message}  + +

+ )} +
) } diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlertFailedRequest.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlertFailedRequest.tsx index 1148279572..503f4567ff 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlertFailedRequest.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlertFailedRequest.tsx @@ -1,62 +1,27 @@ -import React, { useEffect } from 'react' -import styles from './ErrorAlert.module.scss' -import { Alert } from '@trussworks/react-uswds' -import { useStringConstants } from '../../hooks/useStringConstants' -import { LinkWithLogging } from '../TealiumLogging/Link' -import { useTealium } from '../../hooks' +import React from 'react' + +import { ErrorAlert } from './ErrorAlert' +import { RemediationType } from './ErrorRemediations' export type ErrorAlertFailedRequestProps = { message?: string heading?: string + remediation?: RemediationType } -// TODO: Refactor to use Error Alert and switchover components using GenericApiErrorBanner to use this +// These API alerts are away displayed with emphasis and always have a remediation step +// default remediation is to refresh and retry the request export const ErrorAlertFailedRequest = ({ heading, message, + remediation = 'DEFAULT' }: ErrorAlertFailedRequestProps): React.ReactElement => { - const stringConstants = useStringConstants() - const { logAlertImpressionEvent } = useTealium() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT - - useEffect(() => { - logAlertImpressionEvent({ - error_type: 'system', - error_message: message ?? "We're having trouble loading this page.", - type: 'error', - extension: 'react-uswds', - }) - }, [logAlertImpressionEvent, message]) return ( - -
-

- - {message || "We're having trouble loading this page."} - -

-

- - Please refresh your browser and if you continue to - experience an error,  - - - let us know. - -

-
-
+ ) } diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlertScheduledMaintenance.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlertScheduledMaintenance.tsx index 0e7f680980..66b05bc954 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlertScheduledMaintenance.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlertScheduledMaintenance.tsx @@ -4,9 +4,7 @@ import { ErrorAlert } from './ErrorAlert' export const ErrorAlertScheduledMaintenance = (): React.ReactElement => ( ) diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlertSignIn.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlertSignIn.tsx index 9a88239467..80a0bbed3d 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlertSignIn.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlertSignIn.tsx @@ -4,7 +4,7 @@ import { ErrorAlert } from './ErrorAlert' export const ErrorAlertSignIn = (): React.ReactElement => ( ) diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlertSiteUnavailable.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlertSiteUnavailable.tsx index b2858c0349..64a431fcae 100644 --- a/services/app-web/src/components/ErrorAlert/ErrorAlertSiteUnavailable.tsx +++ b/services/app-web/src/components/ErrorAlert/ErrorAlertSiteUnavailable.tsx @@ -4,10 +4,7 @@ import { ErrorAlert } from './ErrorAlert' export const ErrorAlertSiteUnavailable = (): React.ReactElement => ( ) diff --git a/services/app-web/src/components/ErrorAlert/ErrorAlertValidationError.tsx b/services/app-web/src/components/ErrorAlert/ErrorAlertValidationError.tsx new file mode 100644 index 0000000000..84cb497b1c --- /dev/null +++ b/services/app-web/src/components/ErrorAlert/ErrorAlertValidationError.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import { ErrorAlertFailedRequest } from './ErrorAlertFailedRequest' + +export type ErrorAlertFailedRequestProps = { + message?: string + heading?: string +} + +export const ErrorAlertValidationError = ({ + heading = 'Missing required fields', + message = "We're having trouble completing this request.", +}: ErrorAlertFailedRequestProps): React.ReactElement => { + + return ( + + ) +} diff --git a/services/app-web/src/components/ErrorAlert/ErrorRemediations.tsx b/services/app-web/src/components/ErrorAlert/ErrorRemediations.tsx new file mode 100644 index 0000000000..cb70603030 --- /dev/null +++ b/services/app-web/src/components/ErrorAlert/ErrorRemediations.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { ContactSupportLink } from "./ContactSupportLink"; + +// These components are used to display remediation messages in ErrorAlert +// This is the second paragraph (which is optional) in the alert content + +const DefaultRemediation = (): React.ReactElement => ( +<> + +Please refresh your browser and if you continue to +experience an error,  + + . +) + +const SignInRemediation = (): React.ReactElement => ( + <> + + Please try to sign in again and if you continue to experience an error,  + + . + ) + +const TechnicalIssuesRemediation= (): React.ReactElement => ( + <> + + If you have questions or need immediate assistance with your submission, please,  + + . + ) + +const ValidationRemediation= (): React.ReactElement => ( + <> + + Please provide the required information before submitting. If you continue to see this message,  + + . + ) + +type RemediationType = 'DEFAULT' | 'TECH_ISSUE' | 'SIGNIN_ERROR' | 'VALIDATION_ERROR'; + +const ErrorRemediation = ({type} : {type: RemediationType | undefined}): React.ReactElement | null => { + switch(type){ + case 'DEFAULT': + return + case 'TECH_ISSUE': + return + case 'SIGNIN_ERROR': + return + case 'VALIDATION_ERROR': + return + default: + return null + } +} + + export {type RemediationType, ErrorRemediation} \ No newline at end of file diff --git a/services/app-web/src/components/Footer/Footer.tsx b/services/app-web/src/components/Footer/Footer.tsx index 9d1e6c8b67..de8aae2087 100644 --- a/services/app-web/src/components/Footer/Footer.tsx +++ b/services/app-web/src/components/Footer/Footer.tsx @@ -7,14 +7,13 @@ import { Logo } from '../Logo' import { GridContainer, Grid } from '@trussworks/react-uswds' import { useStringConstants } from '../../hooks/useStringConstants' import { useCurrentRoute } from '../../hooks/useCurrentRoute' -import { LinkWithLogging } from '../TealiumLogging/Link' +import { ContactSupportLink } from '../ErrorAlert/ContactSupportLink' /** * CMS Footer */ export const Footer = (): React.ReactElement => { const stringConstants = useStringConstants() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT const { currentRoute: route } = useCurrentRoute() return route !== 'GRAPHQL_EXPLORER' ? ( @@ -44,14 +43,7 @@ export const Footer = (): React.ReactElement => { Email  - - {MAIL_TO_SUPPORT} - +  to get help or send feedback 7500 Security Boulevard Baltimore, MD 21244 diff --git a/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.test.tsx b/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.test.tsx index 1cc5933df8..5559e85ecb 100644 --- a/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.test.tsx +++ b/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.test.tsx @@ -54,7 +54,6 @@ describe('UserLoginInfo', () => { it('renders link to support email', () => { const stringConstants = useStringConstants() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT const jestFn = vi.fn() renderWithProviders( @@ -67,11 +66,11 @@ describe('UserLoginInfo', () => { /> ) const feedbackLink = screen.getByRole('link', { - name: `${MAIL_TO_SUPPORT}`, + name: `${stringConstants.MAIL_TO_SUPPORT}`, }) expect(feedbackLink).toHaveAttribute( 'href', - `mailto: ${MAIL_TO_SUPPORT}, mc-review-team@truss.works` + stringConstants.MAIL_TO_SUPPORT_HREF ) }) diff --git a/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.tsx b/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.tsx index f8e3c94b0c..76f5a0feeb 100644 --- a/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.tsx +++ b/services/app-web/src/components/Header/UserLoginInfo/UserLoginInfo.tsx @@ -12,6 +12,7 @@ import { LinkWithLogging, ButtonWithLogging, } from '../../../components' +import { ContactSupportLink } from '../../ErrorAlert/ContactSupportLink' type LogoutHandlerT = ( e: React.MouseEvent @@ -22,18 +23,10 @@ const LoggedInUserInfo = ( logout: LogoutHandlerT ): React.ReactElement => { const stringConstants = useStringConstants() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT return (
Contact - - {MAIL_TO_SUPPORT} - + | {user.email} | diff --git a/services/app-web/src/components/Modal/Modal.tsx b/services/app-web/src/components/Modal/Modal.tsx index dd4856bb50..9fde5a5bae 100644 --- a/services/app-web/src/components/Modal/Modal.tsx +++ b/services/app-web/src/components/Modal/Modal.tsx @@ -84,7 +84,7 @@ export const Modal = ({ )}
{children}
diff --git a/services/app-web/src/components/Modal/V2/UnlockSubmitModalV2.tsx b/services/app-web/src/components/Modal/V2/UnlockSubmitModalV2.tsx index 2b39d4e654..d9579f58fa 100644 --- a/services/app-web/src/components/Modal/V2/UnlockSubmitModalV2.tsx +++ b/services/app-web/src/components/Modal/V2/UnlockSubmitModalV2.tsx @@ -246,11 +246,10 @@ export const UnlockSubmitModal = ({ heading: modalValues.errorHeading, message: result.message, // When we have generic/unknown errors override any suggestions and display the fallback "please refresh text" - suggestion: - result.message === ERROR_MESSAGES.submit_error_generic || - result.message === ERROR_MESSAGES.unlock_error_generic - ? undefined - : modalValues.errorSuggestion, + validationFail: + result.message === ERROR_MESSAGES.submit_missing_field + ? true + : false, }) } else { modalRef.current?.toggleModal(undefined, false) diff --git a/services/app-web/src/hooks/useStringConstants.ts b/services/app-web/src/hooks/useStringConstants.ts index feca971f96..04eef95dc0 100644 --- a/services/app-web/src/hooks/useStringConstants.ts +++ b/services/app-web/src/hooks/useStringConstants.ts @@ -1,7 +1,9 @@ export const useStringConstants = () => { // Keep this hook around, incase we need to feature flag any other copy changes. + const SUPPORT_ADDRESS = 'MC_Review_HelpDesk@cms.hhs.gov' return { - MAIL_TO_SUPPORT: 'MC_Review_HelpDesk@cms.hhs.gov', + MAIL_TO_SUPPORT: SUPPORT_ADDRESS, + MAIL_TO_SUPPORT_HREF: `mailto: ${SUPPORT_ADDRESS}, mc-review-team@truss.works`, } } diff --git a/services/app-web/src/pages/Errors/GenericErrorPage.tsx b/services/app-web/src/pages/Errors/GenericErrorPage.tsx index 90b73df6ef..1d053734f1 100644 --- a/services/app-web/src/pages/Errors/GenericErrorPage.tsx +++ b/services/app-web/src/pages/Errors/GenericErrorPage.tsx @@ -1,13 +1,11 @@ import React from 'react' -import { useStringConstants } from '../../hooks/useStringConstants' import styles from './Errors.module.scss' -import { PageHeading, LinkWithLogging } from '../../components' +import { PageHeading } from '../../components' import { GridContainer } from '@trussworks/react-uswds' +import { ContactSupportLink } from '../../components/ErrorAlert/ContactSupportLink' export const GenericErrorPage = (): React.ReactElement => { - const stringConstants = useStringConstants() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT return (
@@ -18,14 +16,7 @@ export const GenericErrorPage = (): React.ReactElement => { your browser and if you continue to experience an error,  - - let us know. - +

diff --git a/services/app-web/src/pages/QuestionResponse/QuestionResponse.test.tsx b/services/app-web/src/pages/QuestionResponse/QuestionResponse.test.tsx index 6d92b4afd8..3390310882 100644 --- a/services/app-web/src/pages/QuestionResponse/QuestionResponse.test.tsx +++ b/services/app-web/src/pages/QuestionResponse/QuestionResponse.test.tsx @@ -13,11 +13,56 @@ import { iterableCmsUsersMockData, } from '../../testHelpers/apolloMocks' import { IndexQuestionsPayload } from '../../gen/gqlClient' +import { useStringConstants } from '../../hooks/useStringConstants' describe('QuestionResponse', () => { describe.each(iterableCmsUsersMockData)( '$userRole QuestionResponse tests', ({ userRole, mockUser }) => { + it('render error if CMS user does not have division set', async () =>{ + const stringConstants = useStringConstants() + const user = mockUser({divisionAssignment: undefined}) + renderWithProviders( + + }> + } + /> + + , + { + apolloProvider: { + mocks: [ + fetchCurrentUserMock({ user, statusCode: 200}), + fetchStateHealthPlanPackageWithQuestionsMockSuccess( + { + id: '15', + questions: mockQuestionsPayload('15'), + } + ), + ], + }, + routerProvider: { + route: '/submissions/15/question-and-answers', + }, + } + ) + + expect(await screen.findByRole('heading', {name: 'Missing division'})).toBeInTheDocument() + const feedbackLink = screen.getByRole('link', { + name: `email the help desk`, + }) + expect(feedbackLink).toHaveAttribute( + 'href', + stringConstants.MAIL_TO_SUPPORT_HREF + ) + + + + }) it('renders expected questions correctly with rounds', async () => { const mockQuestions = mockQuestionsPayload('15') diff --git a/services/app-web/src/pages/QuestionResponse/QuestionResponse.tsx b/services/app-web/src/pages/QuestionResponse/QuestionResponse.tsx index 703cbbd499..f4fb9b55f2 100644 --- a/services/app-web/src/pages/QuestionResponse/QuestionResponse.tsx +++ b/services/app-web/src/pages/QuestionResponse/QuestionResponse.tsx @@ -20,6 +20,7 @@ import { CmsUser, QuestionEdge, StateUser } from '../../gen/gqlClient' import { useStringConstants } from '../../hooks/useStringConstants' import { GenericErrorPage } from '../Errors/GenericErrorPage' import { hasCMSUserPermissions } from '../../gqlHelpers' +import { ContactSupportLink } from '../../components/ErrorAlert/ContactSupportLink' type divisionQuestionDataType = { division: Division @@ -59,8 +60,6 @@ const getDivisionOrder = (division?: Division): Division[] => }) as Division[] export const QuestionResponse = () => { - const stringConstants = useStringConstants() - const MAIL_TO_SUPPORT = stringConstants.MAIL_TO_SUPPORT // router context const location = useLocation() const submitType = new URLSearchParams(location.search).get('submit') @@ -106,7 +105,6 @@ export const QuestionResponse = () => { ), }) ) - const mapQASections = () => questions.map((divisionQuestions) => (
{ ))}
)) - return (
@@ -136,16 +133,8 @@ export const QuestionResponse = () => { message={ You must be assigned to a division in order to - ask questions about a submission. Contact{' '} - - {MAIL_TO_SUPPORT} - {' '} - to add your division. + ask questions about a submission. Please  +  to add your division. } /> diff --git a/services/app-web/src/testHelpers/apolloMocks/questionResponseDataMocks.ts b/services/app-web/src/testHelpers/apolloMocks/questionResponseDataMocks.ts index 1a35d3e66f..805adffc69 100644 --- a/services/app-web/src/testHelpers/apolloMocks/questionResponseDataMocks.ts +++ b/services/app-web/src/testHelpers/apolloMocks/questionResponseDataMocks.ts @@ -14,7 +14,7 @@ function mockQuestionsPayload(contractID: string): IndexQuestionsPayload { contractID, createdAt: new Date('2022-12-15'), addedBy: mockValidCMSUser({ - divisionAssignment: 'DMCO', + divisionAssignment: undefined, }) as CmsUser, documents: [ { diff --git a/services/app-web/src/testHelpers/apolloMocks/userGQLMock.ts b/services/app-web/src/testHelpers/apolloMocks/userGQLMock.ts index feea8e89af..58fe897d88 100644 --- a/services/app-web/src/testHelpers/apolloMocks/userGQLMock.ts +++ b/services/app-web/src/testHelpers/apolloMocks/userGQLMock.ts @@ -13,7 +13,7 @@ import { import { mockMNState } from './stateMock' function mockValidUser(userData?: Partial): StateUser { - return { + return Object.assign({}, { __typename: 'StateUser' as const, id: 'foo-id', state: mockMNState(), @@ -21,8 +21,7 @@ function mockValidUser(userData?: Partial): StateUser { givenName: 'bob', familyName: 'ddmas', email: 'bob@dmas.mn.gov', - ...userData, - } + }, userData) } const mockValidStateUser = (userData?: Partial): StateUser => { @@ -30,7 +29,7 @@ const mockValidStateUser = (userData?: Partial): StateUser => { } function mockValidCMSUser(userData?: Partial): CmsUser { - return { + return Object.assign({}, { __typename: 'CMSUser' as const, id: 'bar-id', role: 'CMS_USER', @@ -39,12 +38,11 @@ function mockValidCMSUser(userData?: Partial): CmsUser { email: 'bob@dmas.mn.gov', divisionAssignment: 'DMCO', stateAssignments: [], - ...userData, - } + }, userData) } function mockValidCMSApproverUser(userData?: Partial): CmsApproverUser { - return { + return Object.assign({}, { __typename: 'CMSApproverUser' as const, id: 'bar-id', role: 'CMS_APPROVER_USER', @@ -54,23 +52,22 @@ function mockValidCMSApproverUser(userData?: Partial): CmsAppro divisionAssignment: 'DMCO', stateAssignments: [], ...userData, - } + }, userData) } function mockValidAdminUser(userData?: Partial): AdminUser { - return { + return Object.assign({}, { __typename: 'AdminUser' as const, id: 'bar-id', role: 'ADMIN_USER', givenName: 'bobadmin', familyName: 'ddmas', email: 'bobadmin@dmas.mn.gov', - ...userData, - } + }, userData) } function mockValidHelpDeskUser(userData?: Partial): HelpdeskUser { - return { + return Object.assign({}, { __typename: 'HelpdeskUser' as const, id: 'bar-id', role: 'HELPDESK_USER', @@ -78,7 +75,7 @@ function mockValidHelpDeskUser(userData?: Partial): HelpdeskUser { familyName: 'ddmas', email: 'bob@dmas.mn.gov', ...userData, - } + }, userData) } function mockValidBusinessOwnerUser(userData?: Partial): HelpdeskUser {