From da13cf02c6f9ad6b1f1a62e06196dc1b03da8dff Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Thu, 22 Aug 2024 12:15:53 -0500 Subject: [PATCH 01/30] [MHV-61146] sets focus on error field after clicking send btn --- .../components/ComposeForm/ComposeForm.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index d3de2b2c46d2..3dc21d22470a 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -391,8 +391,6 @@ const ComposeForm = props => { } = checkMessageValidity(); if (type === 'manual') { - setLastFocusableElement(e?.target); - // if all checks are valid, then save the draft if ( (messageValid && !isSignatureRequired) || @@ -400,10 +398,11 @@ const ComposeForm = props => { ) { setNavigationError(null); setSavedDraft(true); - } else - setUnsavedNavigationError( - ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, - ); + setLastFocusableElement(e?.target); + } else focusOnErrorField(); + setUnsavedNavigationError( + ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, + ); let errorType = null; if ( @@ -507,6 +506,7 @@ const ComposeForm = props => { setLastFocusableElement(e.target); } else { setSendMessageFlag(false); + focusOnErrorField(); } }, [checkMessageValidity, isSignatureRequired], From b87056660f3b6772c6fff161bba69fa57c388019 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Thu, 22 Aug 2024 14:22:45 -0700 Subject: [PATCH 02/30] uncomment failed tests --- ...e-error-message-keyboard-nav.cypress.spec.js | 11 +++++------ ...ure-messaging-compose-errors.cypress.spec.js | 17 ++++++++--------- 2 files changed, 13 insertions(+), 15 deletions(-) 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..4f11c0e09163 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(); 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(); 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(); 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(); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); 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..cb53d2a77c44 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(); 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(); 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(); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -64,8 +63,8 @@ describe('Secure Messaging Compose Errors', () => { }); PatientComposePage.clickSendMessageButton(); - // PatientComposePage.verifyErrorText(Data.BODY_CANNOT_BLANK); - // PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyErrorText(Data.BODY_CANNOT_BLANK); + PatientComposePage.verifyFocusOnErrorMessage(); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); From d9383aed975203ee6b73022ea3392da67a0ceda3 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Mon, 26 Aug 2024 12:57:55 -0700 Subject: [PATCH 03/30] update verifyFocusOnErrorMessage --- ...ompose-error-message-keyboard-nav.cypress.spec.js | 8 ++++---- ...nav-to-links-buttons-landing-page.cypress.spec.js | 12 ++++++------ .../tests/e2e/pages/PatientComposePage.js | 8 +++----- .../secure-messaging-compose-errors.cypress.spec.js | 8 ++++---- ...ecure-messaging-save-draft-errors.cypress.spec.js | 8 ++++---- 5 files changed, 21 insertions(+), 23 deletions(-) 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 4f11c0e09163..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 @@ -21,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); @@ -35,7 +35,7 @@ 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); @@ -49,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); @@ -65,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-to-links-buttons-landing-page.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js index 2701ce0bd6cb..5f87e4231f19 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js @@ -27,12 +27,12 @@ describe('Secure Messaging Verify Links and Buttons Keyboard Nav', () => { cy.get(Locators.ALERTS.BACK_TOP).scrollIntoView(); - cy.get(Locators.ALERTS.BACK_TOP) - .shadow() - .find('.docked.reveal', { timeout: 1000 }) - .should('be.visible'); - cy.realPress('Tab'); - cy.get(Locators.ALERTS.BACK_TOP).should('have.focus'); + // cy.get(Locators.ALERTS.BACK_TOP) + // .shadow() + // .find('.docked.reveal', { timeout: 1000 }) + // .should('be.visible'); + // cy.realPress('Tab'); + // cy.get(Locators.ALERTS.BACK_TOP).should('have.focus'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); 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 e391903e9e88..a25c50e10d70 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js @@ -119,11 +119,9 @@ class PatientComposePage { cy.get('.usa-error-message').should('contain.text', text); }; - verifyFocusOnErrorMessage = () => { - const allowedTags = ['INPUT', 'TEXTAREA', 'SELECT']; - return cy.focused().then(el => { - const tagName = el.prop('tagName'); - expect(tagName).to.be.oneOf(allowedTags); + verifyFocusOnErrorMessage = element => { + cy.focused().then(el => { + expect(el.prop('tagName')).to.eq(element); }); }; 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 cb53d2a77c44..39ec42103e8f 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 @@ -19,7 +19,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSendMessageButton(); PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_RECIPIENT); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('SELECT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -34,7 +34,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSendMessageButton(); PatientComposePage.verifyErrorText(Data.PLEASE_SELECT_CATEGORY); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -49,7 +49,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSendMessageButton(); PatientComposePage.verifyErrorText(Data.SUBJECT_CANNOT_BLANK); - PatientComposePage.verifyFocusOnErrorMessage(); + PatientComposePage.verifyFocusOnErrorMessage('INPUT'); cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); @@ -64,7 +64,7 @@ describe('Secure Messaging Compose Errors', () => { PatientComposePage.clickSendMessageButton(); 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/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); }); From a86a9e7095fb43eb194dc4bc423b33b224ad1ba6 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Wed, 28 Aug 2024 11:18:57 -0500 Subject: [PATCH 04/30] [MHV-61146] Resolve recipient select bug, user is not allowed to send if recipient is not selected --- .../components/ComposeForm/ComposeForm.jsx | 53 +++++++++---------- .../ComposeForm/RecipientsSelect.jsx | 20 +++++-- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 3dc21d22470a..96b025bcafcd 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -54,21 +54,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(''); @@ -108,7 +108,7 @@ const ComposeForm = props => { const debouncedMessageBody = useDebounce(messageBody, draftAutoSaveTimeout); const debouncedCategory = useDebounce(category, draftAutoSaveTimeout); const debouncedRecipient = useDebounce( - selectedRecipient, + selectedRecipientId, draftAutoSaveTimeout, ); @@ -236,7 +236,7 @@ const ComposeForm = props => { subject, }; messageData[`${'draft_id'}`] = draft?.messageId; - messageData[`${'recipient_id'}`] = selectedRecipient; + messageData[`${'recipient_id'}`] = selectedRecipientId; let sendData; if (attachments.length > 0) { @@ -293,7 +293,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, @@ -303,7 +303,7 @@ const ComposeForm = props => { ...prevRecipientsList, newRecipient, ]); - setSelectedRecipient(newRecipient.id); + setSelectedRecipientId(newRecipient.id); } setCategory(draft.category); setSubject(draft.subject); @@ -331,9 +331,9 @@ const ComposeForm = props => { let checkboxValid = true; if ( - selectedRecipient === '0' || - selectedRecipient === '' || - !selectedRecipient + selectedRecipientId === '0' || + selectedRecipientId === '' || + !selectedRecipientId ) { setRecipientError(ErrorMessages.ComposeForm.RECIPIENT_REQUIRED); messageValid = false; @@ -371,7 +371,7 @@ const ComposeForm = props => { return { messageValid, signatureValid, checkboxValid }; }, [ - selectedRecipient, + selectedRecipientId, subject, messageBody, category, @@ -438,7 +438,7 @@ const ComposeForm = props => { 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, @@ -450,7 +450,7 @@ const ComposeForm = props => { setFieldsString(newFieldsString); const formData = { - recipientId: selectedRecipient, + recipientId: selectedRecipientId, category, subject, body: messageBody, @@ -467,7 +467,7 @@ const ComposeForm = props => { checkMessageValidity, draft, debouncedRecipient, - selectedRecipient, + selectedRecipientId, debouncedCategory, category, debouncedSubject, @@ -517,19 +517,19 @@ const ComposeForm = props => { const isBlankForm = () => messageBody === '' && subject === '' && - (selectedRecipient === 0 || selectedRecipient === '0') && + (selectedRecipientId === 0 || 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() && @@ -567,7 +567,7 @@ const ComposeForm = props => { draft?.subject, formPopulated, messageBody, - selectedRecipient, + selectedRecipientId, subject, savedDraft, setUnsavedNavigationError, @@ -600,19 +600,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 => { @@ -650,7 +645,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 : '') || @@ -669,7 +664,7 @@ const ComposeForm = props => { }, [ draft, - selectedRecipient, + selectedRecipientId, category, subject, messageBody, @@ -793,7 +788,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/RecipientsSelect.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx index 03e157cd9d09..42274f7cdec1 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" @@ -141,6 +149,8 @@ RecipientsSelect.propTypes = { defaultValue: PropTypes.number, error: PropTypes.string, isSignatureRequired: PropTypes.bool, + setCheckboxMarked: PropTypes.func, + setElectronicSignature: PropTypes.func, }; export default RecipientsSelect; From 9be8af84b07ed392dac695051be54e6cae321f3e Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Wed, 28 Aug 2024 12:51:30 -0500 Subject: [PATCH 05/30] [MHV-61146] Bug fix, prevents user from saving or sending a message to specific tg if all required fields aren't completed --- .../mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 96b025bcafcd..49b11aa48326 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -498,7 +498,7 @@ const ComposeForm = props => { await setSendMessageFlag(false); const validSignatureNotRequired = messageValid && !isSignatureRequired; const validSignatureRequired = - isSignatureRequired && signatureValid && checkboxValid; + isSignatureRequired && signatureValid && checkboxValid && messageValid; if (validSignatureNotRequired || validSignatureRequired) { setSendMessageFlag(true); From c21b07fb6475c18f88e997873df0c49231c53956 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Wed, 28 Aug 2024 13:15:28 -0700 Subject: [PATCH 06/30] add test to compose-errors spec --- .../tests/e2e/pages/PatientComposePage.js | 1 - ...re-messaging-compose-errors.cypress.spec.js | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) 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 a25c50e10d70..e2c492afd03c 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') 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 39ec42103e8f..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 @@ -69,4 +69,22 @@ describe('Secure Messaging Compose Errors', () => { 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); + }); }); From 205e5bf07a84fbc175ec23e65062c9bb2d01e35f Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Fri, 30 Aug 2024 09:26:05 -0500 Subject: [PATCH 07/30] [MHV-61146] Accessibility fix to adjust focus to announce the recipient field and electronic signature required alert correctly --- .../components/ComposeForm/ComposeForm.jsx | 58 ++++++++++++++----- .../ComposeForm/ElectronicSignature.jsx | 1 + .../ComposeForm/RecipientsSelect.jsx | 17 ++++-- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index b72156de4dfc..f88cf0a20bae 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -1,4 +1,10 @@ -import React, { useState, useEffect, useMemo, useCallback } from 'react'; +import React, { + useState, + useEffect, + useMemo, + useCallback, + useRef, +} from 'react'; import PropTypes from 'prop-types'; import { validateNameSymbols } from 'platform/forms-system/src/js/web-component-patterns/fullNamePattern'; import { useDispatch, useSelector } from 'react-redux'; @@ -52,11 +58,14 @@ const ComposeForm = props => { } = recipients; const dispatch = useDispatch(); const history = useHistory(); + const alertRef = useRef(); const [recipientsList, setRecipientsList] = useState(allowedRecipients); const [selectedRecipientId, setSelectedRecipientId] = useState(null); const [isSignatureRequired, setIsSignatureRequired] = useState(null); const [checkboxMarked, setCheckboxMarked] = useState(false); + const [alertDisplayed, setAlertDisplayed] = useState(false); + const [alertHasFocused, setAlertHasFocused] = useState(false); useEffect( () => { @@ -264,14 +273,34 @@ const ComposeForm = props => { useEffect( () => { - if ( - messageInvalid || - (isSignatureRequired && (signatureInvalid || checkboxInvalid)) - ) { - focusOnErrorField(); - } + const handleEffect = async () => { + const selectedTG = recipientsList.find( + recipient => recipient.triageTeamId === +selectedRecipientId, + ); + if ( + alertDisplayed && + !alertHasFocused && + alertRef.current && + selectedTG + ) { + await focusElement(selectedTG?.name); + focusElement(alertRef.current); + setAlertHasFocused(true); + } else if (messageInvalid) { + focusOnErrorField(); + } + }; + handleEffect(); }, - [checkboxInvalid, isSignatureRequired, messageInvalid, signatureInvalid], + [ + alertDisplayed, + alertHasFocused, + checkboxInvalid, + isSignatureRequired, + messageInvalid, + selectedRecipientId, + signatureInvalid, + ], ); useEffect( @@ -351,16 +380,14 @@ const ComposeForm = props => { messageValid = false; } if ( - (isSignatureRequired && !electronicSignature) || - isSignatureRequired === null + messageValid === true && + isSignatureRequired && + !electronicSignature ) { setSignatureError(ErrorMessages.ComposeForm.SIGNATURE_REQUIRED); signatureValid = false; } - if ( - (isSignatureRequired && !checkboxMarked) || - isSignatureRequired === null - ) { + if (messageValid === true && isSignatureRequired && !checkboxMarked) { setCheckboxError(ErrorMessages.ComposeForm.CHECKBOX_REQUIRED); checkboxValid = false; } @@ -785,6 +812,9 @@ const ComposeForm = props => { !noAssociations && !allTriageGroupsBlocked && ( { - const alertRef = useRef(null); const isSignatureRequiredRef = useRef(); isSignatureRequiredRef.current = isSignatureRequired; - const [alertDisplayed, setAlertDisplayed] = useState(false); const [selectedRecipient, setSelectedRecipient] = useState(null); useEffect( @@ -57,7 +58,7 @@ const RecipientsSelect = ({ setAlertDisplayed(true); } }, - [isSignatureRequired], + [isSignatureRequired, setAlertDisplayed], ); useEffect( @@ -92,7 +93,12 @@ const RecipientsSelect = ({ setAlertDisplayed(true); } }, - [recipientsList, isSignatureRequired, setSelectedRecipient], + [ + recipientsList, + isSignatureRequired, + setSelectedRecipient, + setAlertDisplayed, + ], ); return ( @@ -146,9 +152,12 @@ const RecipientsSelect = ({ RecipientsSelect.propTypes = { recipientsList: PropTypes.array.isRequired, onValueChange: PropTypes.func.isRequired, + alertDisplayed: PropTypes.bool, + alertRef: PropTypes.object, defaultValue: PropTypes.number, error: PropTypes.string, isSignatureRequired: PropTypes.bool, + setAlertDisplayed: PropTypes.func, setCheckboxMarked: PropTypes.func, setElectronicSignature: PropTypes.func, }; From 695d1f46aeb0e1e2b8b206c5303055995ff9b3c9 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Fri, 30 Aug 2024 09:26:59 -0500 Subject: [PATCH 08/30] [MHV-61146] Unit test fixes in progress --- .../Compose/ComposeForm.unit.spec.jsx | 28 +++++++++++-------- .../Compose/RecipientsSelect.unit.spec.jsx | 7 +++-- 2 files changed, 22 insertions(+), 13 deletions(-) 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 f20e2297c70f..e8d62c23e5b1 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 @@ -22,7 +22,7 @@ import { Paths, Prompts, ElectronicSignatureBox, - ErrorMessages, + // ErrorMessages, } from '../../../util/constants'; import { messageSignatureFormatter } from '../../../util/helpers'; import * as messageActions from '../../../actions/messages'; @@ -893,7 +893,11 @@ describe('Compose form component', () => { it('displays alerts in Electronic Signature component if signature and checkbox is required', async () => { const screen = renderWithStoreAndRouter( - , + , { initialState, reducers: reducer, @@ -930,16 +934,18 @@ describe('Compose form component', () => { inputVaTextInput(screen.container, 'Test User', signatureTextFieldSelector); expect(signatureTextField).to.have.attribute('error', ''); - const checkboxSelector = `va-checkbox[label='${ - ElectronicSignatureBox.CHECKBOX_LABEL - }']`; - const checkbox = screen.container.querySelector(checkboxSelector); - const sendButton = screen.getByTestId('save-draft-button'); + // const checkboxSelector = `va-checkbox[label='${ + // ElectronicSignatureBox.CHECKBOX_LABEL + // }']`; + // const checkbox = screen.container.querySelector(checkboxSelector); + const sendButton = screen.getByTestId('send-button'); fireEvent.click(sendButton); - expect(checkbox).to.have.attribute( - 'error', - `${ErrorMessages.ComposeForm.CHECKBOX_REQUIRED}`, - ); + // await waitFor(() => { + // expect(checkbox).to.have.attribute( + // 'error', + // `${ErrorMessages.ComposeForm.CHECKBOX_REQUIRED}`, + // ); + // }); }); }); 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..139fbba3da54 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 @@ -53,14 +53,16 @@ describe('RecipientsSelect', () => { expect(options).to.have.lengthOf(recipientsList.length); }); - it('calls the onValueChange callback when a recipient is selected', async () => { + xit('calls the onValueChange callback when a recipient is selected', async () => { 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; @@ -74,9 +76,10 @@ describe('RecipientsSelect', () => { expect(onValueChange.calledWith(recipientsList[0])).to.be.true; }); - it('displays the signature alert when a recipient with signatureRequired is selected', async () => { + xit('displays the signature alert when a recipient with signatureRequired is selected', async () => { const customProps = { isSignatureRequired: true, + messageValid: true, }; const { getByTestId } = setup({ props: customProps }); From 3b427a7436389d32c2bd319bd4f0e6b69905497a Mon Sep 17 00:00:00 2001 From: fazilqa Date: Wed, 4 Sep 2024 10:55:31 -0700 Subject: [PATCH 09/30] test fix --- ...ure-messaging-electronic-signature-alerts.cypress.spec.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 2f21311de899..c89e2360e714 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, }); @@ -48,7 +50,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 }); From dc3c4f7552224d65d2ce9d92787f346c5b7212e7 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Wed, 4 Sep 2024 14:30:58 -0500 Subject: [PATCH 10/30] [MHV-61146] unit test updates for electronic signature checkbox --- .../Compose/ComposeForm.unit.spec.jsx | 74 +++++++++++++++---- .../Compose/RecipientsSelect.unit.spec.jsx | 11 ++- 2 files changed, 68 insertions(+), 17 deletions(-) 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 e8d62c23e5b1..40308ccd8b71 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 @@ -22,7 +22,7 @@ import { Paths, Prompts, ElectronicSignatureBox, - // ErrorMessages, + ErrorMessages, } from '../../../util/constants'; import { messageSignatureFormatter } from '../../../util/helpers'; import * as messageActions from '../../../actions/messages'; @@ -33,6 +33,7 @@ import { inputVaTextInput, selectVaRadio, selectVaSelect, + checkVaCheckbox, } from '../../../util/testUtils'; import { drupalStaticData } from '../../fixtures/cerner-facility-mock-data.json'; @@ -891,7 +892,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( { ); inputVaTextInput(screen.container, 'Test User', signatureTextFieldSelector); expect(signatureTextField).to.have.attribute('error', ''); + }); - // const checkboxSelector = `va-checkbox[label='${ - // ElectronicSignatureBox.CHECKBOX_LABEL - // }']`; - // const checkbox = screen.container.querySelector(checkboxSelector); - const sendButton = screen.getByTestId('send-button'); + 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); + + await waitFor(() => { + selectVaRadio(screen.container, 'COVID'); + expect( + $('va-radio-option[value="COVID"]', screen.container), + ).to.have.attribute('checked', 'true'); + }); + + const subjectInput = 'Test Subject'; + inputVaTextInput(screen.container, subjectInput); + await waitFor(() => { + expect(screen.getByTestId('message-subject-field')).to.have.value( + subjectInput, + ); + }); + + const messageBody = 'test body'; + inputVaTextInput(screen.container, messageBody, 'va-textarea'); + await waitFor(() => { + expect(screen.getByTestId('message-body-field')).to.have.value( + messageBody, + ); + }); + const checkboxSelector = `va-checkbox[label='${ + ElectronicSignatureBox.CHECKBOX_LABEL + }']`; + const checkbox = screen.container.querySelector(checkboxSelector); + checkVaCheckbox(checkbox, false); + + const sendButton = screen.getByTestId('send-button'); fireEvent.click(sendButton); - // await waitFor(() => { - // expect(checkbox).to.have.attribute( - // 'error', - // `${ErrorMessages.ComposeForm.CHECKBOX_REQUIRED}`, - // ); - // }); + // after clicking send, validation checks on Electronic Signature component runs + await waitFor(() => { + 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 139fbba3da54..8458025bab06 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 @@ -53,7 +53,7 @@ describe('RecipientsSelect', () => { expect(options).to.have.lengthOf(recipientsList.length); }); - xit('calls the onValueChange callback when a recipient is selected', async () => { + it('calls the onValueChange callback when a recipient is selected', async () => { const onValueChange = sinon.spy(); const setCheckboxMarked = sinon.spy(); const setElectronicSignature = sinon.spy(); @@ -72,19 +72,22 @@ describe('RecipientsSelect', () => { waitFor(() => { 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; }); - xit('displays the signature alert when a recipient with signatureRequired is selected', async () => { + it('displays the signature alert when a recipient with signatureRequired is selected', async () => { + const setAlertDisplayed = sinon.spy(); const customProps = { isSignatureRequired: true, - messageValid: 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, From a6cc58435f27d642b282e6b9820f43dde93b3f15 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Thu, 5 Sep 2024 10:57:26 -0500 Subject: [PATCH 11/30] cleanup --- .../components/ComposeForm/ComposeForm.jsx | 14 +++++--------- .../components/Compose/ComposeForm.unit.spec.jsx | 12 ++---------- .../Compose/RecipientsSelect.unit.spec.jsx | 1 + 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index f88cf0a20bae..953fe785a022 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -379,15 +379,11 @@ const ComposeForm = props => { setCategoryError(ErrorMessages.ComposeForm.CATEGORY_REQUIRED); messageValid = false; } - if ( - messageValid === true && - isSignatureRequired && - !electronicSignature - ) { + if (messageValid && isSignatureRequired && !electronicSignature) { setSignatureError(ErrorMessages.ComposeForm.SIGNATURE_REQUIRED); signatureValid = false; } - if (messageValid === true && isSignatureRequired && !checkboxMarked) { + if (messageValid && isSignatureRequired && !checkboxMarked) { setCheckboxError(ErrorMessages.ComposeForm.CHECKBOX_REQUIRED); checkboxValid = false; } @@ -524,10 +520,10 @@ const ComposeForm = props => { await setMessageInvalid(false); await setSendMessageFlag(false); const validSignatureNotRequired = messageValid && !isSignatureRequired; - const validSignatureRequired = + const isSignatureValid = isSignatureRequired && signatureValid && checkboxValid && messageValid; - if (validSignatureNotRequired || validSignatureRequired) { + if (validSignatureNotRequired || isSignatureValid) { setSendMessageFlag(true); setNavigationError(null); setLastFocusableElement(e.target); @@ -544,7 +540,7 @@ const ComposeForm = props => { const isBlankForm = () => messageBody === '' && subject === '' && - (selectedRecipientId === 0 || selectedRecipientId === '0') && + Number(selectedRecipientId) === 0 && category === null && attachments.length === 0; 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 40308ccd8b71..fa3fef04a9be 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 @@ -894,11 +894,7 @@ describe('Compose form component', () => { it('displays alerts in Electronic Signature component if signature is required', async () => { const screen = renderWithStoreAndRouter( - , + , { initialState, reducers: reducer, @@ -938,11 +934,7 @@ describe('Compose form component', () => { it('displays an error in Electronic Signature component if checkbox is not checked', async () => { const screen = renderWithStoreAndRouter( - , + , { initialState, reducers: reducer, 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 8458025bab06..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 @@ -70,6 +70,7 @@ 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; From 56e7e6f92c21afc315bc8805ff6b0ab984ec2a99 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Fri, 6 Sep 2024 12:34:24 -0500 Subject: [PATCH 12/30] cleanup --- .../components/ComposeForm/ComposeForm.jsx | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 953fe785a022..37b0f71ec8b3 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -65,7 +65,6 @@ const ComposeForm = props => { const [isSignatureRequired, setIsSignatureRequired] = useState(null); const [checkboxMarked, setCheckboxMarked] = useState(false); const [alertDisplayed, setAlertDisplayed] = useState(false); - const [alertHasFocused, setAlertHasFocused] = useState(false); useEffect( () => { @@ -273,28 +272,10 @@ const ComposeForm = props => { useEffect( () => { - const handleEffect = async () => { - const selectedTG = recipientsList.find( - recipient => recipient.triageTeamId === +selectedRecipientId, - ); - if ( - alertDisplayed && - !alertHasFocused && - alertRef.current && - selectedTG - ) { - await focusElement(selectedTG?.name); - focusElement(alertRef.current); - setAlertHasFocused(true); - } else if (messageInvalid) { - focusOnErrorField(); - } - }; - handleEffect(); + focusOnErrorField(); }, [ alertDisplayed, - alertHasFocused, checkboxInvalid, isSignatureRequired, messageInvalid, From ace4e23056148b9f5f992b61e84c2071cb3729b8 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Fri, 6 Sep 2024 12:04:05 -0700 Subject: [PATCH 13/30] fix failed tests --- ...g-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js | 2 ++ .../mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js index 89b68aace69e..657285662256 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/keyboard-nav-test/secure-messaging-keyboard-nav-to-links-buttons-landing-page.cypress.spec.js @@ -24,6 +24,8 @@ describe('Secure Messaging Verify Links and Buttons Keyboard Nav', () => { cy.get(el).should('have.focus'); }); + cy.get(Locators.ALERTS.BACK_TOP).scrollIntoView(); + cy.get(Locators.ALERTS.BACK_TOP) .shadow() .find('a') 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 7356ddb72916..a2968b0e3c5f 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js @@ -501,7 +501,7 @@ class PatientComposePage { backToInbox = () => { cy.get(Locators.BACK_TO).click(); - cy.get('[visible=""] > [secondary=""]').click({ force: true }); + // cy.get('[visible=""] > [secondary=""]').click({ force: true }); }; } From daaa3734bc6da8185773005d7a81274c9be48e72 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Fri, 6 Sep 2024 12:59:17 -0700 Subject: [PATCH 14/30] code cleanup --- .../mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js | 1 - 1 file changed, 1 deletion(-) 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 a2968b0e3c5f..adb3ccc2fa88 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js @@ -501,7 +501,6 @@ class PatientComposePage { backToInbox = () => { cy.get(Locators.BACK_TO).click(); - // cy.get('[visible=""] > [secondary=""]').click({ force: true }); }; } From f1a6792dcbf6cf6ad757ade9643c41da24bc59c9 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Mon, 9 Sep 2024 09:20:52 -0700 Subject: [PATCH 15/30] update test --- .../secure-messaging-delete-draft-no-changes.cypress.spec.js | 2 -- 1 file changed, 2 deletions(-) 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'); From 19cf3ff417ed06bbbb15ab4291b7b9cabbd3ed13 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Tue, 10 Sep 2024 09:46:51 -0500 Subject: [PATCH 16/30] cleanup --- .../components/ComposeForm/ComposeForm.jsx | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 37b0f71ec8b3..38c049724cd2 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -272,16 +272,14 @@ const ComposeForm = props => { useEffect( () => { - focusOnErrorField(); + if ( + messageInvalid || + (isSignatureRequired && (signatureInvalid || checkboxInvalid)) + ) { + focusOnErrorField(); + } }, - [ - alertDisplayed, - checkboxInvalid, - isSignatureRequired, - messageInvalid, - selectedRecipientId, - signatureInvalid, - ], + [checkboxInvalid, isSignatureRequired, messageInvalid, signatureInvalid], ); useEffect( @@ -396,10 +394,14 @@ const ComposeForm = props => { if (type === 'manual') { // if all checks are valid, then save the draft - if ( - (messageValid && !isSignatureRequired) || - (isSignatureRequired && signatureValid && checkboxValid && !saveError) - ) { + const validSignatureNotRequired = messageValid && !isSignatureRequired; + const isSignatureValid = + isSignatureRequired && + signatureValid && + checkboxValid && + !saveError && + messageValid; + if (validSignatureNotRequired || isSignatureValid) { setNavigationError(null); setSavedDraft(true); setLastFocusableElement(e?.target); From 272deebbd3452f6f890aa7d185f7d3a745ab0ff1 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Tue, 10 Sep 2024 16:42:10 -0500 Subject: [PATCH 17/30] [MHV-61146] cleanup; Removed separate signature and checkbox validation checks - all validation check will now be operated by messageValid --- .../components/ComposeForm/ComposeForm.jsx | 58 ++++--------------- .../ComposeForm/RecipientsSelect.jsx | 17 ++---- 2 files changed, 16 insertions(+), 59 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 38c049724cd2..5b0e6a997767 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -1,10 +1,4 @@ -import React, { - useState, - useEffect, - useMemo, - useCallback, - useRef, -} from 'react'; +import React, { useState, useEffect, useMemo, useCallback } from 'react'; import PropTypes from 'prop-types'; import { validateNameSymbols } from 'platform/forms-system/src/js/web-component-patterns/fullNamePattern'; import { useDispatch, useSelector } from 'react-redux'; @@ -58,13 +52,11 @@ const ComposeForm = props => { } = recipients; const dispatch = useDispatch(); const history = useHistory(); - const alertRef = useRef(); const [recipientsList, setRecipientsList] = useState(allowedRecipients); const [selectedRecipientId, setSelectedRecipientId] = useState(null); const [isSignatureRequired, setIsSignatureRequired] = useState(null); const [checkboxMarked, setCheckboxMarked] = useState(false); - const [alertDisplayed, setAlertDisplayed] = useState(false); useEffect( () => { @@ -93,8 +85,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); @@ -272,14 +262,11 @@ const ComposeForm = props => { useEffect( () => { - if ( - messageInvalid || - (isSignatureRequired && (signatureInvalid || checkboxInvalid)) - ) { + if (messageInvalid || isSignatureRequired) { focusOnErrorField(); } }, - [checkboxInvalid, isSignatureRequired, messageInvalid, signatureInvalid], + [isSignatureRequired, messageInvalid], ); useEffect( @@ -335,9 +322,6 @@ const ComposeForm = props => { const checkMessageValidity = useCallback( () => { let messageValid = true; - let signatureValid = true; - let checkboxValid = true; - if ( selectedRecipientId === '0' || selectedRecipientId === '' || @@ -358,19 +342,17 @@ const ComposeForm = props => { setCategoryError(ErrorMessages.ComposeForm.CATEGORY_REQUIRED); messageValid = false; } - if (messageValid && isSignatureRequired && !electronicSignature) { + if (isSignatureRequired && !electronicSignature) { setSignatureError(ErrorMessages.ComposeForm.SIGNATURE_REQUIRED); - signatureValid = false; + messageValid = false; } - if (messageValid && isSignatureRequired && !checkboxMarked) { + if (isSignatureRequired && !checkboxMarked) { setCheckboxError(ErrorMessages.ComposeForm.CHECKBOX_REQUIRED); - checkboxValid = false; + messageValid = false; } setMessageInvalid(!messageValid); - setSignatureInvalid(!signatureValid); - setCheckboxInvalid(!checkboxValid); - return { messageValid, signatureValid, checkboxValid }; + return { messageValid }; }, [ selectedRecipientId, @@ -386,21 +368,13 @@ const ComposeForm = props => { const saveDraftHandler = useCallback( async (type, e) => { - const { - messageValid, - signatureValid, - checkboxValid, - } = checkMessageValidity(); + const { messageValid } = checkMessageValidity(); if (type === 'manual') { // if all checks are valid, then save the draft const validSignatureNotRequired = messageValid && !isSignatureRequired; const isSignatureValid = - isSignatureRequired && - signatureValid && - checkboxValid && - !saveError && - messageValid; + isSignatureRequired && !saveError && messageValid; if (validSignatureNotRequired || isSignatureValid) { setNavigationError(null); setSavedDraft(true); @@ -493,18 +467,13 @@ const ComposeForm = props => { const sendMessageHandler = useCallback( async e => { - const { - messageValid, - signatureValid, - checkboxValid, - } = checkMessageValidity(); + const { messageValid } = checkMessageValidity(); // TODO add GA event await setMessageInvalid(false); await setSendMessageFlag(false); const validSignatureNotRequired = messageValid && !isSignatureRequired; - const isSignatureValid = - isSignatureRequired && signatureValid && checkboxValid && messageValid; + const isSignatureValid = isSignatureRequired && messageValid; if (validSignatureNotRequired || isSignatureValid) { setSendMessageFlag(true); @@ -791,9 +760,6 @@ const ComposeForm = props => { !noAssociations && !allTriageGroupsBlocked && ( { + const alertRef = useRef(null); const isSignatureRequiredRef = useRef(); isSignatureRequiredRef.current = isSignatureRequired; + const [alertDisplayed, setAlertDisplayed] = useState(false); const [selectedRecipient, setSelectedRecipient] = useState(null); useEffect( @@ -58,7 +57,7 @@ const RecipientsSelect = ({ setAlertDisplayed(true); } }, - [isSignatureRequired, setAlertDisplayed], + [isSignatureRequired], ); useEffect( @@ -93,12 +92,7 @@ const RecipientsSelect = ({ setAlertDisplayed(true); } }, - [ - recipientsList, - isSignatureRequired, - setSelectedRecipient, - setAlertDisplayed, - ], + [recipientsList, isSignatureRequired, setSelectedRecipient], ); return ( @@ -152,12 +146,9 @@ const RecipientsSelect = ({ RecipientsSelect.propTypes = { recipientsList: PropTypes.array.isRequired, onValueChange: PropTypes.func.isRequired, - alertDisplayed: PropTypes.bool, - alertRef: PropTypes.object, defaultValue: PropTypes.number, error: PropTypes.string, isSignatureRequired: PropTypes.bool, - setAlertDisplayed: PropTypes.func, setCheckboxMarked: PropTypes.func, setElectronicSignature: PropTypes.func, }; From f19a1a98eca2e4e67494baf302cae5a5d2931a43 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Mon, 16 Sep 2024 22:15:55 -0500 Subject: [PATCH 18/30] [MHV-61146] Resolve bug; focus remains on recipient after selection and user can confirm saving draft without electronic signature - all compose form and electronic signature fields must be valid before user can save draft --- .../components/ComposeForm/ComposeForm.jsx | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 5b0e6a997767..79a9edeb6a9c 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -262,7 +262,7 @@ const ComposeForm = props => { useEffect( () => { - if (messageInvalid || isSignatureRequired) { + if (messageInvalid) { focusOnErrorField(); } }, @@ -371,18 +371,18 @@ const ComposeForm = props => { const { messageValid } = checkMessageValidity(); if (type === 'manual') { - // if all checks are valid, then save the draft - const validSignatureNotRequired = messageValid && !isSignatureRequired; - const isSignatureValid = - isSignatureRequired && !saveError && messageValid; - if (validSignatureNotRequired || isSignatureValid) { + await setMessageInvalid(false); + // All fields are valid , save the draft + if (messageValid) { + setSaveError(null); setNavigationError(null); - setSavedDraft(true); setLastFocusableElement(e?.target); - } else focusOnErrorField(); - setUnsavedNavigationError( - ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, - ); + } else { + setUnsavedNavigationError( + ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, + ); + focusOnErrorField(); + } let errorType = null; if ( @@ -395,12 +395,13 @@ const ComposeForm = props => { .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 !== '') { + } else if ( + messageValid && + isSignatureRequired && + (electronicSignature || checkboxError) !== '' + ) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; } - if (errorType) { setSaveError(errorType); if ( @@ -437,9 +438,10 @@ const ComposeForm = props => { }; // saves the draft if all checks are valid or can save draft without signature if ( - (messageValid && !isSignatureRequired) || - (isSignatureRequired && messageValid && saveError !== null) + messageValid && + (!isSignatureRequired || (isSignatureRequired && saveError !== null)) ) { + setSaveError(null); dispatch(saveDraft(formData, type, draftId)); } }, @@ -715,7 +717,6 @@ const ComposeForm = props => { text={saveError.saveDraft} onClick={() => { saveDraftHandler('manual'); - setSaveError(null); }} /> )} From 8fbf8ce79079ad174e87eee4626d021cea81eeab Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Tue, 17 Sep 2024 14:07:38 -0500 Subject: [PATCH 19/30] [MHV-61146] Remove aria-live polite from alert to prevent announcing close button --- .../components/ComposeForm/RecipientsSelect.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx index 42274f7cdec1..44ddeee4d678 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/RecipientsSelect.jsx @@ -119,8 +119,6 @@ const RecipientsSelect = ({ {alertDisplayed && ( -

+

{isSignatureRequired === true ? Prompts.Compose.SIGNATURE_REQUIRED : Prompts.Compose.SIGNATURE_NOT_REQUIRED} From 2b7aa8a773c4c61bb47fa93ddd6ad17588528e0f Mon Sep 17 00:00:00 2001 From: fazilqa Date: Thu, 19 Sep 2024 08:53:31 -0700 Subject: [PATCH 20/30] update method according to correct behavior --- .../mhv-secure-messaging/tests/e2e/pages/ContactListPage.js | 1 - 1 file changed, 1 deletion(-) 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 05b043595607..877914f2b30f 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/ContactListPage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/ContactListPage.js @@ -164,7 +164,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`); }; From 4b5cfe7494ce5ba02717bbf1556c2b30aa56cb69 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Tue, 24 Sep 2024 08:45:24 -0500 Subject: [PATCH 21/30] [MHV-61146] Bug fix, user can save draft with attachment modal --- .../components/ComposeForm/ComposeForm.jsx | 94 ++++++++++--------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 79a9edeb6a9c..9b9a4fbe0102 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -266,7 +266,7 @@ const ComposeForm = props => { focusOnErrorField(); } }, - [isSignatureRequired, messageInvalid], + [messageInvalid], ); useEffect( @@ -369,12 +369,18 @@ const ComposeForm = props => { const saveDraftHandler = useCallback( async (type, e) => { const { messageValid } = checkMessageValidity(); + const validSignatureNotRequired = + messageValid && !isSignatureRequired && !savedDraft; + const isSignatureValid = + isSignatureRequired && messageValid && !saveError; if (type === 'manual') { await setMessageInvalid(false); + await setSavedDraft(false); // All fields are valid , save the draft - if (messageValid) { - setSaveError(null); + if (validSignatureNotRequired || isSignatureValid) { + await setSavedDraft(true); + await setSaveError(null); setNavigationError(null); setLastFocusableElement(e?.target); } else { @@ -384,37 +390,44 @@ const ComposeForm = props => { focusOnErrorField(); } - 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 ( - messageValid && - isSignatureRequired && - (electronicSignature || checkboxError) !== '' - ) { - 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', - }); + const getErrorType = () => { + const hasAttachments = attachments.length > 0; + const hasValidSignature = + isSignatureRequired && electronicSignature !== ''; + const hasSignatureOrCheckboxError = + isSignatureRequired && + (electronicSignature || checkboxError) !== ''; + + let errorType = null; + if (hasAttachments && hasValidSignature) { + errorType = + ErrorMessages.ComposeForm + .UNABLE_TO_SAVE_DRAFT_SIGNATURE_OR_ATTACHMENTS; + } else if (hasAttachments && !savedDraft) { + errorType = + ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT; + } else if (messageValid && hasSignatureOrCheckboxError) { + 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', + }); + } + } else { + setSaveError(null); + } + }; + getErrorType(); } const draftId = draft && draft.messageId; @@ -437,11 +450,7 @@ const ComposeForm = props => { body: messageBody, }; // saves the draft if all checks are valid or can save draft without signature - if ( - messageValid && - (!isSignatureRequired || (isSignatureRequired && saveError !== null)) - ) { - setSaveError(null); + if ((messageValid && !isSignatureRequired) || isSignatureValid) { dispatch(saveDraft(formData, type, draftId)); } }, @@ -464,6 +473,7 @@ const ComposeForm = props => { electronicSignature, checkboxError, dispatch, + savedDraft, ], ); @@ -514,9 +524,6 @@ const ComposeForm = props => { const unsavedDraft = isEditPopulatedForm() && !deleteButtonClicked; - if (!isEditPopulatedForm() || !isSavedEdits()) { - setSavedDraft(false); - } let error = null; if (isBlankForm() || savedDraft) { error = null; @@ -707,7 +714,10 @@ const ComposeForm = props => { {saveError?.editDraft && ( setSaveError(null)} + onClick={() => { + setSavedDraft(false); + setSaveError(null); + }} /> )} {saveError?.saveDraft && ( From c47aa2891d81c53ff0da1abd952eea52d4afffe2 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Tue, 24 Sep 2024 18:59:22 -0500 Subject: [PATCH 22/30] [MHV-61146] Cleanup unit tests and ElectronicSignature fields must be populated before sending a msg fix --- .../components/ComposeForm/ComposeForm.jsx | 79 +++++++++++-------- .../Compose/ComposeForm.unit.spec.jsx | 49 ++++-------- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 9b9a4fbe0102..77dfd64d47c4 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -322,6 +322,9 @@ const ComposeForm = props => { const checkMessageValidity = useCallback( () => { let messageValid = true; + let signatureValid = true; + let checkboxValid = true; + if ( selectedRecipientId === '0' || selectedRecipientId === '' || @@ -344,15 +347,15 @@ const ComposeForm = props => { } if (isSignatureRequired && !electronicSignature) { setSignatureError(ErrorMessages.ComposeForm.SIGNATURE_REQUIRED); - messageValid = false; + signatureValid = false; } if (isSignatureRequired && !checkboxMarked) { setCheckboxError(ErrorMessages.ComposeForm.CHECKBOX_REQUIRED); - messageValid = false; + checkboxValid = false; } setMessageInvalid(!messageValid); - return { messageValid }; + return { messageValid, signatureValid, checkboxValid }; }, [ selectedRecipientId, @@ -368,27 +371,23 @@ const ComposeForm = props => { const saveDraftHandler = useCallback( async (type, e) => { - const { messageValid } = checkMessageValidity(); + const { + messageValid, + signatureValid, + checkboxValid, + } = checkMessageValidity(); const validSignatureNotRequired = messageValid && !isSignatureRequired && !savedDraft; - const isSignatureValid = - isSignatureRequired && messageValid && !saveError; if (type === 'manual') { - await setMessageInvalid(false); - await setSavedDraft(false); - // All fields are valid , save the draft - if (validSignatureNotRequired || isSignatureValid) { - await setSavedDraft(true); - await setSaveError(null); + if (validSignatureNotRequired) { setNavigationError(null); + setSavedDraft(true); setLastFocusableElement(e?.target); - } else { - setUnsavedNavigationError( - ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, - ); - focusOnErrorField(); - } + } else focusOnErrorField(); + setUnsavedNavigationError( + ErrorMessages.Navigation.UNABLE_TO_SAVE_ERROR, + ); const getErrorType = () => { const hasAttachments = attachments.length > 0; @@ -396,17 +395,25 @@ const ComposeForm = props => { isSignatureRequired && electronicSignature !== ''; const hasSignatureOrCheckboxError = isSignatureRequired && - (electronicSignature || checkboxError) !== ''; + !messageInvalid && + (!electronicSignature || checkboxError) !== ''; + const verifyAllFieldsAreValid = + (messageValid && + signatureValid && + checkboxValid && + isSignatureRequired) || + (!isSignatureRequired && messageValid); let errorType = null; - if (hasAttachments && hasValidSignature) { + + if (hasAttachments && hasValidSignature && verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm .UNABLE_TO_SAVE_DRAFT_SIGNATURE_OR_ATTACHMENTS; - } else if (hasAttachments && !savedDraft) { + } else if (hasAttachments && verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT; - } else if (messageValid && hasSignatureOrCheckboxError) { + } else if (hasSignatureOrCheckboxError && verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; } @@ -423,8 +430,6 @@ const ComposeForm = props => { cancelButtonText: 'Delete draft', }); } - } else { - setSaveError(null); } }; getErrorType(); @@ -449,13 +454,18 @@ const ComposeForm = props => { subject, body: messageBody, }; - // saves the draft if all checks are valid or can save draft without signature - if ((messageValid && !isSignatureRequired) || isSignatureValid) { + if ( + (messageValid && !isSignatureRequired) || + (isSignatureRequired && messageValid && saveError !== null) + ) { dispatch(saveDraft(formData, type, draftId)); } }, [ checkMessageValidity, + isSignatureRequired, + savedDraft, + saveError, draft, debouncedRecipient, selectedRecipientId, @@ -466,26 +476,29 @@ const ComposeForm = props => { debouncedMessageBody, messageBody, fieldsString, - isSignatureRequired, - saveError, + messageInvalid, setUnsavedNavigationError, attachments.length, electronicSignature, checkboxError, dispatch, - savedDraft, ], ); const sendMessageHandler = useCallback( async e => { - const { messageValid } = checkMessageValidity(); + const { + messageValid, + signatureValid, + checkboxValid, + } = checkMessageValidity(); // TODO add GA event await setMessageInvalid(false); await setSendMessageFlag(false); const validSignatureNotRequired = messageValid && !isSignatureRequired; - const isSignatureValid = isSignatureRequired && messageValid; + const isSignatureValid = + isSignatureRequired && messageValid && signatureValid && checkboxValid; if (validSignatureNotRequired || isSignatureValid) { setSendMessageFlag(true); @@ -523,6 +536,9 @@ const ComposeForm = props => { !isSavedEdits(); const unsavedDraft = isEditPopulatedForm() && !deleteButtonClicked; + if (!isEditPopulatedForm() || !isSavedEdits()) { + setSavedDraft(false); + } let error = null; if (isBlankForm() || savedDraft) { @@ -727,6 +743,7 @@ const ComposeForm = props => { text={saveError.saveDraft} onClick={() => { saveDraftHandler('manual'); + setSaveError(null); }} /> )} 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 99b09d0d957a..f99cc823cc80 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 @@ -352,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'); @@ -372,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", @@ -937,46 +938,24 @@ describe('Compose form component', () => { ).id; selectVaSelect(screen.container, tgRecipient); - await waitFor(() => { - selectVaRadio(screen.container, 'COVID'); - expect( - $('va-radio-option[value="COVID"]', screen.container), - ).to.have.attribute('checked', 'true'); - }); - - const subjectInput = 'Test Subject'; - inputVaTextInput(screen.container, subjectInput); - await waitFor(() => { - expect(screen.getByTestId('message-subject-field')).to.have.value( - subjectInput, - ); - }); - - const messageBody = 'test body'; - inputVaTextInput(screen.container, messageBody, 'va-textarea'); - await waitFor(() => { - expect(screen.getByTestId('message-body-field')).to.have.value( - messageBody, - ); - }); - const checkboxSelector = `va-checkbox[label='${ ElectronicSignatureBox.CHECKBOX_LABEL }']`; - const checkbox = screen.container.querySelector(checkboxSelector); - checkVaCheckbox(checkbox, false); - const sendButton = screen.getByTestId('send-button'); - fireEvent.click(sendButton); - // after clicking send, validation checks on Electronic Signature component runs 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', ''); + checkVaCheckbox(checkbox, true); + expect(checkbox).to.have.attribute('error', ''); + }); }); }); From 4c90da2714de36bde29aa027e023dd66ed7ecb9a Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Wed, 25 Sep 2024 11:26:16 -0500 Subject: [PATCH 23/30] [MHV-61146] cleanup --- .../components/ComposeForm/ComposeForm.jsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index 77dfd64d47c4..eea3e20d012b 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -393,10 +393,6 @@ const ComposeForm = props => { const hasAttachments = attachments.length > 0; const hasValidSignature = isSignatureRequired && electronicSignature !== ''; - const hasSignatureOrCheckboxError = - isSignatureRequired && - !messageInvalid && - (!electronicSignature || checkboxError) !== ''; const verifyAllFieldsAreValid = (messageValid && signatureValid && @@ -413,7 +409,7 @@ const ComposeForm = props => { } else if (hasAttachments && verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT; - } else if (hasSignatureOrCheckboxError && verifyAllFieldsAreValid) { + } else if (verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; } From 886837e043c31a2bd299663c04f936e9806bd0ef Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Wed, 25 Sep 2024 13:05:45 -0500 Subject: [PATCH 24/30] cleanup --- .../components/ComposeForm/ComposeForm.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx index eea3e20d012b..43d5a8532078 100644 --- a/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx +++ b/src/applications/mhv-secure-messaging/components/ComposeForm/ComposeForm.jsx @@ -398,7 +398,7 @@ const ComposeForm = props => { signatureValid && checkboxValid && isSignatureRequired) || - (!isSignatureRequired && messageValid); + (!isSignatureRequired && messageValid && validSignatureNotRequired); let errorType = null; @@ -409,7 +409,7 @@ const ComposeForm = props => { } else if (hasAttachments && verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_ATTACHMENT; - } else if (verifyAllFieldsAreValid) { + } else if (!validSignatureNotRequired && verifyAllFieldsAreValid) { errorType = ErrorMessages.ComposeForm.UNABLE_TO_SAVE_DRAFT_SIGNATURE; } From 3c9a31cdd79f6f3b1bf3ded5ecc9302c219e14fc Mon Sep 17 00:00:00 2001 From: fazilqa Date: Wed, 25 Sep 2024 11:19:23 -0700 Subject: [PATCH 25/30] update focus assertion --- ...secure-messaging-keyboard-nav-save-draft.cypress.spec.js | 6 ++++-- .../tests/e2e/pages/PatientComposePage.js | 4 ++-- .../mhv-secure-messaging/tests/e2e/utils/constants.js | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) 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..20fdf0374360 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,7 +22,9 @@ 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(); 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 aabfb49db886..93467cfe617a 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js @@ -425,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'); }; 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 46921a982251..2b8d479e249f 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js @@ -140,6 +140,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"]', From 4307e7493c4ffae3f9edbf84108af6119302c8f9 Mon Sep 17 00:00:00 2001 From: fazilqa Date: Wed, 25 Sep 2024 11:34:44 -0700 Subject: [PATCH 26/30] update constants --- .../secure-messaging-keyboard-nav-save-draft.cypress.spec.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 20fdf0374360..18ba59893d2e 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 @@ -25,8 +25,6 @@ describe('Check confirmation message after save draft', () => { PatientComposePage.verifyAlertFocusFocus(); cy.get(Locators.BUTTONS.ALERT_CLOSE).click(); - cy.get('.sm-breadcrumb-list-item') - .find('a') - .click(); + cy.get(Locators.BACK_TO).click(); }); }); From 8c86d74f6fd13c635e1bbd038907c254439c5c65 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Fri, 27 Sep 2024 09:01:00 -0500 Subject: [PATCH 27/30] checking for interpolation errors --- .../tests/components/Compose/ComposeForm.unit.spec.jsx | 4 ++-- ...messaging-message-thread-detail-reply-page.cypress.spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 f99cc823cc80..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 @@ -938,9 +938,9 @@ describe('Compose form component', () => { ).id; selectVaSelect(screen.container, tgRecipient); - const checkboxSelector = `va-checkbox[label='${ + const checkboxSelector = `va-checkbox[label="${ ElectronicSignatureBox.CHECKBOX_LABEL - }']`; + }"]`; await waitFor(() => { const sendButton = screen.getByTestId('send-button'); 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); From 08dc6286beca5b465157546b3049362716380ccd Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Mon, 30 Sep 2024 07:32:14 -0500 Subject: [PATCH 28/30] [MHV-61146] Adding cy test updates --- ...secure-messaging-keyboard-nav-save-draft.cypress.spec.js | 6 +++++- .../tests/e2e/pages/PatientComposePage.js | 4 ++-- .../mhv-secure-messaging/tests/e2e/utils/constants.js | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) 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..bd2a9928afc9 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', () => { @@ -23,8 +23,12 @@ describe('Check confirmation message after save draft', () => { 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/PatientComposePage.js b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js index aabfb49db886..77c630d40fc4 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/pages/PatientComposePage.js @@ -425,8 +425,8 @@ class PatientComposePage { .should('be.visible'); }; - verifyDraftSaveButtonOnFocus = () => { - cy.get(Locators.BUTTONS.SAVE_DRAFT) + verifyAlertFocusFocus = () => { + cy.get(`.first-focuasable-child`) .should('exist') .and('be.focused'); }; 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 46921a982251..2b8d479e249f 100644 --- a/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js +++ b/src/applications/mhv-secure-messaging/tests/e2e/utils/constants.js @@ -140,6 +140,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"]', From 379ee65479ff40978cbd744e165dce0ad3b176c3 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Mon, 30 Sep 2024 16:15:17 -0500 Subject: [PATCH 29/30] [MHV-61146] Fix validation focus on Reply page --- .../components/ComposeForm/ReplyDraftItem.jsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) 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)); From ad69100cf2456779713ac96cfb5115de39948076 Mon Sep 17 00:00:00 2001 From: Vic Saleem Date: Tue, 1 Oct 2024 09:17:26 -0500 Subject: [PATCH 30/30] Update secure-messaging-keyboard-nav-save-draft.cypress.spec.js --- .../secure-messaging-keyboard-nav-save-draft.cypress.spec.js | 1 - 1 file changed, 1 deletion(-) 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 bd2a9928afc9..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 @@ -22,7 +22,6 @@ describe('Check confirmation message after save draft', () => { cy.injectAxe(); cy.axeCheck(AXE_CONTEXT); - PatientComposePage.verifyDraftSaveButtonOnFocus(); PatientComposePage.verifyAlertFocusFocus(); cy.get(Locators.BUTTONS.ALERT_CLOSE).click();