diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index fb70e1ec13fb..f0d945c2d30f 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -56,21 +56,21 @@ const ComposeForm = props => { const history = useHistory(); const [recipientsList, setRecipientsList] = useState(allowedRecipients); - const [selectedRecipient, setSelectedRecipient] = useState(null); + const [selectedRecipientId, setSelectedRecipientId] = useState(null); const [isSignatureRequired, setIsSignatureRequired] = useState(null); const [checkboxMarked, setCheckboxMarked] = useState(false); useEffect( () => { - if (selectedRecipient) { + if (selectedRecipientId) { setIsSignatureRequired( allowedRecipients.some( - r => +r.id === +selectedRecipient && r.signatureRequired, + r => +r.id === +selectedRecipientId && r.signatureRequired, ) || false, ); } }, - [selectedRecipient, allowedRecipients], + [selectedRecipientId, allowedRecipients], ); const [category, setCategory] = useState(null); const [categoryError, setCategoryError] = useState(''); @@ -87,8 +87,6 @@ const ComposeForm = props => { const [fieldsString, setFieldsString] = useState(''); const [sendMessageFlag, setSendMessageFlag] = useState(false); const [messageInvalid, setMessageInvalid] = useState(false); - const [signatureInvalid, setSignatureInvalid] = useState(false); - const [checkboxInvalid, setCheckboxInvalid] = useState(false); const [navigationError, setNavigationError] = useState(null); const [saveError, setSaveError] = useState(null); const [lastFocusableElement, setLastFocusableElement] = useState(null); @@ -110,7 +108,7 @@ const ComposeForm = props => { const debouncedMessageBody = useDebounce(messageBody, draftAutoSaveTimeout); const debouncedCategory = useDebounce(category, draftAutoSaveTimeout); const debouncedRecipient = useDebounce( - selectedRecipient, + selectedRecipientId, draftAutoSaveTimeout, ); const alertsList = useSelector(state => state.sm.alerts.alertList); @@ -249,7 +247,7 @@ const ComposeForm = props => { subject, }; messageData[`${'draft_id'}`] = draft?.messageId; - messageData[`${'recipient_id'}`] = selectedRecipient; + messageData[`${'recipient_id'}`] = selectedRecipientId; let sendData; if (attachments.length > 0) { @@ -277,14 +275,11 @@ const ComposeForm = props => { useEffect( () => { - if ( - messageInvalid || - (isSignatureRequired && (signatureInvalid || checkboxInvalid)) - ) { + if (messageInvalid) { focusOnErrorField(); } }, - [checkboxInvalid, isSignatureRequired, messageInvalid, signatureInvalid], + [messageInvalid], ); useEffect( @@ -306,7 +301,7 @@ const ComposeForm = props => { // Populates form fields with recipients and categories const populateForm = () => { if (recipientExists(draft.recipientId)) { - setSelectedRecipient(draft.recipientId); + setSelectedRecipientId(draft.recipientId); } else { const newRecipient = { id: draft?.recipientId, @@ -316,7 +311,7 @@ const ComposeForm = props => { ...prevRecipientsList, newRecipient, ]); - setSelectedRecipient(newRecipient.id); + setSelectedRecipientId(newRecipient.id); } setCategory(draft.category); setSubject(draft.subject); @@ -344,9 +339,9 @@ const ComposeForm = props => { let checkboxValid = true; if ( - selectedRecipient === '0' || - selectedRecipient === '' || - !selectedRecipient + selectedRecipientId === '0' || + selectedRecipientId === '' || + !selectedRecipientId ) { setRecipientError(ErrorMessages.ComposeForm.RECIPIENT_REQUIRED); messageValid = false; @@ -363,28 +358,20 @@ const ComposeForm = props => { setCategoryError(ErrorMessages.ComposeForm.CATEGORY_REQUIRED); messageValid = false; } - if ( - (isSignatureRequired && !electronicSignature) || - isSignatureRequired === null - ) { + if (isSignatureRequired && !electronicSignature) { setSignatureError(ErrorMessages.ComposeForm.SIGNATURE_REQUIRED); signatureValid = false; } - if ( - (isSignatureRequired && !checkboxMarked) || - isSignatureRequired === null - ) { + if (isSignatureRequired && !checkboxMarked) { setCheckboxError(ErrorMessages.ComposeForm.CHECKBOX_REQUIRED); checkboxValid = false; } setMessageInvalid(!messageValid); - setSignatureInvalid(!signatureValid); - setCheckboxInvalid(!checkboxValid); return { messageValid, signatureValid, checkboxValid }; }, [ - selectedRecipient, + selectedRecipientId, subject, messageBody, category, @@ -402,57 +389,64 @@ const ComposeForm = props => { signatureValid, checkboxValid, } = checkMessageValidity(); + const validSignatureNotRequired = + messageValid && !isSignatureRequired && !savedDraft; if (type === 'manual') { - setLastFocusableElement(e?.target); - - // if all checks are valid, then save the draft - if ( - (messageValid && !isSignatureRequired) || - (isSignatureRequired && signatureValid && checkboxValid && !saveError) - ) { + if (validSignatureNotRequired) { setNavigationError(null); setSavedDraft(true); - } else - setUnsavedNavigationError( - ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, - ); - - let errorType = null; - if ( - attachments.length > 0 && - isSignatureRequired && - electronicSignature !== '' - ) { - errorType = - ErrorMessages.ComposeForm - .UNABLE_TO_SAVE_DRAFT_SIGNATURE_OR_ATTACHMENTS; - } else if (attachments.length > 0) { - errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT; - } else if (isSignatureRequired && electronicSignature !== '') { - errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; - } else if (isSignatureRequired && checkboxError !== '') { - errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; - } + setLastFocusableElement(e?.target); + } else focusOnErrorField(); + setUnsavedNavigationError( + ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, + ); - if (errorType) { - setSaveError(errorType); - if ( - errorType.title !== - ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE.title - ) { - setNavigationError({ - ...errorType, - confirmButtonText: 'Continue editing', - cancelButtonText: 'Delete draft', - }); + const getErrorType = () => { + const hasAttachments = attachments.length > 0; + const hasValidSignature = + isSignatureRequired && electronicSignature !== ''; + const verifyAllFieldsAreValid = + (messageValid && + signatureValid && + checkboxValid && + isSignatureRequired) || + (!isSignatureRequired && messageValid); + + let errorType = null; + + if (hasAttachments && hasValidSignature && verifyAllFieldsAreValid) { + errorType = + ErrorMessages.ComposeForm + .UNABLE_TO_SAVE_DRAFT_SIGNATURE_OR_ATTACHMENTS; + } else if (hasAttachments && verifyAllFieldsAreValid) { + errorType = + ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT; + } else if (verifyAllFieldsAreValid) { + errorType = + ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; } - } + + if (errorType) { + setSaveError(errorType); + if ( + errorType.title !== + ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE.title + ) { + setNavigationError({ + ...errorType, + confirmButtonText: 'Continue editing', + cancelButtonText: 'Delete draft', + }); + } + } + }; + getErrorType(); } const draftId = draft && draft.messageId; const newFieldsString = JSON.stringify({ - rec: parseInt(debouncedRecipient || selectedRecipient, 10), + rec: parseInt(debouncedRecipient || selectedRecipientId, 10), cat: debouncedCategory || category, sub: debouncedSubject || subject, bod: debouncedMessageBody || messageBody, @@ -464,12 +458,11 @@ const ComposeForm = props => { setFieldsString(newFieldsString); const formData = { - recipientId: selectedRecipient, + recipientId: selectedRecipientId, category, subject, body: messageBody, }; - // saves the draft if all checks are valid or can save draft without signature if ( (messageValid && !isSignatureRequired) || (isSignatureRequired && messageValid && saveError !== null) @@ -479,9 +472,12 @@ const ComposeForm = props => { }, [ checkMessageValidity, + isSignatureRequired, + savedDraft, + saveError, draft, debouncedRecipient, - selectedRecipient, + selectedRecipientId, debouncedCategory, category, debouncedSubject, @@ -489,8 +485,7 @@ const ComposeForm = props => { debouncedMessageBody, messageBody, fieldsString, - isSignatureRequired, - saveError, + messageInvalid, setUnsavedNavigationError, attachments.length, electronicSignature, @@ -511,15 +506,16 @@ const ComposeForm = props => { await setMessageInvalid(false); await setSendMessageFlag(false); const validSignatureNotRequired = messageValid && !isSignatureRequired; - const validSignatureRequired = - isSignatureRequired && signatureValid && checkboxValid; + const isSignatureValid = + isSignatureRequired && messageValid && signatureValid && checkboxValid; - if (validSignatureNotRequired || validSignatureRequired) { + if (validSignatureNotRequired || isSignatureValid) { setSendMessageFlag(true); setNavigationError(null); setLastFocusableElement(e.target); } else { setSendMessageFlag(false); + focusOnErrorField(); } }, [checkMessageValidity, isSignatureRequired], @@ -530,29 +526,29 @@ const ComposeForm = props => { const isBlankForm = () => messageBody === '' && subject === '' && - (selectedRecipient === 0 || selectedRecipient === '0') && + Number(selectedRecipientId) === 0 && category === null && attachments.length === 0; const isSavedEdits = () => messageBody === draft?.body && - Number(selectedRecipient) === draft?.recipientId && + Number(selectedRecipientId) === draft?.recipientId && category === draft?.category && subject === draft?.subject; const isEditPopulatedForm = () => (messageBody !== draft?.body || - selectedRecipient !== draft?.recipientId || + selectedRecipientId !== draft?.recipientId || category !== draft?.category || subject !== draft?.subject) && !isBlankForm() && !isSavedEdits(); const unsavedDraft = isEditPopulatedForm() && !deleteButtonClicked; - if (!isEditPopulatedForm() || !isSavedEdits()) { setSavedDraft(false); } + let error = null; if (isBlankForm() || savedDraft) { error = null; @@ -580,7 +576,7 @@ const ComposeForm = props => { draft?.subject, formPopulated, messageBody, - selectedRecipient, + selectedRecipientId, subject, savedDraft, setUnsavedNavigationError, @@ -613,19 +609,14 @@ const ComposeForm = props => { const recipientHandler = useCallback( recipient => { - setSelectedRecipient(recipient.id.toString()); + setSelectedRecipientId(recipient?.id ? recipient.id.toString() : '0'); if (recipient.id !== '0') { if (recipient.id) setRecipientError(''); setUnsavedNavigationError(); } }, - [ - setRecipientError, - setUnsavedNavigationError, - setCheckboxMarked, - setElectronicSignature, - ], + [setRecipientError, setUnsavedNavigationError], ); const subjectHandler = e => { @@ -663,7 +654,7 @@ const ComposeForm = props => { const beforeUnloadHandler = useCallback( e => { if ( - selectedRecipient?.toString() !== + selectedRecipientId?.toString() !== (draft ? draft?.recipientId.toString() : '0') || category !== (draft ? draft?.category : null) || subject !== (draft ? draft?.subject : '') || @@ -682,7 +673,7 @@ const ComposeForm = props => { }, [ draft, - selectedRecipient, + selectedRecipientId, category, subject, messageBody, @@ -749,8 +740,11 @@ const ComposeForm = props => { {saveError?.editDraft && ( { + setSavedDraft(false); + setSaveError(null); + }} data-dd-action-name={`${saveError.editDraft} Button`} - onClick={() => setSaveError(null)} /> )} {saveError?.saveDraft && ( @@ -809,7 +803,7 @@ const ComposeForm = props => { recipientsList={recipientsList} onValueChange={recipientHandler} error={recipientError} - defaultValue={+selectedRecipient} + defaultValue={+selectedRecipientId} isSignatureRequired={isSignatureRequired} setCheckboxMarked={setCheckboxMarked} setElectronicSignature={setElectronicSignature} diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ElectronicSignature.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ElectronicSignature.jsx index 213bb5e35b3c..be39430810df 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ElectronicSignature.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ElectronicSignature.jsx @@ -49,6 +49,7 @@ const ElectronicSignature = ({ ElectronicSignature.propTypes = { checkboxError: PropTypes.string, checked: PropTypes.bool, + electronicSignature: PropTypes.string, nameError: PropTypes.string, onCheckboxCheck: PropTypes.func, onInput: PropTypes.func, diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx index 03e157cd9d09..44ddeee4d678 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx @@ -78,13 +78,21 @@ const RecipientsSelect = ({ const handleRecipientSelect = useCallback( e => { - const recipient = recipientsList.find(r => +r.id === +e.detail.value); - setSelectedRecipient(recipient); - if (recipient.signatureRequired || isSignatureRequired) { + const recipient = recipientsList?.find(r => +r.id === +e.detail.value); + + if (e.detail.value === '') { + setSelectedRecipient({}); + } + + if (e.detail.value !== '') { + setSelectedRecipient(recipient); + } + + if (recipient?.signatureRequired || isSignatureRequired) { setAlertDisplayed(true); } }, - [recipientsList, isSignatureRequired], + [recipientsList, isSignatureRequired, setSelectedRecipient], ); return ( @@ -94,7 +102,7 @@ const RecipientsSelect = ({ id="recipient-dropdown" label="To" name="to" - value={defaultValue !== undefined ? defaultValue : ''} + value={defaultValue} onVaSelect={handleRecipientSelect} class="composeSelect" data-testid="compose-recipient-select" @@ -111,8 +119,6 @@ const RecipientsSelect = ({ {alertDisplayed && ( -

+

{isSignatureRequired === true ? Prompts.Compose.SIGNATURE_REQUIRED : Prompts.Compose.SIGNATURE_NOT_REQUIRED} @@ -141,6 +147,8 @@ RecipientsSelect.propTypes = { defaultValue: PropTypes.number, error: PropTypes.string, isSignatureRequired: PropTypes.bool, + setCheckboxMarked: PropTypes.func, + setElectronicSignature: PropTypes.func, }; export default RecipientsSelect; diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ReplyDraftItem.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ReplyDraftItem.jsx index 7e6b2de78c76..147a8771574a 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ReplyDraftItem.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ReplyDraftItem.jsx @@ -157,7 +157,7 @@ const ReplyDraftItem = props => { messageValid = false; } setMessageInvalid(!messageValid); - return messageValid; + return { messageValid }; }, [messageBody], ); @@ -193,18 +193,17 @@ const ReplyDraftItem = props => { return; } - const isValidMessage = checkMessageValidity(); + const { messageValid } = checkMessageValidity(); if (type === 'manual') { - setMessageInvalid(false); - if (isValidMessage) { + if (messageValid) { setLastFocusableElement(e.target); } if (attachments.length) { setSaveError( ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT, ); - } + } else focusOnErrorField(); setNavigationError( attachments.length ? { @@ -234,7 +233,7 @@ const ReplyDraftItem = props => { body: messageBody, }; - if (isValidMessage) { + if (messageValid) { if (!draftId) { setFieldsString(newFieldsString); dispatch(saveReplyDraft(replyMessage.messageId, formData, type)); diff --git a/src/applications/mhv-secure-messaging/tests/components/Compose/ComposeForm.unit.spec.jsx b/src/applications/mhv-secure-messaging/tests/components/Compose/ComposeForm.unit.spec.jsx index 4efc364626e6..5cc39db5a30a 100644 --- a/src/applications/mhv-secure-messaging/tests/components/Compose/ComposeForm.unit.spec.jsx +++ b/src/applications/mhv-secure-messaging/tests/components/Compose/ComposeForm.unit.spec.jsx @@ -34,6 +34,7 @@ import { inputVaTextInput, selectVaRadio, selectVaSelect, + checkVaCheckbox, } from '../../../util/testUtils'; import { drupalStaticData } from '../../fixtures/cerner-facility-mock-data.json'; @@ -351,10 +352,12 @@ describe('Compose form component', () => { }); it('displays an error on attempt to save a draft with attachments', async () => { - const screen = setup(initialState, Paths.COMPOSE, { + const customProps = { + ...draftMessage, + messageValid: true, isSignatureRequired: false, - messageValid: false, - }); + }; + const screen = setup(initialState, Paths.COMPOSE, { draft: customProps }); const file = new File(['(⌐□_□)'], 'test.png', { type: 'image/png' }); const uploader = screen.getByTestId('attach-file-input'); @@ -371,7 +374,6 @@ describe('Compose form component', () => { modal = screen.queryByTestId('quit-compose-double-dare'); expect(modal).to.exist; }); - expect(modal).to.have.attribute( 'modal-title', "We can't save attachments in a draft message", @@ -882,7 +884,7 @@ describe('Compose form component', () => { expect(screen.queryByTestId('send-button')).to.not.exist; }); - it('displays alerts in Electronic Signature component if signature and checkbox is required', async () => { + it('displays alerts in Electronic Signature component if signature is required', async () => { const screen = renderWithStoreAndRouter( , { @@ -920,17 +922,40 @@ describe('Compose form component', () => { ); inputVaTextInput(screen.container, 'Test User', signatureTextFieldSelector); expect(signatureTextField).to.have.attribute('error', ''); + }); - const checkboxSelector = `va-checkbox[label='${ + it('displays an error in Electronic Signature component if checkbox is not checked', async () => { + const screen = renderWithStoreAndRouter( + , + { + initialState, + reducers: reducer, + }, + ); + // Enters value for all other compose form fields first + const tgRecipient = initialState.sm.recipients.allowedRecipients.find( + r => r.signatureRequired, + ).id; + selectVaSelect(screen.container, tgRecipient); + + const checkboxSelector = `va-checkbox[label="${ ElectronicSignatureBox.CHECKBOX_LABEL - }']`; - const checkbox = screen.container.querySelector(checkboxSelector); - const sendButton = screen.getByTestId('save-draft-button'); + }"]`; - fireEvent.click(sendButton); - expect(checkbox).to.have.attribute( - 'error', - `${ErrorMessages.ComposeForm.CHECKBOX_REQUIRED}`, - ); + await waitFor(() => { + const sendButton = screen.getByTestId('send-button'); + const checkbox = screen.container.querySelector(checkboxSelector); + checkVaCheckbox(checkbox, false); + + // after clicking send, validation checks on Electronic Signature component runs + fireEvent.click(sendButton); + expect(checkbox).to.have.attribute( + 'error', + `${ErrorMessages.ComposeForm.CHECKBOX_REQUIRED}`, + ); + + checkVaCheckbox(checkbox, true); + expect(checkbox).to.have.attribute('error', ''); + }); }); }); diff --git a/src/applications/mhv-secure-messaging/tests/components/Compose/RecipientsSelect.unit.spec.jsx b/src/applications/mhv-secure-messaging/tests/components/Compose/RecipientsSelect.unit.spec.jsx index 064f86fc67db..a2bf367e7c0a 100644 --- a/src/applications/mhv-secure-messaging/tests/components/Compose/RecipientsSelect.unit.spec.jsx +++ b/src/applications/mhv-secure-messaging/tests/components/Compose/RecipientsSelect.unit.spec.jsx @@ -57,10 +57,12 @@ describe('RecipientsSelect', () => { const onValueChange = sinon.spy(); const setCheckboxMarked = sinon.spy(); const setElectronicSignature = sinon.spy(); + const setAlertDisplayed = sinon.spy(); const customProps = { onValueChange, setCheckboxMarked, setElectronicSignature, + setAlertDisplayed, }; const screen = setup({ props: customProps }); const val = recipientsList[0].id; @@ -68,20 +70,25 @@ describe('RecipientsSelect', () => { const select = screen.getByTestId('compose-recipient-select'); waitFor(() => { + expect(setAlertDisplayed).to.be.calledOnce; expect(select).to.have.value(val); expect(onValueChange.calledOnce).to.be.true; + expect(onValueChange.calledWith(recipientsList[0])).to.be.true; }); - expect(onValueChange.calledWith(recipientsList[0])).to.be.true; }); it('displays the signature alert when a recipient with signatureRequired is selected', async () => { + const setAlertDisplayed = sinon.spy(); const customProps = { isSignatureRequired: true, + setAlertDisplayed, + alertDisplayed: true, }; const { getByTestId } = setup({ props: customProps }); waitFor(() => { const alert = getByTestId('signature-alert'); + expect(setAlertDisplayed).to.be.calledOnce; expect(alert).to.exist; expect(alert).to.contain.text( Constants.Prompts.Compose.SIGNATURE_REQUIRED, diff --git a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-compose-error-message-keyboard-nav.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-compose-error-message-keyboard-nav.cypress.spec.js index 0842dc49c409..ed7983373051 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-compose-error-message-keyboard-nav.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-compose-error-message-keyboard-nav.cypress.spec.js @@ -4,7 +4,6 @@ import PatientComposePage from '../pages/PatientComposePage'; import FolderLoadPage from '../pages/FolderLoadPage'; import { AXE_CONTEXT, Data } from '../utils/constants'; -// focus validation temporary commented due to focus error (will be fixed in MHV-61146) describe('Secure Messaging Compose Errors Keyboard Nav', () => { beforeEach(() => { SecureMessagingSite.login(); @@ -22,7 +21,7 @@ describe('Secure Messaging Compose Errors Keyboard Nav', () => { PatientComposePage.getMessageBodyField().type(Data.TEST_MESSAGE_BODY); PatientComposePage.pushSendMessageWithKeyboardPress(); PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_RECIPIENT); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('SELECT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -36,12 +35,12 @@ describe('Secure Messaging Compose Errors Keyboard Nav', () => { PatientComposePage.getMessageBodyField().type(Data.TEST_MESSAGE_BODY); PatientComposePage.pushSendMessageWithKeyboardPress(); PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_CATEGORY); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); - // PatientComposePage.selectCategory(); + PatientComposePage.selectCategory(); }); it('focus on error message for empty message subject', () => { @@ -50,7 +49,7 @@ describe('Secure Messaging Compose Errors Keyboard Nav', () => { PatientComposePage.getMessageBodyField().type(Data.TEST_MESSAGE_BODY); PatientComposePage.pushSendMessageWithKeyboardPress(); PatientComposePage.verifyErrorText(Data.SUBJECT_CANNOT_BLANK); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -66,7 +65,7 @@ describe('Secure Messaging Compose Errors Keyboard Nav', () => { }); PatientComposePage.pushSendMessageWithKeyboardPress(); PatientComposePage.verifyErrorText(Data.BODY_CANNOT_BLANK); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('TEXTAREA'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-save-draft.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-save-draft.cypress.spec.js index 9219ec90bf1f..9139894c9322 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-save-draft.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-save-draft.cypress.spec.js @@ -2,7 +2,7 @@ import SecureMessagingSite from '../sm_site/SecureMessagingSite'; import PatientInboxPage from '../pages/PatientInboxPage'; import PatientComposePage from '../pages/PatientComposePage'; import requestBody from '../fixtures/message-compose-request-body.json'; -import { AXE_CONTEXT } from '../utils/constants'; +import { AXE_CONTEXT, Locators } from '../utils/constants'; describe('Check confirmation message after save draft', () => { it('Check confirmation message after save draft', () => { @@ -22,9 +22,12 @@ describe('Check confirmation message after save draft', () => { cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); - PatientComposePage.verifyDraftSaveButtonOnFocus(); + PatientComposePage.verifyAlertFocusFocus(); + cy.get(Locators.BUTTONS.ALERT_CLOSE).click(); + cy.get('.sm-breadcrumb-list-item') .find('a') .click(); + cy.get(Locators.BACK_TO).click(); }); }); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/pages/ContactListPage.js b/src/applications/mhv-secure-messaging/tests/e2e/pages/ContactListPage.js index 315630c314a9..57d9fbfe62a8 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/ContactListPage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/ContactListPage.js @@ -160,7 +160,6 @@ class ContactListPage { .find(`a[href*="contact"]`) .click({ force: true }); - cy.contains(`Delete draft`).click({ force: true }); cy.url().should(`include`, `${Paths.UI_MAIN}/contact-list`); }; diff --git a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js index 4749305b13ee..eb9707bf273a 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js @@ -64,7 +64,6 @@ class PatientComposePage { }; selectRecipient = (index = 1) => { - cy.get(Locators.ALERTS.REPT_SELECT).click(); cy.get(Locators.ALERTS.REPT_SELECT) .shadow() .find('select') @@ -426,8 +425,8 @@ class PatientComposePage { .should('be.visible'); }; - verifyDraftSaveButtonOnFocus = () => { - cy.get(Locators.BUTTONS.SAVE_DRAFT) + verifyAlertFocusFocus = () => { + cy.get(`.first-focusable-child`) .should('exist') .and('be.focused'); }; @@ -503,7 +502,6 @@ class PatientComposePage { backToInbox = () => { cy.get(Locators.BACK_TO).click(); - cy.get('[visible=""] > [secondary=""]').click({ force: true }); }; } diff --git a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-compose-errors.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-compose-errors.cypress.spec.js index 88f5e8a3b3d8..d18a5e3b298b 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-compose-errors.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-compose-errors.cypress.spec.js @@ -3,7 +3,6 @@ import PatientInboxPage from './pages/PatientInboxPage'; import PatientComposePage from './pages/PatientComposePage'; import { AXE_CONTEXT, Data } from './utils/constants'; -// focus validation temporary commented due to focus error (will be fixed in MHV-61146) describe('Secure Messaging Compose Errors', () => { beforeEach(() => { SecureMessagingSite.login(); @@ -19,8 +18,8 @@ describe('Secure Messaging Compose Errors', () => { }); PatientComposePage.clickSendMessageButton(); - // PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_RECIPIENT); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_RECIPIENT); + PatientComposePage.verifyFocusOnErrorMessage('SELECT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -34,8 +33,8 @@ describe('Secure Messaging Compose Errors', () => { }); PatientComposePage.clickSendMessageButton(); - // PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_CATEGORY); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_CATEGORY); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -49,8 +48,8 @@ describe('Secure Messaging Compose Errors', () => { }); PatientComposePage.clickSendMessageButton(); - // PatientComposePage.verifyErrorText(Data.SUBJECT_CANNOT_BLANK); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyErrorText(Data.SUBJECT_CANNOT_BLANK); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -64,8 +63,26 @@ describe('Secure Messaging Compose Errors', () => { }); PatientComposePage.clickSendMessageButton(); - // PatientComposePage.verifyErrorText(Data.BODY_CANNOT_BLANK); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyErrorText(Data.BODY_CANNOT_BLANK); + PatientComposePage.verifyFocusOnErrorMessage('TEXTAREA'); + + cy.injectAxe(); + cy.axeCheck(AXE_CONTEXT); + }); + + it(`verify user can't send a message with electronic signature only`, () => { + PatientComposePage.selectRecipient('Record Amendment Admin'); + PatientComposePage.getElectronicSignatureField().type('Jack Sparrow', { + force: true, + }); + PatientComposePage.clickElectronicSignatureCheckbox(); + PatientComposePage.clickSendMessageButton(); + + PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_CATEGORY); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); + + cy.contains(Data.SUBJECT_CANNOT_BLANK).should('be.visible'); + cy.contains(Data.BODY_CANNOT_BLANK).should('be.visible'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-delete-draft-no-changes.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-delete-draft-no-changes.cypress.spec.js index 66e26321ee09..7fa289c88aaf 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-delete-draft-no-changes.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-delete-draft-no-changes.cypress.spec.js @@ -1,7 +1,6 @@ import SecureMessagingSite from './sm_site/SecureMessagingSite'; import PatientInboxPage from './pages/PatientInboxPage'; import PatientMessageDraftsPage from './pages/PatientMessageDraftsPage'; -import mockDraftResponse from './fixtures/message-draft-response.json'; import { AXE_CONTEXT, Locators } from './utils/constants'; describe('Secure Messaging Delete Draft Navigate to Inbox', () => { @@ -10,7 +9,6 @@ describe('Secure Messaging Delete Draft Navigate to Inbox', () => { PatientInboxPage.loadInboxMessages(); PatientInboxPage.navigateToComposePage(); PatientMessageDraftsPage.clickDeleteButton(); - PatientMessageDraftsPage.confirmDeleteDraft(mockDraftResponse); PatientMessageDraftsPage.verifyDeleteConfirmationMessage(); cy.get(Locators.HEADER_FOLDER).should('have.text', 'Inbox'); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-electronic-signature-alerts.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-electronic-signature-alerts.cypress.spec.js index 041e3f55e019..22252eb99a70 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-electronic-signature-alerts.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-electronic-signature-alerts.cypress.spec.js @@ -10,7 +10,9 @@ describe('Secure Messaging Digital Signature Error flows', () => { PatientInboxPage.navigateToComposePage(); PatientComposePage.selectRecipient('Record Amendment Admin'); PatientComposePage.selectCategory(); - PatientComposePage.getMessageSubjectField().type(`DS test`); + PatientComposePage.getMessageSubjectField().type(`DS test`, { + force: true, + }); PatientComposePage.getMessageBodyField().type(`\nDS tests text`, { force: true, }); @@ -47,7 +49,6 @@ describe('Secure Messaging Digital Signature Error flows', () => { force: true, }); - // TODO clarify `unchecked save draft` behavior PatientComposePage.clickElectronicSignatureCheckbox(); cy.get(Locators.BUTTONS.SAVE_DRAFT).click({ force: true }); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-message-thread-detail-reply-page.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-message-thread-detail-reply-page.cypress.spec.js index f9c1d785344e..d9bbde0ee06f 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-message-thread-detail-reply-page.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-message-thread-detail-reply-page.cypress.spec.js @@ -20,9 +20,9 @@ describe('Secure Messaging Reply Message Details Thread', () => { PatientReplyPage.verifyExpandedMessageDate(testMessage); cy.get( - `[data-testid='expand-message-button-${ + `[data-testid="expand-message-button-${ testMessage.data.attributes.messageId - }']`, + }"]`, ).click({ waitforanimations: true, multiple: true }); PatientReplyPage.verifyExpandedMessageDate(testMessage); PatientMessageDetailsPage.verifyExpandedMessageId(testMessage); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-save-draft-errors.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-save-draft-errors.cypress.spec.js index cce27942d0a6..9e5086de8cc3 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-save-draft-errors.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/secure-messaging-save-draft-errors.cypress.spec.js @@ -19,7 +19,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSaveDraftButton(); PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_RECIPIENT); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('SELECT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -32,7 +32,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSaveDraftButton(); PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_CATEGORY); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -47,7 +47,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSaveDraftButton(); PatientComposePage.verifyErrorText(Data.SUBJECT_CANNOT_BLANK); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -62,7 +62,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSaveDraftButton(); PatientComposePage.verifyErrorText(Data.BODY_CANNOT_BLANK); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('TEXTAREA'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); }); diff --git a/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js b/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js index ea5049606be0..1af9c981e1ca 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js @@ -141,6 +141,7 @@ export const Locators = { EDIT_DRAFTS: '[data-testid="edit-draft-button-body-text"]', CL_SAVE: `[data-testid="contact-list-save"]`, CL_GO_BACK: '[data-testid="contact-list-go-back"]', + ALERT_CLOSE: `.first-focusable-child`, }, LINKS: { GO_TO_INBOX: '[data-testid="inbox-link"]',