From b5bb8ba3b5743386a2208648fa78229ba4d8e07b Mon Sep 17 00:00:00 2001 From: Chris Alexander Date: Wed, 7 Aug 2024 13:26:44 -0600 Subject: [PATCH] feature/8898-UpdateClaimPhaseComponent (#9083) Co-authored-by: Rachael Bontrager --- VAMobile/e2e/tests/Claims.e2e.ts | 315 ++++++++++-------- .../src/api/types/ClaimsAndAppealsData.ts | 1 + VAMobile/src/constants/claims.ts | 40 +++ .../ClaimDetailsScreen/ClaimDetailsScreen.tsx | 9 +- .../ClaimStatus/ClaimStatus.test.tsx | 20 +- .../ClaimStatus/ClaimStatus.tsx | 9 +- .../ClaimTimeline/ClaimPhase.test.tsx | 97 +++--- .../ClaimStatus/ClaimTimeline/ClaimPhase.tsx | 181 +++++----- .../ClaimTimeline/ClaimTimeline.test.tsx | 30 +- .../ClaimTimeline/ClaimTimeline.tsx | 47 ++- .../ClaimTimeline/DEPRECATED_ClaimPhase.tsx | 163 +++++++++ .../BenefitsScreen/ClaimsScreen/claimData.ts | 1 + VAMobile/src/store/api/demo/mocks/claims.json | 1 + VAMobile/src/translations/en/common.json | 44 ++- VAMobile/src/utils/claims.tsx | 11 +- 15 files changed, 621 insertions(+), 348 deletions(-) create mode 100644 VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/DEPRECATED_ClaimPhase.tsx diff --git a/VAMobile/e2e/tests/Claims.e2e.ts b/VAMobile/e2e/tests/Claims.e2e.ts index c5c66cbcf3d..d79a8f5b2b6 100644 --- a/VAMobile/e2e/tests/Claims.e2e.ts +++ b/VAMobile/e2e/tests/Claims.e2e.ts @@ -19,13 +19,22 @@ export const ClaimsE2eIdConstants = { CLAIM_5_ID: 'Compensation Received March 22, 2019', CLAIM_6_ID: 'Dependency Received January 01, 2016', CLOSED_CLAIM_DECISION_LETTER_ID: 'Compensation Decision letter ready Received January 01, 2021', - CLAIM_1_STATUS_STEP_1_ID: 'Step 1 of 5. completed. Claim received July 20, 2021', - CLAIM_1_STATUS_STEP_2_ID: 'Step 2 of 5. current. Initial review July 20, 2021', - CLAIM_1_STATUS_STEP_3_ID: 'Step 3 of 5. Evidence gathering, review, and decision', - CLAIM_1_STATUS_STEP_4_ID: 'Step 4 of 5. Preparation for notification', - CLAIM_1_STATUS_STEP_5_ID: 'Step 5 of 5. Complete', + CLAIM_3_STATUS_STEP_1_ID: 'Step 1. Claim received. Complete.', + CLAIM_3_STATUS_STEP_2_ID: 'Step 2. Initial review. Current step. Step 1 complete.', + CLAIM_3_STATUS_STEP_3_ID: 'Step 3. Evidence gathering, review, and decision. Incomplete.', + CLAIM_3_STATUS_STEP_4_ID: 'Step 4. Preparation for notification. Incomplete.', + CLAIM_3_STATUS_STEP_5_ID: 'Step 5. Complete. Incomplete.', + CLAIM_4_STATUS_STEP_1_ID: 'Step 1. Claim received. Complete.', + CLAIM_4_STATUS_STEP_2_ID: 'Step 2. Initial review. Complete.', + CLAIM_4_STATUS_STEP_3_ID: 'Step 3. Evidence gathering. Current step. Step 1 through 2 complete.', + CLAIM_4_STATUS_STEP_4_ID: 'Step 4. Evidence review. Incomplete.', + CLAIM_4_STATUS_STEP_5_ID: 'Step 5. Rating. Incomplete.', + CLAIM_4_STATUS_STEP_6_ID: 'Step 6. Preparing decision letter. Incomplete.', + CLAIM_4_STATUS_STEP_7_ID: 'Step 7. Final review. Incomplete.', + CLAIM_4_STATUS_STEP_8_ID: 'Step 8. Claim decided. Incomplete.', GET_CLAIMS_LETTER_BUTTON_ID: 'getClaimLettersTestID', FILE_REQUEST_BUTTON_ID: 'Review file requests', + CURRENT_STEP_TEXT: 'Current step', TAKE_OR_SELECT_PHOTOS_CAMERA_OPTION_TEXT: device.getPlatform() === 'ios' ? 'Camera' : 'Camera ', TAKE_OR_SELECT_PHOTOS_PHOTO_GALLERY_OPTION_TEXT: device.getPlatform() === 'ios' ? 'Photo Gallery' : 'Photo gallery ', SELECT_A_FILE_FILE_FOLDER_OPTION_TEXT: device.getPlatform() === 'ios' ? 'File Folder' : 'File folder ', @@ -56,25 +65,50 @@ describe('Claims Screen', () => { await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_6_ID))).toExist() }) - it('Verify the claim status detail page', async () => { + it('Verify the claim status detail page (8-step claim)', async () => { + await element(by.id(ClaimsE2eIdConstants.CLAIM_4_ID)).tap() + await expect(element(by.text('Status'))).toExist() + await expect(element(by.text('Files'))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_1_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_2_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_3_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_4_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_5_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_6_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_7_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_8_ID))).toExist() + await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)).scrollTo('top') + await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() + }) + + it('Verify the claim status detail page (5-step claim)', async () => { await element(by.id(ClaimsE2eIdConstants.CLAIM_3_ID)).tap() await expect(element(by.text('Status'))).toExist() await expect(element(by.text('Files'))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_1_ID))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_2_ID))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_3_ID))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_4_ID))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_5_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_1_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_2_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_3_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_4_ID))).toExist() + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_5_ID))).toExist() }) - it('Open claim recieved and give the correct details', async () => { - await element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_1_ID)).atIndex(0).tap() - await expect(element(by.text('Thank you. VA received your claim'))).toExist() + it('Open initial review claim and give the correct details', async () => { + await expect(element(by.text('Initial review'))).toExist() + await expect(element(by.text(ClaimsE2eIdConstants.CURRENT_STEP_TEXT))).toExist() + await expect( + element( + by.text('Your claim has been assigned to a reviewer who is determining if additional information is needed.'), + ), + ).toExist() }) - it('Close claim recived and verify that no details are still displayed', async () => { - await element(by.id(ClaimsE2eIdConstants.CLAIM_1_STATUS_STEP_1_ID)).atIndex(0).tap() - await expect(element(by.text('Thank you. VA received your claim'))).not.toExist() + it('Close initial review claim and verify that no details are still displayed', async () => { + await element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_2_ID)).atIndex(0).tap() + await expect( + element( + by.text('Your claim has been assigned to a reviewer who is determining if additional information is needed.'), + ), + ).not.toExist() }) it('Verify VA sometimes combine claims information', async () => { @@ -104,126 +138,134 @@ describe('Claims Screen', () => { await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() }) - it('should tap on a claim and verify the dates match', async () => { + it('automatically expands and scrolls to current step', async () => { await element(by.id(ClaimsE2eIdConstants.CLAIM_4_ID)).tap() - await expect(element(by.text('Received January 01, 2021'))).toExist() - }) - - it('should verify that the review file request button is visible in step 3', async () => { - await waitFor(element(by.text('Review file requests'))) - .toBeVisible() - .whileElement(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)) - .scroll(100, 'down') + await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_3_ID))).toExist() + await expect(element(by.text(ClaimsE2eIdConstants.CURRENT_STEP_TEXT))).toExist() }) - it('expand step 3 and verify that the review file request button is visible', async () => { - await element(by.id('Step 3 of 5. current. Evidence gathering, review, and decision June 4, 2021')).tap() - await expect(element(by.id(ClaimsE2eIdConstants.FILE_REQUEST_BUTTON_ID))).toExist() - await element(by.id('Step 3 of 5. current. Evidence gathering, review, and decision June 4, 2021')).tap() + it('should tap on a claim and verify the dates match', async () => { + await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)).scrollTo('top') + await expect(element(by.text('Received January 01, 2021'))).toExist() }) it('verify number of requests in review file requests', async () => { - await element(by.id(ClaimsE2eIdConstants.FILE_REQUEST_BUTTON_ID)).tap() await expect(element(by.label('You have 3 file requests from V-A '))).toExist() - }) - - it('verify that the user is sent to the file upload page', async () => { - await element(by.text('Dental disability - More information needed')).tap() - await expect(element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT))).toExist() - await expect(element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT))).toExist() - }) - - it('should back out of the file request screen and reenter a new file request screen', async () => { - await element(by.text('Requests')).tap() - await element(by.text('Accidental injury - 21-4176 needed')).tap() - }) - - it('verify the select files screen displays the correct info', async () => { - await element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).tap() - await expect(element(by.text('Select a file to upload for Accidental injury - 21-4176 needed'))).toExist() - await expect(element(by.label(ClaimsE2eIdConstants.MAXIMUM_FILE_SIZE_LABEL))).toExist() - await expect(element(by.text(ClaimsE2eIdConstants.ACCEPTED_FILE_TYPES_TEXT))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(1)).toExist() - }) - - it('verify tap select a file options', async () => { - if (device.getPlatform() === 'android') { - await element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(0).tap() - } else { - await element(by.id(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(0).tap() - } - await expect(element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_FILE_FOLDER_OPTION_TEXT))).toExist() - await expect(element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT))).toExist() - }) - - it('should navigate back to the request select a file screen', async () => { - if (device.getPlatform() === 'android') { - await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).tap() - } else { - await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).atIndex(1).tap() - } - await element(by.text(CommonE2eIdConstants.CANCEL_UNIVERSAL_TEXT)).tap() - }) - - it('verify take or select photos panel', async () => { - await element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).tap() - await expect(element(by.text('This feature is not yet accessible to screen readers'))).toExist() - await expect(element(by.label(ClaimsE2eIdConstants.MAXIMUM_FILE_SIZE_LABEL))).toExist() - await expect(element(by.text(ClaimsE2eIdConstants.ACCEPTED_FILE_TYPES_TEXT))).toExist() - await expect(element(by.id(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).atIndex(1)).toExist() - }) - - it('should select take or select photos and verify the options given', async () => { - await element(by.id('takePhotosTestID')).scrollTo('bottom') - if (device.getPlatform() === 'android') { - await element(by.id(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).atIndex(0).tap() - } else { - await element(by.id(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).atIndex(1).tap() - } - await expect(element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_CAMERA_OPTION_TEXT))).toExist() - await expect(element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_PHOTO_GALLERY_OPTION_TEXT))).toExist() - }) - - it('should navigate back to the file request screen', async () => { - if (device.getPlatform() === 'android') { - await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).tap() - } else { - await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).atIndex(1).tap() - } - await element(by.text(CommonE2eIdConstants.CANCEL_UNIVERSAL_TEXT)).tap() - await element(by.text('Requests')).tap() - }) - - it('verify Review evaluation details', async () => { - await element(by.id('fileRequestPageTestID')).scrollTo('bottom') - await element(by.id('Review evaluation details')).tap() - await expect(element(by.text('Claim evaluation'))).toExist() - await expect( - element( - by.text( - 'I have submitted all evidence that will support my claim and I’m not going to turn in any more information. I would like VA to make a decision on my claim based on the information already provided. (Required)', - ), - ), - ).toExist() - await expect(element(by.id('Request claim evaluation'))).toExist() - }) - - it('verify error is displayed when request claim evaluation isnt checked', async () => { - await element(by.id('askForClaimDecisionPageTestID')).scrollTo('bottom') - await element(by.id('Request claim evaluation')).tap() - await expect(element(by.text('Check the box to confirm the information is correct.'))).toExist() - }) - - it('should navigate back to the claims history screen', async () => { - await element(by.text('Cancel')).tap() - await element(by.text('Claim')).tap() await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() }) + /******* Commented out because file request/review details buttons are moving *******/ + // + // it('should verify that the review file request button is visible in step 3', async () => { + // await waitFor(element(by.text('Review file requests'))) + // .toBeVisible() + // .whileElement(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)) + // .scroll(100, 'down') + // }) + + // it('expand step 3 and verify that the review file request button is visible', async () => { + // await element(by.id('Step 3 of 5. current. Evidence gathering, review, and decision June 4, 2021')).tap() + // await expect(element(by.id(ClaimsE2eIdConstants.FILE_REQUEST_BUTTON_ID))).toExist() + // await element(by.id('Step 3 of 5. current. Evidence gathering, review, and decision June 4, 2021')).tap() + // }) + + // it('verify that the user is sent to the file upload page', async () => { + // await element(by.text('Dental disability - More information needed')).tap() + // await expect(element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT))).toExist() + // await expect(element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT))).toExist() + // }) + + // it('should back out of the file request screen and reenter a new file request screen', async () => { + // await element(by.text('Requests')).tap() + // await element(by.text('Accidental injury - 21-4176 needed')).tap() + // }) + + // it('verify the select files screen displays the correct info', async () => { + // await element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).tap() + // await expect(element(by.text('Select a file to upload for Accidental injury - 21-4176 needed'))).toExist() + // await expect(element(by.label(ClaimsE2eIdConstants.MAXIMUM_FILE_SIZE_LABEL))).toExist() + // await expect(element(by.text(ClaimsE2eIdConstants.ACCEPTED_FILE_TYPES_TEXT))).toExist() + // await expect(element(by.id(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(1)).toExist() + // }) + + // it('verify tap select a file options', async () => { + // if (device.getPlatform() === 'android') { + // await element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(0).tap() + // } else { + // await element(by.id(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(0).tap() + // } + // await expect(element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_FILE_FOLDER_OPTION_TEXT))).toExist() + // await expect(element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT))).toExist() + // }) + + // it('should navigate back to the request select a file screen', async () => { + // if (device.getPlatform() === 'android') { + // await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).tap() + // } else { + // await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).atIndex(1).tap() + // } + // await element(by.text(CommonE2eIdConstants.CANCEL_UNIVERSAL_TEXT)).tap() + // }) + + // it('verify take or select photos panel', async () => { + // await element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).tap() + // await expect(element(by.text('This feature is not yet accessible to screen readers'))).toExist() + // await expect(element(by.label(ClaimsE2eIdConstants.MAXIMUM_FILE_SIZE_LABEL))).toExist() + // await expect(element(by.text(ClaimsE2eIdConstants.ACCEPTED_FILE_TYPES_TEXT))).toExist() + // await expect(element(by.id(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).atIndex(1)).toExist() + // }) + + // it('should select take or select photos and verify the options given', async () => { + // await element(by.id('takePhotosTestID')).scrollTo('bottom') + // if (device.getPlatform() === 'android') { + // await element(by.id(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).atIndex(0).tap() + // } else { + // await element(by.id(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_TEXT)).atIndex(1).tap() + // } + // await expect(element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_CAMERA_OPTION_TEXT))).toExist() + // await expect(element(by.text(ClaimsE2eIdConstants.TAKE_OR_SELECT_PHOTOS_PHOTO_GALLERY_OPTION_TEXT))).toExist() + // }) + + // it('should navigate back to the file request screen', async () => { + // if (device.getPlatform() === 'android') { + // await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).tap() + // } else { + // await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).atIndex(1).tap() + // } + // await element(by.text(CommonE2eIdConstants.CANCEL_UNIVERSAL_TEXT)).tap() + // await element(by.text('Requests')).tap() + // }) + + // it('verify Review evaluation details', async () => { + // await element(by.id('fileRequestPageTestID')).scrollTo('bottom') + // await element(by.id('Review evaluation details')).tap() + // await expect(element(by.text('Claim evaluation'))).toExist() + // await expect( + // element( + // by.text( + // 'I have submitted all evidence that will support my claim and I’m not going to turn in any more information. I would like VA to make a decision on my claim based on the information already provided. (Required)', + // ), + // ), + // ).toExist() + // await expect(element(by.id('Request claim evaluation'))).toExist() + // }) + + // it('verify error is displayed when request claim evaluation isnt checked', async () => { + // await element(by.id('askForClaimDecisionPageTestID')).scrollTo('bottom') + // await element(by.id('Request claim evaluation')).tap() + // await expect(element(by.text('Check the box to confirm the information is correct.'))).toExist() + // }) + + // it('should navigate back to the claims history screen', async () => { + // await element(by.text('Cancel')).tap() + // await element(by.text('Claim')).tap() + // await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() + // }) + it('should verify details of claim on step 1', async () => { await element(by.id(ClaimsE2eIdConstants.CLAIM_1_ID)).tap() - await expect(element(by.id('Step 1 of 5. current. Claim received December 4, 2023'))).toExist() - await element(by.id('Step 1 of 5. current. Claim received December 4, 2023')).tap() + await expect(element(by.id('Step 1. Claim received. Current step.'))).toExist() + await expect(element(by.text(ClaimsE2eIdConstants.CURRENT_STEP_TEXT))).toExist() await expect(element(by.text('Thank you. VA recieved your claim'))) await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() }) @@ -234,13 +276,18 @@ describe('Claims Screen', () => { await openClaims() await openClaimsHistory() await element(by.id(ClaimsE2eIdConstants.CLAIM_3_ID)).tap() - await expect(element(by.id('Step 2 of 5. current. Initial review July 20, 2021'))).toExist() - await element(by.id('Step 2 of 5. current. Initial review July 20, 2021')).tap() + await expect(element(by.id('Step 2. Initial review. Current step. Step 1 complete.'))).toExist() await expect( element( by.text('Your claim has been assigned to a reviewer who is determining if additional information is needed.'), ), ).toExist() + await element(by.id('Step 2. Initial review. Current step. Step 1 complete.')).tap() + await expect( + element( + by.text('Your claim has been assigned to a reviewer who is determining if additional information is needed.'), + ), + ).not.toExist() await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() }) @@ -251,9 +298,11 @@ describe('Claims Screen', () => { .scroll(100, 'down') await element(by.id(ClaimsE2eIdConstants.CLAIM_5_ID)).tap() await expect( - element(by.id('Step 3 of 5. current. Evidence gathering, review, and decision June 4, 2021')), + element(by.id('Step 3. Evidence gathering, review, and decision. Current step. Step 1 through 2 complete.')), ).toExist() - await element(by.id('Step 3 of 5. current. Evidence gathering, review, and decision June 4, 2021')).tap() + await element( + by.id('Step 3. Evidence gathering, review, and decision. Current step. Step 1 through 2 complete.'), + ).tap() await expect( element( by.text( @@ -274,8 +323,9 @@ describe('Claims Screen', () => { .whileElement(by.id('claimsHistoryID')) .scroll(100, 'down') await element(by.id(ClaimsE2eIdConstants.CLAIM_6_ID)).tap() - await expect(element(by.id('Step 4 of 5. current. Preparation for notification '))).toExist() - await element(by.id('Step 4 of 5. current. Preparation for notification ')).tap() + await expect( + element(by.id('Step 4. Preparation for notification. Current step. Step 1 through 3 complete.')), + ).toExist() await expect(element(by.text('We are preparing your claim decision packet to be mailed.'))).toExist() await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() }) @@ -284,8 +334,7 @@ describe('Claims Screen', () => { await element(by.id('claimsHistoryID')).scrollTo('top') await element(by.id(ClaimsE2eIdConstants.CLAIM_2_ID)).tap() await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)).scrollTo('bottom') - await expect(element(by.id('Step 5 of 5. completed. Complete '))).toExist() - await element(by.id('Step 5 of 5. completed. Complete ')).tap() + await element(by.id('Step 5. Complete. Complete.')).tap() await expect(element(by.text('Complete')).atIndex(1)).toExist() await element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT)).tap() }) diff --git a/VAMobile/src/api/types/ClaimsAndAppealsData.ts b/VAMobile/src/api/types/ClaimsAndAppealsData.ts index ea357c37b50..a64e283cf67 100644 --- a/VAMobile/src/api/types/ClaimsAndAppealsData.ts +++ b/VAMobile/src/api/types/ClaimsAndAppealsData.ts @@ -472,6 +472,7 @@ export type ClaimAttributesData = { currentPhaseBack: boolean requestedDecision: boolean claimType: string + claimTypeCode: string updatedAt: string contentionList: Array vaRepresentative: string diff --git a/VAMobile/src/constants/claims.ts b/VAMobile/src/constants/claims.ts index e70c60d36ea..bf8921c6535 100644 --- a/VAMobile/src/constants/claims.ts +++ b/VAMobile/src/constants/claims.ts @@ -8,4 +8,44 @@ export const ClaimTypeConstants: { export type ClaimType = 'ACTIVE' | 'CLOSED' +// These are claim type codes for Disability Compensation claims. Claim type codes listed here +// are used in isDisabilityCompensationClaim() to show the 8 claim phase steps instead of 5. +export const DISABILITY_COMPENSATION_CLAIM_TYPE_CODES = [ + '010INITMORE8', + '010LCMPPIDES', + '010LCOMP', + '010LCOMPBDD', + '010LCOMPD2D', + '010LCOMPIDES', + '010NADIDES8', + '020BDDNO', + '020CLMINC', + '020EPDSUPP', + '020IDESRRNAD', + '020NADIDESNO', + '020NEW', + '020NEWIDES', + '020NEWPMC', + '020NHPNH10', + '020NI', + '020PNI', + '020PREDSUPP', + '020RCOMP', + '020RI', + '020RN', + '020RRNADIDES', + '020RSCDTH', + '020RSCDTHPMC', + '020SD2D', + '020SMB', + '020SUPP', + '110INITLESS8', + '110LCMP7IDES', + '110LCOMP7', + '110LCOMP7BDD', + '110LCOMPD2D', + '110LCOMPIDES', + '110NADIDES7', +] + export const MAX_NUM_PHOTOS = 10 diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx index 01620707058..b6b323aac15 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx @@ -1,5 +1,6 @@ -import React, { useCallback, useEffect, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' +import { ScrollView } from 'react-native' import { useFocusEffect } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' @@ -42,6 +43,7 @@ type ClaimDetailsScreenProps = StackScreenProps(null) const navigateTo = useRouteNavigation() const controlLabels = [ t('claimDetails.status'), @@ -207,6 +209,7 @@ function ClaimDetailsScreen({ navigation, route }: ClaimDetailsScreenProps) { backLabel={backLabel} backLabelOnPress={navigation.goBack} title={t('claimDetails.title')} + scrollViewProps={{ scrollViewRef }} testID="ClaimDetailsScreen"> {loadingClaim ? ( @@ -234,7 +237,9 @@ function ClaimDetailsScreen({ navigation, route }: ClaimDetailsScreenProps) { - {claim && selectedTab === 0 && } + {claim && selectedTab === 0 && ( + + )} {claim && selectedTab === 1 && !featureEnabled('claimPhaseExpansion') && } {claim && selectedTab === 1 && featureEnabled('claimPhaseExpansion') && } diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.test.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.test.tsx index d1154f0bc6c..2df1724f622 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.test.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.test.tsx @@ -1,4 +1,5 @@ -import React from 'react' +import React, { RefObject } from 'react' +import { ScrollView } from 'react-native' import { fireEvent, screen } from '@testing-library/react-native' @@ -27,6 +28,7 @@ context('ClaimStatus', () => { const props = mockNavProps({ claim: { ...claim, attributes: { ...claim.attributes, maxEstDate: maxEstDate } }, claimType, + scrollViewRef: {} as RefObject, }) render() } @@ -37,14 +39,14 @@ context('ClaimStatus', () => { }) it('Renders ClaimStatus', () => { - expect(screen.getAllByText('You have 2 file requests from VA')).toBeTruthy() - expect(screen.getByTestId('Step 1 of 5. completed. Claim received June 6, 2019')).toBeTruthy() - expect(screen.getByTestId('Step 2 of 5. completed. Initial review June 6, 2019')).toBeTruthy() - expect( - screen.getByTestId('Step 3 of 5. current. Evidence gathering, review, and decision July 16, 2020'), - ).toBeTruthy() - expect(screen.getByTestId('Step 4 of 5. Preparation for notification')).toBeTruthy() - expect(screen.getByTestId('Step 5 of 5. Complete')).toBeTruthy() + expect(screen.getByLabelText('Step 1. Claim received. Complete.')).toBeTruthy() + expect(screen.getByLabelText('Step 2. Initial review. Complete.')).toBeTruthy() + expect(screen.getByLabelText('Step 3. Evidence gathering. Current step. Step 1 through 2 complete.')).toBeTruthy() + expect(screen.getByLabelText('Step 4. Evidence review. Incomplete.')).toBeTruthy() + expect(screen.getByLabelText('Step 5. Rating. Incomplete.')).toBeTruthy() + expect(screen.getByLabelText('Step 6. Preparing decision letter. Incomplete.')).toBeTruthy() + expect(screen.getByLabelText('Step 7. Final review. Incomplete.')).toBeTruthy() + expect(screen.getByLabelText('Step 8. Claim decided. Incomplete.')).toBeTruthy() expect(screen.getByText('Why does VA sometimes combine claims?')).toBeTruthy() expect(screen.getByText("What should I do if I disagree with VA's decision on my disability claim?")).toBeTruthy() }) diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.tsx index 7d841443450..065806b3264 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimStatus.tsx @@ -1,5 +1,6 @@ -import React, { useRef } from 'react' +import React, { RefObject, useRef } from 'react' import { useTranslation } from 'react-i18next' +import { ScrollView } from 'react-native' import { Button } from '@department-of-veterans-affairs/mobile-component-library' @@ -26,12 +27,14 @@ type ClaimStatusProps = { claim: ClaimData /** indicates either open or closed claim */ claimType: ClaimType + /** ref to parent scrollView, used for auto scroll */ + scrollViewRef: RefObject } /** * Component for rendering the details area of a claim when selected on the ClaimDetailsScreen */ -function ClaimStatus({ claim, claimType }: ClaimStatusProps) { +function ClaimStatus({ claim, claimType, scrollViewRef }: ClaimStatusProps) { const { t } = useTranslation(NAMESPACE.COMMON) const navigateTo = useRouteNavigation() const { data: userAuthorizedServices } = useAuthorizedServices() @@ -81,7 +84,7 @@ function ClaimStatus({ claim, claimType }: ClaimStatusProps) { return ( - {claim && } + {claim && } {false && } diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.test.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.test.tsx index fefe380a93f..26cdff3fe51 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.test.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.test.tsx @@ -1,11 +1,13 @@ -import React from 'react' +import React, { RefObject } from 'react' +import { ScrollView } from 'react-native' import { fireEvent, screen } from '@testing-library/react-native' -import { context, render } from 'testUtils' +import { context, render, when } from 'testUtils' +import { featureEnabled } from 'utils/remoteConfig' import { claim } from '../../../claimData' -import ClaimPhase from './ClaimPhase' +import ClaimPhase, { ClaimPhaseProps } from './ClaimPhase' const mockNavigationSpy = jest.fn() jest.mock('utils/hooks', () => { @@ -16,13 +18,16 @@ jest.mock('utils/hooks', () => { } }) +jest.mock('utils/remoteConfig') +when(featureEnabled).calledWith('claimPhaseExpansion').mockReturnValue(true) + context('ClaimPhase', () => { const initializeTestInstance = (phase: number, current: number) => { - const props = { + const props: ClaimPhaseProps = { phase, - current, - attributes: claim.attributes, + attributes: { ...claim.attributes, phase: current }, claimID: claim.id, + scrollViewRef: {} as RefObject, } render() @@ -30,77 +35,53 @@ context('ClaimPhase', () => { it('initializes correctly', () => { initializeTestInstance(1, 1) - expect(screen.getByTestId('Step 1 of 5. current. Claim received June 6, 2019')).toBeTruthy() + expect(screen.getByLabelText('Step 1. Claim received. Current step.')).toBeTruthy() expect(screen.getByRole('tab')).toBeTruthy() }) describe('when phase is less than current', () => { - it('should render text details after pressing icon', () => { + it('renders correct label and text after press', () => { initializeTestInstance(1, 2) + expect(screen.getByLabelText('Step 1. Claim received. Complete.')).toBeTruthy() fireEvent.press(screen.getAllByRole('tab')[0]) - expect(screen.getByText('Thank you. VA received your claim')).toBeTruthy() + expect(screen.getByText('We received your claim in our system.')).toBeTruthy() }) }) describe('when phase is equal to current', () => { - it('should render text details after pressing icon', () => { + it('renders correct label and text without press', () => { initializeTestInstance(2, 2) - fireEvent.press(screen.getAllByRole('tab')[0]) + expect(screen.getByLabelText('Step 2. Initial review. Current step. Step 1 complete.')).toBeTruthy() expect( screen.getByText( - 'Your claim has been assigned to a reviewer who is determining if additional information is needed.', + "We'll check your claim for basic information we need, like your name and Social Security number.\n\nIf information is missing, we'll contact you.", ), ).toBeTruthy() }) }) - describe('when phase is 3', () => { - describe('if there are files that can be uploaded', () => { - beforeEach(() => { - claim.attributes.decisionLetterSent = false - claim.attributes.open = true - claim.attributes.documentsNeeded = true - claim.attributes.eventsTimeline = [ - { - type: 'still_need_from_you_list', - date: '2020-07-16', - status: 'NEEDED', - uploaded: false, - uploadsAllowed: true, - }, - { - type: 'still_need_from_you_list', - date: '2020-07-16', - status: 'NEEDED', - uploaded: false, - uploadsAllowed: true, - }, - ] - initializeTestInstance(3, 2) - }) - - it('should display the view file requests va button', () => { - expect(screen.getByText('You have 2 file requests from VA')).toBeTruthy() - expect(screen.getByRole('button', { name: 'Review file requests' })).toBeTruthy() - fireEvent.press(screen.getByRole('button', { name: 'Review file requests' })) - expect(mockNavigationSpy).toHaveBeenCalledWith('FileRequest', { claimID: '600156928' }) - }) + describe('when phase is equal to current with multiple steps complete', () => { + it('renders correct label and text without press', () => { + initializeTestInstance(6, 6) + expect( + screen.getByLabelText('Step 6. Preparing decision letter. Current step. Step 1 through 5 complete.'), + ).toBeTruthy() + expect( + screen.getByText( + 'We’ll prepare your decision letter.\n\nIf we need more evidence or you submit more evidence, your claim will go back to Step 3.', + ), + ).toBeTruthy() + }) + }) - describe('when number of requests is equal to 1', () => { - it('should display the text "You have 1 file request from VA"', () => { - claim.attributes.eventsTimeline = [ - { - type: 'still_need_from_you_list', - date: '2020-07-16', - status: 'NEEDED', - uploaded: false, - uploadsAllowed: true, - }, - ] - initializeTestInstance(3, 2) - expect(screen.getByText('You have 1 file request from VA')).toBeTruthy() - }) - }) + describe('when phase is greater than current', () => { + it('renders correct label and text after press', () => { + initializeTestInstance(8, 7) + expect(screen.getByLabelText('Step 8. Claim decided. Incomplete.')).toBeTruthy() + fireEvent.press(screen.getAllByRole('tab')[0]) + expect( + screen.getByText("You’ll be able to view and download your decision letter. We'll also mail you this letter."), + ).toBeTruthy() }) }) }) diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.tsx index add57ecfa21..2a8a93a6115 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimTimeline/ClaimPhase.tsx @@ -1,38 +1,15 @@ -import React, { ReactNode, useEffect } from 'react' +import React, { RefObject, useEffect } from 'react' import { useTranslation } from 'react-i18next' +import { ScrollView } from 'react-native' -import { Button } from '@department-of-veterans-affairs/mobile-component-library' -import { DateTime } from 'luxon' - -import { ClaimAttributesData, ClaimEventData } from 'api/types' -import { AccordionCollapsible, Box, TextView } from 'components' +import { ClaimAttributesData } from 'api/types' +import { AccordionCollapsible, Box, LabelTag, LabelTagTypeConstants, TextView, VAIcon } from 'components' import { Events } from 'constants/analytics' import { NAMESPACE } from 'constants/namespaces' import { a11yLabelVA } from 'utils/a11yLabel' -import { testIdProps } from 'utils/accessibility' import { logAnalyticsEvent } from 'utils/analytics' -import { groupTimelineActivity, needItemsFromVet, numberOfItemsNeedingAttentionFromVet } from 'utils/claims' -import { sortByDate } from 'utils/common' -import { useRouteNavigation, useTheme } from 'utils/hooks' - -import PhaseIndicator from './PhaseIndicator' - -/** - * takes the events array, sorts is and returns the latest updated date - * @param events - events array from the claim attributes - * @param phase - phase that this component is rendering for - * @returns a string representing the date that this phase was last updated - */ -const updatedLast = (events: ClaimEventData[], phase: number): string => { - const phases = groupTimelineActivity(events) - const currentPhase = (phases[`${phase}`] as unknown as Array<{ [key: string]: string }>) || [] - sortByDate(currentPhase, 'date', true) - - const lastUpdate = currentPhase.length > 0 && currentPhase[0]?.date - return lastUpdate - ? DateTime.fromISO(lastUpdate).toLocaleString({ year: 'numeric', month: 'long', day: 'numeric' }) - : '' -} +import { getUserPhase, isDisabilityCompensationClaim } from 'utils/claims' +import { useAutoScrollToElement, useTheme } from 'utils/hooks' /** * props for ClaimPhase components @@ -40,76 +17,91 @@ const updatedLast = (events: ClaimEventData[], phase: number): string => { export type ClaimPhaseProps = { /** phase number of the current indicator */ phase: number - /** phase that the current claim is on */ - current: number /** attributes object from ClaimData */ attributes: ClaimAttributesData /** given claims ID */ claimID: string + /** ref to parent scrollView, used for auto scroll */ + scrollViewRef: RefObject } /** * Component for rendering each phase of a claim's lifetime. */ -function ClaimPhase({ phase, current, attributes, claimID }: ClaimPhaseProps) { +function ClaimPhase({ phase, attributes, claimID, scrollViewRef }: ClaimPhaseProps) { const { t } = useTranslation(NAMESPACE.COMMON) + const [scrollRef, viewRef, scrollToCurrentPhase] = useAutoScrollToElement() const theme = useTheme() - const navigateTo = useRouteNavigation() - const { condensedMarginBetween, standardMarginBetween } = theme.dimensions - const { eventsTimeline } = attributes + const { condensedMarginBetween, standardMarginBetween, tinyMarginBetween } = theme.dimensions - const phaseLessThanEqualToCurrent = phase <= current - const heading = t(`claimPhase.heading.phase${phase}`) - const updatedLastDate = phaseLessThanEqualToCurrent ? updatedLast(eventsTimeline, phase) : '' - const showClaimFileUploadBtn = needItemsFromVet(attributes) && !attributes.waiverSubmitted + const isDisabilityClaim = isDisabilityCompensationClaim(attributes.claimTypeCode) + const translationStepString = isDisabilityClaim ? '8step' : '5step' + const heading = t(`claimPhase.${translationStepString}.heading.phase${phase}`) + + const current = isDisabilityClaim ? attributes.phase : getUserPhase(attributes.phase) + const isCompletedPhase = phase < current + const isCurrentPhase = phase === current + const isIncompletePhase = phase > current useEffect(() => { - if (phase === 3 && current === 3 && showClaimFileUploadBtn) { - logAnalyticsEvent(Events.vama_claim_file_request(claimID)) + if (phase > 1 && isCurrentPhase && scrollViewRef?.current) { + scrollRef.current = scrollViewRef.current + scrollToCurrentPhase(-standardMarginBetween) } - }, [phase, current, showClaimFileUploadBtn, claimID]) - - const getPhaseHeader = (): ReactNode => { - return ( - - - - - {heading} - - {phaseLessThanEqualToCurrent && {updatedLastDate}} - - - ) - } - - const getPhaseExpandedContent = (): ReactNode => { - return ( - - {detailsText} + }, [phase, isCurrentPhase, scrollToCurrentPhase, scrollRef, scrollViewRef, standardMarginBetween]) + + const phaseHeader = ( + + + {isCompletedPhase && ( + + )} + {`Step ${phase}`} - ) - } + {heading} + {isCurrentPhase && ( + + + + )} + + ) - let status = '' + const detailsText = t(`claimPhase.${translationStepString}.details.phase${phase}`) + const phaseExpandedContent = ( + + {detailsText} + + ) - if (phase === current) { - status = t('claimPhase.heading.a11y.current') - } else if (phase < current) { - status = t('claimPhase.heading.a11y.completed') + let currentStatusA11y = '' + if (isIncompletePhase) { + currentStatusA11y = t('incomplete') + } else if (isCurrentPhase) { + currentStatusA11y = t('currentStep') + } else if (isCompletedPhase) { + currentStatusA11y = t('complete') } - let testID = `${t('claimPhase.heading.a11y.step', { step: phase })} ${status} ${heading}` - - if (phaseLessThanEqualToCurrent) { - testID = `${testID} ${updatedLastDate}` + let completedStepsA11y = '' + if (phase === 2 && isCurrentPhase) { + completedStepsA11y = t('claimPhase.heading.a11y.step1Complete') + } else if (phase > 2 && isCurrentPhase) { + completedStepsA11y = t('claimPhase.heading.a11y.stepCompleteRange', { lastStep: current - 1 }) } - const count = numberOfItemsNeedingAttentionFromVet(eventsTimeline) - - const detailsText = t(`claimPhase.details.phase${phase}`) - const detailsA11yLabel = phase === 1 ? a11yLabelVA(t('claimPhase.details.phase1')) : detailsText - const youHaveFileRequestsText = t('claimPhase.youHaveFileRequest', { count }) + let testID = `${t('claimPhase.heading.a11y.step', { step: phase })} ${heading}. ${currentStatusA11y}.` + if (completedStepsA11y) { + testID += ` ${completedStepsA11y}.` + } const accordionPress = (isExpanded: boolean | undefined) => { logAnalyticsEvent( @@ -124,39 +116,16 @@ function ClaimPhase({ phase, current, attributes, claimID }: ClaimPhaseProps) { ) } - const fileRequestsPress = () => { - logAnalyticsEvent(Events.vama_claim_review(claimID, attributes.claimType, count)) - navigateTo('FileRequest', { claimID }) - } - return ( - {phase === 3 && showClaimFileUploadBtn && ( - - - {youHaveFileRequestsText} - - -