diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml index 927030a135d..aaca9bc0384 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yml +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -92,9 +92,9 @@ body: - type: input id: duedate attributes: - label: 12.) What is your ideal due date for this change request? + label: 12.) Is there a hard deadline associated with this request? description: - placeholder: MM/DD/YYYY or Quarter + placeholder: MM/DD/YYYY validations: required: true diff --git a/.github/ISSUE_TEMPLATE/release_ticket.md b/.github/ISSUE_TEMPLATE/release_ticket.md index a8a7ad6297a..9d5b6292b61 100644 --- a/.github/ISSUE_TEMPLATE/release_ticket.md +++ b/.github/ISSUE_TEMPLATE/release_ticket.md @@ -3,7 +3,7 @@ name: Release Review Template about: Template for requesting a production release for VA mobile app title: "{{ env.releaseDate }} Release Sign-Off: {{ env.versionNumber }}" labels: release -assignees: timwright12, chrisj-usds, dumathane, rachelhanster, SarahHuber-AdHoc, DonMcCaugheyUSDS, TKDickson +assignees: timwright12, chrisj-usds, dumathane, SarahHuber-AdHoc, DonMcCaugheyUSDS, TKDickson --- diff --git a/.github/workflows/app_store_checks_apple.yml b/.github/workflows/app_store_checks_apple.yml new file mode 100644 index 00000000000..65ead1589db --- /dev/null +++ b/.github/workflows/app_store_checks_apple.yml @@ -0,0 +1,68 @@ +# workflow to check that PR does not break any Apple App Store max file or max character limits +name: "App Store requirement checks" + +on: + pull_request: + branches: + - main + - develop + - 'release/v**' + paths: + - "VAMobile/ios/fastlane/metadata/en-US/**" + - "VAMobile/ios/fastlane/screenshots/**" + +jobs: + check_ios_ipad_pro2_images: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 10 + working_dir: VAMobile/ios/fastlane/screenshots/en-US + counting_function: find . -maxdepth 1 -name "ipadPro2*" -printf '.' | wc -m + check_ios_ipad_pro13_images: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 10 + working_dir: VAMobile/ios/fastlane/screenshots/en-US + counting_function: find . -maxdepth 1 -name "ipadPro13*" -printf '.' | wc -m + check_ios_ipad_pro129_images: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 10 + working_dir: VAMobile/ios/fastlane/screenshots/en-US + counting_function: find . -maxdepth 1 -name "ipadPro12*" -printf '.' | wc -m + check_ios_iphone55_images: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 10 + working_dir: VAMobile/ios/fastlane/screenshots/en-US + counting_function: find . -maxdepth 1 -name "phone5*" -printf '.' | wc -m + check_ios_iphone67_images: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 10 + working_dir: VAMobile/ios/fastlane/screenshots/en-US + counting_function: find . -maxdepth 1 -name "iphone6*" -printf '.' | wc -m + check_ios_description: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 4000 + working_dir: VAMobile/ios/fastlane/metadata/en-US + counting_function: wc -c description.txt | awk '{print $1}' + check_ios_release_notes: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 4000 + working_dir: VAMobile/ios/fastlane/metadata/en-US + counting_function: wc -c release_notes.txt | awk '{print $1}' + check_ios_keyword: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 1000 + working_dir: VAMobile/ios/fastlane/metadata/en-US + counting_function: wc -c keywords.txt | awk '{print $1}' + check_ios_title: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 50 + working_dir: VAMobile/ios/fastlane/metadata/en-US + counting_function: wc -c title.txt | awk '{print $1}' diff --git a/.github/workflows/app_store_checks_google.yml b/.github/workflows/app_store_checks_google.yml new file mode 100644 index 00000000000..8101cfa8c7d --- /dev/null +++ b/.github/workflows/app_store_checks_google.yml @@ -0,0 +1,49 @@ +# workflow to check that PR does not break any Googke Play Store max file or max character limits +name: "App Store requirement checks" + +on: + pull_request: + branches: + - main + - develop + - 'release/v**' + paths: + - "VAMobile/android/fastlane/metadata/android/en-US/**" + +jobs: + check_max_android_phone_screenshots: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 8 + working_dir: VAMobile/android/fastlane/metadata/android/en-US/images/phoneScreenshots + counting_function: ls | wc -l + check_max_android_seven_inch_screenshots: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 8 + working_dir: VAMobile/android/fastlane/metadata/android/en-US/images/sevenInchScreenshots + counting_function: ls | wc -l + check_android_long_description: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 4000 + working_dir: VAMobile/android/fastlane/metadata/android/en-US + counting_function: wc -c full-description.txt | awk '{print $1}' + check_android_short_description: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 80 + working_dir: VAMobile/android/fastlane/metadata/android/en-US + counting_function: wc -c short-description.txt | awk '{print $1}' + check_android_change_log: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 500 + working_dir: VAMobile/android/fastlane/metadata/android/en-US/changelogs + counting_function: wc -c default.txt | awk '{print $1}' + check_android_release_name: + uses: ./.github/workflows/check_max_size.yml + with: + max_size: 50 + working_dir: VAMobile/android/fastlane/metadata/android/en-US + counting_function: wc -c title.txt | awk '{print $1}' diff --git a/.github/workflows/check_max_size.yml b/.github/workflows/check_max_size.yml new file mode 100644 index 00000000000..30b2ea1f9db --- /dev/null +++ b/.github/workflows/check_max_size.yml @@ -0,0 +1,25 @@ +on: + workflow_call: + inputs: + working_dir: + required: true + type: string + max_size: + required: true + type: string + counting_function: + required: true + type: string + +jobs: + check_max_files: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: | + if [[ $(${{ inputs.counting_function }}) -gt ${{ inputs.max_size }} ]] + then + echo "PR exceeds app store limits of ${{ inputs.max_size }} for this check" + exit 1 + fi + working-directory: ${{ inputs.working_dir }} diff --git a/.github/workflows/code_checks.yml b/.github/workflows/code_checks.yml index 65f9ac13e97..1be07d502ee 100644 --- a/.github/workflows/code_checks.yml +++ b/.github/workflows/code_checks.yml @@ -53,3 +53,31 @@ jobs: # jest with the specified files. The number at the end is the # of chunks we're splitting the tests into. # This should match the numbers of items in the matrix chunk array above run: bash ${GITHUB_WORKSPACE}/.github/scripts/setupTestMatrix.sh ${{ matrix.chunk }} 5 + bundle_android: + runs-on: ubuntu-4-cores-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version-file: 'VAMobile/.nvmrc' + - name: Install dependencies + uses: nick-fields/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 3 + command: cd VAMobile && yarn install --frozen-lockfile --non-interactive + - run: yarn bundle:android + bundle_ios: + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version-file: 'VAMobile/.nvmrc' + - name: Install dependencies + uses: nick-fields/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 3 + command: cd VAMobile && yarn install --frozen-lockfile --non-interactive + - run: yarn pods && yarn bundle:ios diff --git a/.github/workflows/documentation_accessibility_checks.yml b/.github/workflows/documentation_accessibility_checks.yml index ba349c755e8..fac60e697cd 100644 --- a/.github/workflows/documentation_accessibility_checks.yml +++ b/.github/workflows/documentation_accessibility_checks.yml @@ -1,7 +1,5 @@ name: '[Documentation] Accessibility Check' -# Adapted from https://docusaurus.io/docs/deployment - on: workflow_dispatch: # Run on Weekdays at 9:00 AM UTC, 4AM ET, 1:00 AM PT @@ -14,24 +12,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Setup node and restore yarn cache + uses: actions/setup-node@v3 + with: + node-version-file: 'VAMobile/.nvmrc' + cache: 'yarn' + cache-dependency-path: 'VAMobile/yarn.lock' - name: Clean npm cache run: npm cache clean --force - name: Install Axe CLI globally run: npm install -g @axe-core/cli@latest - - name: Update npm - run: npm install -g npm@latest - - uses: actions/setup-node@v3 - with: - node-version-file: 'VAMobile/.nvmrc' - cache: yarn - cache-dependency-path: VAMobile/yarn.lock - name: Install latest version of chromeDriver run: npm install -g chromedriver@latest - - name: Test build + - name: Run build to generate sitemap working-directory: VAMobile run: | yarn install --frozen-lockfile cd documentation + npx update-browserslist-db@latest yarn install --frozen-lockfile yarn build - name: Start web server @@ -77,7 +75,7 @@ jobs: env: SLACK_API_TOKEN: ${{ secrets.SLACK_API_TOKEN }} channel_name: va-mobile-build-alerts - message: 'Accessibility issues detected. Please review and fix. Build started by ${{ github.actor }}: (:git: `${{ github.ref_name }}`). See :thread: or <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|workflow run> for results.' + message: 'Accessibility issues detected. See :thread: or <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|workflow run> for results.' run: | curl -X POST \ -H "Authorization: Bearer $SLACK_API_TOKEN" \ diff --git a/.github/workflows/e2e_android.yml b/.github/workflows/e2e_android.yml index f849764fc03..e97c3c8f9dc 100644 --- a/.github/workflows/e2e_android.yml +++ b/.github/workflows/e2e_android.yml @@ -226,9 +226,11 @@ jobs: arch: x86_64 avd-name: Pixel_4_XL_API_28 script: yarn e2e:android-test /e2e/tests/Navigation.e2e AvailabilityFramework.e2e ${{matrix.testsuite}}.e2e --updateSnapshot + continue-on-error: true - name: Run e2e tests for Android on failure - if: failure() && steps.run_e2e_tests_nav_AF.outcome == 'failure' + if: steps.run_e2e_tests_nav_AF.outcome == 'failure' + id: run_e2e_tests_retry uses: reactivecircus/android-emulator-runner@v2 with: working-directory: VAMobile @@ -239,7 +241,7 @@ jobs: arch: x86_64 avd-name: Pixel_4_XL_API_28 script: yarn e2e:android-test /e2e/tests/Navigation.e2e AvailabilityFramework.e2e ${{matrix.testsuite}}.e2e --updateSnapshot - + - name: Upload e2e-junit if: failure() || success() uses: actions/upload-artifact@v4 diff --git a/.github/workflows/e2e_detox_mapping.yml b/.github/workflows/e2e_detox_mapping.yml index 2c86b02b9af..ff3b7e0f0c4 100644 --- a/.github/workflows/e2e_detox_mapping.yml +++ b/.github/workflows/e2e_detox_mapping.yml @@ -51,108 +51,110 @@ jobs: - name: Get SHA id: get-sha run: echo "sha=$(git rev-parse origin/develop)" >> $GITHUB_OUTPUT - - name: Get file difference by directory - id: changed_files_dir - uses: tj-actions/changed-files@v41 - with: - dir_names: true - json: true - base_sha: "${{ steps.get-sha.outputs.sha }}" - name: Get file difference by file name id: changed_files_file_name uses: tj-actions/changed-files@v41 with: - json: true base_sha: "${{ steps.get-sha.outputs.sha }}" + path: './VAMobile/src' + - name: Check if directory/file is in detox mapping + id: detox_mapping_check + run: | + fileNames=$(jq -r '.files' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + directoryNames=$(jq -r '.directory' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + for file in ${{steps.changed_files_file_name.outputs.all_changed_and_modified_files}}; do + baseFile=$(echo $file | sed 's#.*/##') + baseFile=$(echo $baseFile | sed 's/ //g') + fileFound=$(echo $fileNames | jq --arg fileName "$baseFile" '.[$fileName]') + if [[ "$fileFound" == "null" ]]; then + fileDirectory=$(dirname $file) + baseDirectory=$(echo $fileDirectory | sed 's#.*/##') + baseDirectory=$(echo $baseDirectory | sed 's/ //g') + directoryFound=$(echo $directoryNames | jq --arg fileName "$baseDirectory" '.[$fileName]') + if [[ "$directoryFound" == "null" ]]; then + echo "Missing File: $file or missing directory: $fileDirectory" + exit 1 + fi + fi + done + - name: Check if directory/file is spelled correctly + id: detox_mapping_spell_check + run: | + directoryNames=$(jq -r '.directory' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + for directory in $(echo $directoryNames | jq -r 'keys | .[]'); do + if [[ "$(find ${{ github.workspace }}/VAMobile/src -type d -name "$directory")" == "" ]]; then + directoryMisspelled="true" + echo "Directory misspelled: $directory" + exit 1 + fi + done + fileNames=$(jq -r '.files' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + for file in $(echo $fileNames | jq -r 'keys | .[]'); do + if [[ "$(find ${{ github.workspace }}/VAMobile/src -type f -name "$file")" == "" ]]; then + fileMisspelled="true" + echo "File misspelled: $file" + exit 1 + fi + done + - name: Check if e2eNames is spelled correctly + id: detox_mapping_e2e_names_spell_check + run: | + directoryNames=$(jq -r '.directory' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + for directory in $(echo $directoryNames | jq 'keys | .[]'); do + for e2eTest in $(echo $directoryNames | jq --argjson directory "$directory" --raw-output '.[$directory] | .[]'); do + if [[ "$(find ${{ github.workspace }}/VAMobile/e2e/tests -type f -name "${e2eTest}.e2e.ts")" == "" ]]; then + echo "e2eTests in $directory are not spelled correctly" + echo "$e2eTests misspelled: $e2eTest" + exit 1 + fi + done + done + fileNames=$(jq -r '.files' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + for file in $(echo $fileNames | jq 'keys | .[]'); do + for e2eTest in $(echo $fileNames | jq --argjson file "$file" --raw-output '.[$file] | .[]'); do + if [[ "$(find ${{ github.workspace }}/VAMobile/e2e/tests -type f -name "${e2eTest}.e2e.ts")" == "" ]]; then + echo "e2eTests in $file are not spelled correctly" + echo "$e2eTests misspelled: $e2eTest" + exit 1 + fi + done + done - name: Get testing matrix array id: testing_matrix run: | - resp=$(echo ${{steps.changed_files_dir.outputs.all_changed_and_modified_files}} | - jq 'select(contains(["LoginScreen"])) += ["LoginScreen"] | - select(contains(["AppealDetailsScreen"])) += ["Appeals", "AppealsExpanded"] | - select(contains(["NeedHelpData"]) or contains(["NoClaimsAndAppeals"]) or contains(["NoClaimsAndAppealsAccess"]) or contains(["ClaimsAndAppealsListView"]) or contains(["claimsAndAppeals"])) += ["Appeals", "AppealsExpanded", "Claims"] | - select(contains(["ClaimDetailsScreen"]) or contains(["ClaimLettersScreen"]) or contains(["SubmitEvidence"]) or contains(["ClaimsHistoryScreen"])) += ["Claims"] | - select(contains(["ClaimLettersScreen"]) or contains(["decisionLetters"])) += ["DecisionLetters"] | - select(contains(["DisabilityRatingsScreen"]) or contains(["disabilityRating"])) += ["DisabilityRatings", "VeteranStatusCard"] | - select(contains(["Letters"]) or contains(["letters"])) += ["VALetters"] | - select(contains(["Appointments"]) or contains(["appointments"])) += ["Appointments", "AppointmentsExpanded"] | - select(contains(["CernerAlert"]) or contains(["Facilities"])) += ["Cerner"] | - select(contains(["Pharmacy"]) or contains(["prescriptions"])) += ["Prescriptions"] | - select(contains(["SecureMessaging"]) or contains(["secureMessaging"])) += ["Messages"] | - select(contains(["Vaccines"]) or contains(["vaccines"])) += ["VaccineRecords"] | - select(contains(["ContactVAScreen"])) += ["HomeScreen"] | - select(contains(["MilitaryInformationScreen"]) or contains(["militaryService"]) or contains(["Nametag"])) += ["MilitaryInformation", "VeteranStatusCard"] | - select(contains(["PersonalInformationScreen"]) or contains(["demographics"]) or contains(["personalInformation"])) += ["PersonalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"] | - select(contains(["SettingsScreen"])) += ["SettingsScreen"] | - select(contains(["VeteransCrisisLineScreen"])) += ["VeteransCrisisLine", "SignIn"] | - select(contains(["VeteranStatusScreen"])) += ["VeteranStatusCard"] | - select(contains(["OnboardingCarousel"])) += ["Onboarding"] | - select(contains(["PaymentHistory"]) or contains(["payments"])) += ["Payments"] | - select(contains(["DirectDepositScreen"]) or contains(["directDeposit"])) += ["DirectDeposit"] | - select(contains(["SplashScreen"])) += ["Onboarding", "LoginScreen"] | - select(contains(["auth"])) += ["SignIn"] | - select(contains(["authorizedServices"])) += ["Appeals", "AppealsExpanded", "Appointments", "AppointmentsExpanded", "Claims", "DirectDeposit", "DisabilityRatings", "PersonalInformationScreen", "VALetters", "MilitaryInformation", "Payments", "Prescriptions", "Messages", "VeteranStatusCard"] | - select(contains(["contactInformation"]) or contains(["ContactInformationScreen"])) += ["ContactInformation", "VALetters"] | - select(contains(["NotificationManager"])) += ["SettingsScreen", "PushNotifications", "Onboarding"] | - select(contains(["Types"]) or contains(["VAImage"])) += - ["AvailabilityFramework", "Cerner", "ContactInformation", "VALetters", "LoginScreen", "Onboarding", "ProfileScreen", "PushNotifications", "SettingsScreen", "SignIn", "VaccineRecords", "Claims", "Appeals", "AppealsExpanded", "DisabilityRatings", "Appointments", "AppointmentsExpanded", "Prescriptions", "Messages", "MilitaryInformation", "HomeScreen", "VeteransCrisisLine", "VeteranStatusCard", "DirectDeposit", "Payments", "PersonalInformationScreen"] - | unique') - resp_file=$(echo ${{steps.changed_files_file_name.outputs.all_changed_and_modified_files}} | - jq 'select(contains(["appealData.tsx"])) += ["Appeals", "AppealsExpanded"] | - select(contains(["claimData.tsx"]) or contains(["ClaimsScreen.tsx"]) or contains(["Claims.json"]) or contains(["Claims.ts"]) or contains(["ClaimsAndAppealsSlice"]) - or contains(["ClaimsAndAppealsData"]) or contains(["claims.ts"]) or contains(["claims.tsx"])) += ["Claims", "Appeals", "AppealsExpanded", "DecisionLetters"] | - select(contains(["DisabilityRatingData"]) or contains(["disabilityRating.json"]) or contains(["disabilityRating.ts"])) += ["DisabilityRatings", "VeteranStatusCard"] | - select(contains(["letters.json"]) or contains(["letters.ts"]) or contains(["Letters.ts"]) or contains(["LettersData"]) or contains(["LetterBeneficiaryData"]) or contains(["BasicError"])) += ["VALetters"] | - select(contains(["HealthScreen.tsx"]) or contains(["HealthStackScreens.tsx"])) += ["Appointments", "AppointmentsExpanded", "Cerner", "Prescriptions", "Messages", "VaccineRecords"] | - select(contains(["BenefitsScreen.tsx"]) or contains(["BenefitsStackScreens.tsx"])) += ["DisabilityRating", "Claims", "Appeals", "VALetters"] | - select(contains(["Appointments.json"]) or contains(["Appointments.ts"]) or contains(["AppointmentsSlice.ts"]) or contains(["appointments.ts"]) or contains(["canclAppointment.tsx"]) or contains(["getAppointments.tsx"]) or contains(["appointments.tsx"])) += ["Appointments", "AppointmentsExpanded"] | - select(contains(["getFacilitiesInfo"]) or contains(["FacilityData"])) += ["Cerner"] | - select(contains(["Prescriptions.json"]) or contains(["Prescriptions.ts"]) or contains(["SelectionList"]) or contains(["MultiTouchCard"]) or contains(["RadioGroupModal"])) += ["Prescriptions"] | - select(contains(["SecureMessaging.json"]) or contains(["SecureMessaging.ts"]) or contains(["InLineTextWithIcons"]) - or contains(["MessageAlert"]) or contains(["MessageList"]) or contains(["MessagesCountTag"]) or contains(["secureMessaging.ts"]) or contains(["TextLineWithIcon"])) += ["Messages"] | - select(contains(["vaccine"])) += ["VaccineRecords"] | - select(contains(["EncourageUpdate.tsx"]) or contains(["WhatsNew.tsx"])) += ["HomeScreen"] | - select(contains(["countries"]) or contains(["militaryPostOffices"]) or contains(["militaryStates"]) or contains(["states.ts"]) or contains(["PhoneData"]) or contains(["EmailData"])) += ["ContactInformation"] | - select(contains(["ServiceHistoryData"])) += ["MilitaryInformation", "VeteranStatusCard"] | - select(contains(["demographics"]) or contains(["PersonalInformation"]) or contains(["UserData"]) or contains(["Demographics"])) += ["PeronalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"] | - select(contains(["settingsSlice.ts"])) += ["SettingsScreen"] | - select(contains(["ProfileScreen.tsx"]) or contains(["profile.json"]) or contains(["profile.ts"])) += ["ProfileScreen", "ContactInformation", "MilitaryInformation", "PersonalInformationScreen", "SettingsScreen", "VALetters", "Payments"] | - select(contains(["HomeScreen.tsx"]) or contains(["HomeStackScreens.tsx"])) += ["ContactVAScreen", "ProfileScreen", "VeteranStatusCard"] | - select(contains(["carousel"])) += ["Onboarding"] | - select(contains(["payments.json"]) or contains(["payments.ts"])) += ["Payments"] | - select(contains(["accounts.ts"])) += ["DirectDeposit"] | - select(contains(["PaymentsScreen.tsx"]) or contains(["PaymentsStackScreens.tsx"])) += ["Payments", "DirectDeposit"] | - select(contains(["decisionLetters.ts"]) or contains(["decisionLetters.json"]) or contains(["claimData.tsx"])) += ["Claims"] | - select(contains(["getAuthorizedServices.json"])) += ["Appeals", "AppealsExpanded", "Appointments", "AppointmentsExpanded", "Claims", "DirectDeposit", "DisabilityRatings", "PersonalInformationScreen", "VALetters", "MilitaryInformation", "Payments", "Prescriptions", "Messages", "VeteranStatusCard"] | - select(contains(["notifications.json"]) or contains(["notifications.ts"]) or contains(["Notifications.ts"])) += ["SettingsScreen", "PushNotifications"] | - select(contains(["ErrorComponent"])) += ["Appeals", "AppealsExpanded", "DisabilityRatings", "VALetters", "Appointments", "AppointmentsExpanded", "Prescriptions", "Messages", "VaccineRecords", "ProfileScreen", "ContactInformation", "MilitaryInformation", "PersonalInformationScreen", "SettingsScreen", "Payments"] | - select(contains(["VAModalPicker"])) += ["Appointments", "Messages", "Payments"] | - select(contains(["RadioGroup"])) += ["PersonalInformationScreen", "ContactInformation"] | - select(contains(["VATextInput"]) or contains(["WaygateWrapper"])) += ["AvailabilityFramework"] | - select(contains(["AccordionCollapsible"])) += ["Claims", "Messages"] | - select(contains(["AlertWithHaptics"])) += ["AvailabilityFramework", "VALetters", "Appointments", "Prescriptions", "Messages", "ContactInformation", "DirectDeposit", "Cerner", "Prescriptions", "ContactInformation"] | - select(contains(["AppVersionAndBuild"])) += ["LoginScreen", "SettingsScreen"] | - select(contains(["ClickForActionLink"]) or contains(["ClickToCallPhoneNumber"])) += ["AvailabilityFramework", "Claims", "Appeals", "DisabilityRatings", "Appointments", "Prescriptions", "Messages", "MilitaryInformation", "HomeScreen", "VeteransCrisisLine", "VeteranStatusCard", "DirectDeposit", "Payments", "PersonalInformationScreen"] | - select(contains(["CollapsibleView"])) += ["Appeals", "AppealsExpanded", "Messages", "DirectDeposit"] | - select(contains(["DefaultList"])) += ["Claims", "DisabilityRattings", "VALetters", "ContactInformation", "Appointments", "VaccineRecords", "MilitaryInformation", "PersonalInformationScreen", "DirectDeposit", "Prescriptions", "Payments", "SettingsScreen"] | - select(contains(["LabelTag"])) += ["Prescriptions", "Messages"] | - select(contains(["SimpleList"])) += ["Messages", "Claims", "Appeals", "VALetters", "Apppointments", "Prescriptions", "VaccineRecords"] | - select(contains(["Pagination"])) += ["Appointments", "Claims", "Appeals", "AppealsExpanded", "Prescriptions", "Messages", "Payments", "VaccinesScreen"] | - select(contains(["SnackBar"])) += ["Claims", "Messages", "ContactInformation", "PersonalInformationScreen", "DirectDeposit"] | - select(contains(["VABulletList"])) += ["Appeals", "AppealsExpanded", "Claims", "Prescriptions", "Cerner", "Messages", "Onboarding", "SignIn", "SettingsScreen"] | - select(contains(["CrisisLineButton"])) += ["HomeScreen", "SignIn", "LoginScreen", "VeteransCrisisLine"] | - select(contains(["ActivityButton.tsx"])) += ["HomeScreen", "Prescriptions", "Appointments", "Claims", "Appeals", "DecisionLetters"] | - select(contains(["LinkRow.tsx"])) += ["HomeScreen"] | - select(contains(["Screens.ts"]) or contains(["BasicError"]) or contains(["LoadingComponent"]) or contains(["Box"]) or contains(["HeaderTitle"]) or contains(["LargeNavButton"]) - or contains(["TextArea"]) or contains(["TextLines"]) or contains(["TextView"]) or contains(["backButtonLabels"]) or contains(["common.ts"])) += - ["AvailabilityFramework", "Cerner", "ContactInformation", "VALetters", "LoginScreen", "Onboarding", "ProfileScreen", "PushNotifications", "SettingsScreen", "SignIn", "VaccineRecords", "Claims", "Appeals", "AppealsExpanded", "DisabilityRatings", "Appointments", "AppointmentsExpanded", "Prescriptions", "Messages", "MilitaryInformation", "HomeScreen", "VeteransCrisisLine", "VeteranStatusCard", "DirectDeposit", "Payments", "PersonalInformationScreen"] - | unique ') - - test_matrix=$(echo "$resp" | jq --argjson a "${resp_file}" --argjson b "${resp}" --compact-output '$a + $b | unique') - echo "$test_matrix" - test_matrix=$(echo $test_matrix | jq --compact-output 'map(select(. == ("Appeals", "AppealsExpanded", "Appointments", "AppointmentExpanded", "AvailabilityFramework", "Cerner", "Claims", - "ContactInformation", "DirectDeposit", "DisabilityRatings", "HomeScreen", "VALetters", "LoginScreen", "Messages", "MilitaryInformation", "Navigation", "Onboarding", "Payments", - "PersonalInformationScreen", "Prescriptions", "ProfileScreen", "PushNotifications", "SettingsScreen", "SignIn", "VaccineRecords", - "VeteransCrisisLine", "VeteranStatusCard")))') + firstInstanceFile="true" + directoryNames=$(jq -r '.directory' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + fileNames=$(jq -r '.files' ${{ github.workspace }}/VAMobile/e2e/detoxMapping.json) + for file in ${{steps.changed_files_file_name.outputs.all_changed_and_modified_files}}; do + baseFile=$(echo $file | sed 's#.*/##') + baseFile=$(echo $baseFile | sed 's/ //g') + fileFound=$(echo $fileNames | jq --arg fileName "$baseFile" '.[$fileName]') + if [[ "$fileFound" == "null" ]]; then + fileDirectory=$(dirname $file) + baseDirectory=$(echo $fileDirectory | sed 's#.*/##') + baseDirectory=$(echo $baseDirectory | sed 's/ //g') + directoryFound=$(echo $directoryNames | jq --arg fileName "$baseDirectory" '.[$fileName]') + if [[ "$firstInstanceFile" == "true" ]]; then + test_matrix=$directoryFound + test_matrix=$(echo $test_matrix | jq -c '.') + firstInstanceFile="false" + else + test_matrix=$(echo $test_matrix | jq -c '.') + test_matrix=$(echo $test_matrix | jq --argjson matrix "$directoryFound" '. += $matrix') + fi + else + if [[ "$firstInstanceFile" == "true" ]]; then + test_matrix=$fileFound + test_matrix=$(echo $test_matrix | jq -c '.') + firstInstanceFile="false" + else + test_matrix=$(echo $test_matrix | jq -c '.') + test_matrix=$(echo $test_matrix | jq --argjson matrix "$fileFound" '. += $matrix') + fi + fi + done + test_matrix=$(echo $test_matrix | jq -c 'unique') echo "TESTING_MATRIX=$test_matrix" >> $GITHUB_OUTPUT echo "TEST_RUN=true" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/native_build_check_android.yml b/.github/workflows/native_build_check_android.yml new file mode 100644 index 00000000000..0c36acb2995 --- /dev/null +++ b/.github/workflows/native_build_check_android.yml @@ -0,0 +1,15 @@ +# Tests to see that changes to native files do not break the Android build process +name: '[Code Quality] Check Native Android Builds' + +on: + pull_request: + paths: + - "VAMobile/android/**" + +jobs: + android_native_build: + name: Android Test Build + uses: ./.github/workflows/build_android.yml + secrets: inherit + with: + lane: test_build_only diff --git a/.github/workflows/native_build_check_android_reusable.yml b/.github/workflows/native_build_check_android_reusable.yml new file mode 100644 index 00000000000..207d2ff80f6 --- /dev/null +++ b/.github/workflows/native_build_check_android_reusable.yml @@ -0,0 +1,11 @@ +# This is a reusable workflow so that required checks work correctly. see https://github.com/orgs/community/discussions/36680 +name: '[Code Quality] Check Native Android Builds' + +on: + workflow_call: + +jobs: + build_android: + runs-on: ubuntu-latest + steps: + - run: echo "PASS -- No native android files updated." diff --git a/.github/workflows/native_build_check_android_skip.yml b/.github/workflows/native_build_check_android_skip.yml new file mode 100644 index 00000000000..be61c4529df --- /dev/null +++ b/.github/workflows/native_build_check_android_skip.yml @@ -0,0 +1,12 @@ +# This test has the opposite filter of native_build_check_android.yml so that required checks dont hang +name: '[Code Quality] Check Native Android Builds' + +on: + pull_request: + paths: + - "!VAMobile/android/**" + +jobs: + android_native_build: + name: Android Test Build + uses: ./.github/workflows/native_build_check_android_reusable.yml diff --git a/.github/workflows/native_build_check_ios.yml b/.github/workflows/native_build_check_ios.yml new file mode 100644 index 00000000000..cedcc2a1fd3 --- /dev/null +++ b/.github/workflows/native_build_check_ios.yml @@ -0,0 +1,15 @@ +# Tests to see that changes to native files do not break the iOs build process +name: '[Code Quality] Check Native iOs Builds' + +on: + pull_request: + paths: + - "VAMobile/ios/**" + +jobs: + ios_native_build: + name: iOS Test Build + uses: ./.github/workflows/build_ios.yml + secrets: inherit + with: + lane: test_build_only diff --git a/.github/workflows/native_build_check_ios_reusable.yml b/.github/workflows/native_build_check_ios_reusable.yml new file mode 100644 index 00000000000..3832c2e9927 --- /dev/null +++ b/.github/workflows/native_build_check_ios_reusable.yml @@ -0,0 +1,11 @@ +# This is a reusable workflow so that required checks work correctly. see https://github.com/orgs/community/discussions/36680 +name: '[Code Quality] Check Native iOs Builds' + +on: + workflow_call: + +jobs: + build_ios: + runs-on: ubuntu-latest + steps: + - run: echo "PASS -- No native ios files updated." diff --git a/.github/workflows/native_build_check_ios_skip.yml b/.github/workflows/native_build_check_ios_skip.yml new file mode 100644 index 00000000000..2c74c224e99 --- /dev/null +++ b/.github/workflows/native_build_check_ios_skip.yml @@ -0,0 +1,13 @@ +# This test has the opposite filter of native_build_check_ios.yml so that required checks dont hang +name: '[Code Quality] Check Native iOs Builds' + +on: + pull_request: + paths: + - "!VAMobile/ios/**" + +jobs: + ios_native_build: + name: iOS Test Build + uses: ./.github/workflows/native_build_check_ios_reusable.yml + diff --git a/.github/workflows/release_branch_issue.yml b/.github/workflows/release_branch_issue.yml index 85cd3359fea..2915cff023b 100644 --- a/.github/workflows/release_branch_issue.yml +++ b/.github/workflows/release_branch_issue.yml @@ -7,7 +7,7 @@ jobs: if: ${{ contains(github.ref, 'refs/heads/release/') }} runs-on: ubuntu-latest outputs: - ticketNumber: ${{steps.create-issue.outputs.number}} + ticketNumber: ${{steps.create_issue.outputs.number}} versionNumber: ${{env.VERSION}} releaseDate: ${{env.RELEASE_DATE}} qaDueDate: ${{env.QA_DUE_DATE}} @@ -105,7 +105,7 @@ jobs: run: | declare -A GITHUB_TO_SLACK_MAP GITHUB_TO_SLACK_MAP["TKDickson"]="U02PJLJ0H6H" - GITHUB_TO_SLACK_MAP["SarahHuber-AdHoc"]="U07U9EDGAFP" + GITHUB_TO_SLACK_MAP["SarahHuber_AdHoc"]="U07U9EDGAFP" GITHUB_TO_SLACK_MAP["dumathane"]="U02RC1BRZBP" GITHUB_TO_SLACK_MAP["timwright12"]="U01DBDAJZ18" GITHUB_TO_SLACK_MAP["ala_yna"]="UQC180926" diff --git a/.github/workflows/start_slack_thread.yml b/.github/workflows/start_slack_thread.yml index d1c9c524921..69a1c45f2ff 100644 --- a/.github/workflows/start_slack_thread.yml +++ b/.github/workflows/start_slack_thread.yml @@ -33,10 +33,31 @@ jobs: - name: Search Slack for channel ID id: search_slack run: | - id=$(curl -X GET -H 'Authorization: Bearer '"$SLACK_API_TOKEN"' ' \ + fetch_page() { + last_response=$(curl -X GET -H 'Authorization: Bearer '"$SLACK_API_TOKEN"' ' \ -H 'Content-type: application/x-www-form-urlencoded' \ - https://slack.com/api/conversations.list\?limit=1000 | - jq '.channels[] | .name as $data | select($data == "${{inputs.channel_name}}").id' ) + https://slack.com/api/conversations.list\?limit=1000\&cursor=$cursor | jq .) + } + get_id() { + id=$(jq '.channels[] | .name as $data | select($data == "${{inputs.channel_name}}").id' <<< $last_response) + } + + get_cursor() { + cursor=$(jq '.response_metadata.next_cursor' <<< $last_response) + } + + id="" + cursor="" + last_response="" + fetch_page + get_id + + while [[ -z "$id" ]] + do + get_cursor + fetch_page + get_id + done echo SLACK_CHANNEL_ID=${id} >> $GITHUB_OUTPUT start_thread: name: Start thread diff --git a/VAMobile/android/Gemfile.lock b/VAMobile/android/Gemfile.lock index 9513b805106..02748598f8f 100644 --- a/VAMobile/android/Gemfile.lock +++ b/VAMobile/android/Gemfile.lock @@ -10,8 +10,8 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.1010.0) - aws-sdk-core (3.213.0) + aws-partitions (1.1013.0) + aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -19,7 +19,7 @@ GEM aws-sdk-kms (1.96.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.172.0) + aws-sdk-s3 (1.174.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) diff --git a/VAMobile/android/fastlane/Fastfile b/VAMobile/android/fastlane/Fastfile index dfb9c767607..df6fe7fe4da 100644 --- a/VAMobile/android/fastlane/Fastfile +++ b/VAMobile/android/fastlane/Fastfile @@ -113,6 +113,11 @@ platform :android do ) end + desc "Makes a test build to ensure changes to native directories did not break build process. DOES NOT DISTRIBUTE" + lane :test_build_only do |options| + bundle("Release") + end + after_all do |lane, options| # This block is called, only if the executed lane was successful end @@ -191,7 +196,7 @@ platform :android do def upload(track, skip_meta = true) puts "Skip meta: " + skip_meta.to_s supply( - track: track, + track: track, package_name: "gov.va.mobileapp", skip_upload_metadata: skip_meta, skip_upload_changelogs: skip_meta, diff --git a/VAMobile/android/fastlane/metadata/android/en-US/changelogs/default.txt b/VAMobile/android/fastlane/metadata/android/en-US/changelogs/default.txt index cb218d76a9f..71941198bb1 100644 --- a/VAMobile/android/fastlane/metadata/android/en-US/changelogs/default.txt +++ b/VAMobile/android/fastlane/metadata/android/en-US/changelogs/default.txt @@ -1 +1 @@ -You can now view and download files from your claim in the app. +We added general improvements and fixed a few bugs. diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/AddressUpdateFlow.md b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/AddressUpdateFlow.md new file mode 100644 index 00000000000..9b25f4c9893 --- /dev/null +++ b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/AddressUpdateFlow.md @@ -0,0 +1,335 @@ +--- +title: Address Update Flow +--- + +Updating an address is a two step process with different option for what to send in the request body.Below are three scenarios for updating when the user has entered a valid address with a single match.A valid address with multiple suggested address matches. And when a user has entered what the validation service considers and invalid addres but the user would like to override that and use it anyway. + +## Single match valid address + +```rst +POST /v0/user/addresses/validate +``` + +### Validate Address Request + +```json +{ + "addressLine1": "51 W Weber Rd", + "addressType": "DOMESTIC", + "city": "Columbus", + "countryName": "United States", + "countryCodeIso3": "USA", + "stateCode": "OH", + "zipCode": "43202", + "type": "DOMESTIC", + "addressPou": "CORRESPONDENCE" +} +``` + +### Validate Address Response + +The address has a 100% confidence score. The address that's returned can be sent in a new/update request. In this case the address object in the meta data should be passed along in that request. + +```json +{ + "data": [ + { + "id": "a3add173-380c-4387-9d72-276b755aa980", + "type": "suggested_address", + "attributes": { + "addressLine1": "51 W Weber Rd", + "addressLine2": null, + "addressLine3": null, + "addressPou": "CORRESPONDENCE", + "addressType": "DOMESTIC", + "city": "Columbus", + "countryCodeIso3": "USA", + "internationalPostalCode": null, + "province": null, + "stateCode": "OH", + "zipCode": "43202", + "zipCodeSuffix": "1922" + }, + "meta": { + "address": { + "confidenceScore": 100.0, + "addressType": "Domestic", + "deliveryPointValidation": "CONFIRMED", + "residentialDeliveryIndicator": "RESIDENTIAL" + }, + "validationKey": -1398777841 + } + } + ] +} +``` + +```rst +PUT /v0/user/addresses +``` + +### User Address Request + +```json +{ + "addressMetaData": { + "confidenceScore": 100.0, + "addressType": "Domestic", + "deliveryPointValidation": "CONFIRMED", + "residentialDeliveryIndicator": "RESIDENTIAL" + }, + "addressLine1": "51 W Weber Rd", + "addressType": "DOMESTIC", + "city": "Columbus", + "countryName": "United States", + "countryCodeIso3": "USA", + "stateCode": "OH", + "zipCode": "43202", + "addressPou": "CORRESPONDENCE", + "id": 181513 +} +``` + +#### Addresses Response + +```json +{ + "data": { + "id": "b2e51260-00c9-4db6-80f6-b6c7541a9e54", + "type": "async_transaction_vet360_address_transactions", + "attributes": { + "transactionId": "b2e51260-00c9-4db6-80f6-b6c7541a9e54", + "transactionStatus": "COMPLETED_SUCCESS", + "type": "AsyncTransaction::Vet360::AddressTransaction", + "metadata": [] + } + } +} +``` + +## Multiple match addresses + +```rst +POST /v0/user/addresses/validate +``` + +### Multiple Addresses Request + +```json +{ + "addressLine1": "37 1st st", + "addressType": "DOMESTIC", + "city": "Brooklyn", + "countryName": "United States", + "countryCodeIso3": "USA", + "stateCode": "NY", + "zipCode": "11249", + "type": "DOMESTIC", + "addressPou": "CORRESPONDENCE", +} +``` + +### Multiple Addresses Response + +In this case two address matches are returned and should be displayed to the user so they can pick which they'd like to use. As above the `meta.address` object is passed along in the new/update request. + +```json +{ + "data": [ + { + "id": "56c30b81-9162-4f64-86ce-e7eaa3ae0327", + "type": "suggested_address", + "attributes": { + "addressLine1": "37 N 1st St", + "addressLine2": null, + "addressLine3": null, + "addressPou": "CORRESPONDENCE", + "addressType": "DOMESTIC", + "city": "Brooklyn", + "countryCodeIso3": "USA", + "internationalPostalCode": null, + "province": null, + "stateCode": "NY", + "zipCode": "11249", + "zipCodeSuffix": "3939" + }, + "meta": { + "address": { + "confidenceScore": 100.0, + "addressType": "Domestic", + "deliveryPointValidation": "UNDELIVERABLE" + }, + "validationKey": -73046298 + } + }, + { + "id": "671e752c-3292-4a2b-8747-d42b2bd56055", + "type": "suggested_address", + "attributes": { + "addressLine1": "37 S 1st St", + "addressLine2": null, + "addressLine3": null, + "addressPou": "CORRESPONDENCE", + "addressType": "DOMESTIC", + "city": "Brooklyn", + "countryCodeIso3": "USA", + "internationalPostalCode": null, + "province": null, + "stateCode": "NY", + "zipCode": "11249", + "zipCodeSuffix": "4101" + }, + "meta": { + "address": { + "confidenceScore": 100.0, + "addressType": "Domestic", + "deliveryPointValidation": "CONFIRMED", + "residentialDeliveryIndicator": "MIXED" + }, + "validationKey": -73046298 + } + } + ] +} +``` + +```rst +PUT /v0/user/addresses +``` + +### Multiple Addresses Request 2 + +```json +{ + "addressMetaData": { + "confidenceScore": 100.0, + "addressType": "Domestic", + "deliveryPointValidation": "CONFIRMED", + "residentialDeliveryIndicator": "MIXED" + }, + "addressLine1": "37 S 1st St", + "addressPou": "CORRESPONDENCE", + "addressType": "DOMESTIC", + "city": "Brooklyn", + "countryCodeIso3": "USA", + "stateCode": "NY", + "zipCode": "11249", + "zipCodeSuffix": "4101", + "id": 181513 +} +``` + +### Multiple Addresses Response 2 + +```json +{ + "data": { + "id": "b2e51260-00c9-4db6-80f6-b6c7541a9e54b2e51260-00c9-4db6-80f6-b6c7541a9e54", + "type": "async_transaction_vet360_address_transactions", + "attributes": { + "transactionId": "b2e51260-00c9-4db6-80f6-b6c7541a9e54", + "transactionStatus": "COMPLETED_SUCCESS", + "type": "AsyncTransaction::Vet360::AddressTransaction", + "metadata": [] + } + } +} +``` + +## Overridding and 'invalid' address + +```rst +POST /v0/user/addresses/validate +``` + +### Invalid Address Request + +```json +{ + "addressLine1": "4200 Weasel Rd", + "addressType": "DOMESTIC", + "city": "Columbus", + "countryName": "United States", + "countryCodeIso3": "USA", + "stateCode": "OH", + "zipCode": "43202", + "type": "DOMESTIC", + "addressPou": "CORRESPONDENCE" +} +``` + +### Invalid Address Response + +This response comes back with a 0% confidence score. We can let the user override the validation by passing back the `meta.validationKey` in the new/update request. + +```json +{ + "data": [ + { + "id": "6ba2f94b-c143-40da-8c5d-a76a637945b5", + "type": "suggested_address", + "attributes": { + "addressLine1": "4200 Weasel Rd", + "addressLine2": null, + "addressLine3": null, + "addressPou": "CORRESPONDENCE", + "addressType": "DOMESTIC", + "city": "Columbus", + "countryCodeIso3": "USA", + "internationalPostalCode": null, + "province": null, + "stateCode": "OH", + "zipCode": "43202", + "zipCodeSuffix": null + }, + "meta": { + "address": { + "confidenceScore": 0.0, + "addressType": "Domestic", + "deliveryPointValidation": "MISSING_ZIP" + }, + "validationKey": 377261722 + } + } + ] +} +``` + +```rst +PUT /v0/user/addresses +``` + +### User Addresses Request + +```json +{ + "validationKey": 377261722, + "addressLine1": "4200 Weasel Rd", + "addressType": "DOMESTIC", + "city": "Columbus", + "countryName": "United States", + "countryCodeIso3": "USA", + "stateCode": "OH", + "zipCode": "43202", + "type": "DOMESTIC", + "addressPou": "CORRESPONDENCE", + "id": 181513 +} +``` + +### User Addresses Response + +```json +{ + "data": { + "id": "b2e51260-00c9-4db6-80f6-b6c7541a9e54", + "type": "async_transaction_vet360_address_transactions", + "attributes": { + "transactionId": "b2e51260-00c9-4db6-80f6-b6c7541a9e54", + "transactionStatus": "COMPLETED_SUCCESS", + "type": "AsyncTransaction::Vet360::AddressTransaction", + "metadata": [] + } + } +} +``` diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Auth Diagrams.md b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Auth Diagrams.md index 08bf84f414a..fc4ecf8a3a1 100644 --- a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Auth Diagrams.md +++ b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Auth Diagrams.md @@ -2,10 +2,11 @@ title: Authentication Diagrams --- -### Username and Password Authorization Flow +## Username and Password Authorization Flow + ![Username and Password Authorization Flow](../../../../static/img/backend/username-and-password-authorization-flow.png) -``` +```yaml sequenceDiagram participant User participant App @@ -16,10 +17,11 @@ sequenceDiagram App-->>User: Display auth result ``` -### Biometrics Flow for Username and Password Initial Login +## Biometrics Flow for Username and Password Initial Login + ![Biometrics Flow for Username and Password Initial Login](../../../../static/img/backend/biometrics-flow-for-username-and-password-initial-login.png) -``` +```yaml sequenceDiagram participant User participant Keychain @@ -34,9 +36,11 @@ sequenceDiagram App-->>User: Display auth result ``` -### Biometrics Flow for Username and Password Subsequent Login +## Biometrics Flow for Username and Password Subsequent Login + ![Biometrics Flow for Username and Password Subsequent Login](../../../../static/img/backend/biometrics-flow-for-username-and-password-subsequent-login.png) -``` + +```yaml sequenceDiagram participant User participant Keychain @@ -53,9 +57,11 @@ sequenceDiagram App-->>User: Display auth result ``` -### VA: Health and Benefits Biometrics Initial Login +## VA: Health and Benefits Biometrics Initial Login + ![Health and Benefits Biometrics Initial Login](../../../../static/img/backend/health-and-benefits-biometrics-initial-login.png) -``` + +```yaml sequenceDiagram participant User participant Secure App Storage @@ -80,9 +86,11 @@ sequenceDiagram App-->>User: Display Auth Result ``` -### VA: Health and Benefits Biometrics Subsequent Login +## VA: Health and Benefits Biometrics Subsequent Login + ![Health and Benefits Biometrics Subsequent Login](../../../../static/img/backend/health-and-benefits-biometrics-subsequent-login.png) -``` + +```yaml sequenceDiagram participant User participant Secure App Storage @@ -99,4 +107,4 @@ sequenceDiagram App-->>User: Display Auth Result ``` -In order to regenerate these graphs, add 'mermaid' to the end of the \`\`\` at the beginning of each codeblock \ No newline at end of file +In order to regenerate these graphs, add 'mermaid' to the end of the \`\`\` at the beginning of each codeblock. diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Testing/Postman.md b/VAMobile/documentation/docs/Engineering/BackEnd/Testing/Postman.md new file mode 100644 index 00000000000..f92aa537471 --- /dev/null +++ b/VAMobile/documentation/docs/Engineering/BackEnd/Testing/Postman.md @@ -0,0 +1,16 @@ +--- +title: Postman +--- + +## Postman Collection +In the mobile module for vets-api, there is a [postman collection](https://github.com/department-of-veterans-affairs/vets-api/blob/master/modules/mobile/docs/Mobile%20Endpoints.postman_collection.json) that can be downloaded and used to run commands against +the staging instances. In order to use the collection, download the json file. + +After installing [Postman](https://www.postman.com), go to the collection section of Postman. From there, you can click "import", and drag +the file into the import window. + +### Layout +The top directory `Mobile Endpoints` contains the settings for authorization. +After aquiring a [token](./ApiTokens.md), click on the directory itself, open the `Authorization` tab, and paste the +token here. Every endpoint within the directory will now use +this token for the requests. diff --git a/VAMobile/documentation/docs/Engineering/DevOps/Automation Code Docs/GitHub Actions/ReleaseIssues.md b/VAMobile/documentation/docs/Engineering/DevOps/Automation Code Docs/GitHub Actions/ReleaseIssues.md index 2b61093dc3f..b15131e1289 100644 --- a/VAMobile/documentation/docs/Engineering/DevOps/Automation Code Docs/GitHub Actions/ReleaseIssues.md +++ b/VAMobile/documentation/docs/Engineering/DevOps/Automation Code Docs/GitHub Actions/ReleaseIssues.md @@ -49,3 +49,20 @@ Because the release is tied into a commit and not the current state of the branc 5. Run `git pull` to ensure you have the latest changes 6. Tag the branch with the version we're trying to release: `git tag -a RC-vX.XX.0-XXXXXX-XXXX -m RC-vX.XX.0-XXXXXX-XXXX` 7. Push the tag `git push origin RC-vX.XX.0-XXXXXX-XXXX` + +## Release Ticket Failure + +Outlined below are the steps to follow when the automation to create a release ticket and Slack coordination thread fails due to issues like incorrect GitHub username assignment. + +1. Update the [release_ticket](https://github.com/department-of-veterans-affairs/va-mobile-app/blob/develop/.github/ISSUE_TEMPLATE/release_ticket.md) template with the correct GitHub username and push to Github +2. Determine the version number of the build (vX.X.X) and RC tag RC-vX.XX.0-XXXXXX-XXXX you want to delete +3. Delete the local release candidate tag: `git tag --delete RC-vX.XX.0-XXXXXX-XXXX` +4. Delete the remote tag: `git push --delete origin ` +5. Delete the local release branch : `git branch -d ` +6. Delete the remote release branch: `git push origin --delete ` +7. Manually ran the [new_release_branch](https://github.com/department-of-veterans-affairs/va-mobile-app/blob/develop/.github/workflows/new_release_branch.yml) workflow using workflow_dispatch. +8. Confirm that: + 1. New RC tag. + 2. New release branch. + 3. release ticket has been created. + 4. Slack thread coordination has been triggered on va-mobile-app channel. \ No newline at end of file diff --git a/VAMobile/documentation/docs/Engineering/DevOps/Making pull requests.md b/VAMobile/documentation/docs/Engineering/DevOps/Making pull requests.md index 8183976f1bb..1720705cafa 100644 --- a/VAMobile/documentation/docs/Engineering/DevOps/Making pull requests.md +++ b/VAMobile/documentation/docs/Engineering/DevOps/Making pull requests.md @@ -4,18 +4,23 @@ position: 2 --- ## Install git + [Git - Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) + ### On Mac + Open terminal and run `git —version` If you do not already have it installed it will prompt you to install it. ### On Windows + [Git - Downloading Package](https://git-scm.com/download/win) ## sublime text -[Sublime Text - Text Editing, Done Right](https://www.sublimetext.com/) +[Sublime Text - Text Editing, Done Right](https://www.sublimetext.com/) ## Install GitHub Desktop + [GitHub Desktop | Simple collaboration from your desktop](https://desktop.github.com/) [Getting started with GitHub Desktop - GitHub Docs](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/overview/getting-started-with-github-desktop) @@ -23,157 +28,152 @@ Open terminal and run `git —version` If you do not already have it installed i Open the zip file. When Finder comes up, you will want to drag the application into the Applications folder -![](../../../static/img/making_changes/ss1.png) +![Mac downloads directory](../../../static/img/making_changes/ss1.png) You can then open the app from either the finder window or using quick search `⌘ + Space` and type GitHub desktop You may see a warning the first time you open the app, click Open -![](../../../static/img/making_changes/ss2.png) +![example warning](../../../static/img/making_changes/ss2.png) When the app opens it may ask you to log into GitHub. Once you are logged in you should see a screen like this: -![](../../../static/img/making_changes/ss3.png) +![getting started screen](../../../static/img/making_changes/ss3.png) Wait until your repositories list loads on the right -![](../../../static/img/making_changes/ss4.png) +![list of repositories in the app](../../../static/img/making_changes/ss4.png) Scroll or use search until you find `department-of-veterans-affairs/va-mobile-app` When you click on the repository name, you should get an option to clone the repository -![](../../../static/img/making_changes/ss5.png) +![highlighted text for the va-mobile-app repo](../../../static/img/making_changes/ss5.png) Click the clone button to pop up a modal. Choose the local path on your machine where you want to save it and click the clone button -![](../../../static/img/making_changes/ss6.png) +![example of fetching by URL](../../../static/img/making_changes/ss6.png) -![](../../../static/img/making_changes/ss7.png) +![cloning loading screen](../../../static/img/making_changes/ss7.png) -![](../../../static/img/making_changes/ss8.png) +![status update screen with no changes](../../../static/img/making_changes/ss8.png) ## Create a new branch + To create a branch, you first need to know what base you need. The base of the branch determines what code changes are available to your branch when you start it. If we think of develop as a trunk, then the two branches shown below will have slightly different code checked in because of where they are branched from. You can see that the yellow branch will have started and be missing two gray commits that the blue branch will have because of where it was based. -![](../../../static/img/making_changes/ss10.png) +![example branching model with dots and lines](../../../static/img/making_changes/ss10.png) This means we need to pay attention the to base branch when we make new branches. -In most cases, you will probably have two cases to choose from : +In most cases, you will probably have two cases to choose from: + 1. I am making new changes that need to get added to the app or wherever, but NOT for the release ticket. For these you will likely need to base off of the `develop` branch. 2. I am making change FOR a release ticket, such as what’s new or content changes that have to be in the next release. For these you will need to base it on the correct release branch and will need to do some extra work. ### If your new branch is based on `develop` + Click on the Current Branch tab at the top -![](../../../static/img/making_changes/ss11.png) +![comparing your branch to develop](../../../static/img/making_changes/ss11.png) There are a few ways to create a new branch. You can type in a branch name in the search, then click the `New Branch` or the `Create New Branch` button. -![](../../../static/img/making_changes/ss12.png) - +![searching for a branch name](../../../static/img/making_changes/ss12.png) You can also press `⌘ + Shift + N` to create a new branch from anywhere in the application. You will see this modal. Just enter your branch name and click `Create Branch` -![](../../../static/img/making_changes/ss13.png) +![creating a new branch](../../../static/img/making_changes/ss13.png) Once you have created your branch, you should see this: -![](../../../static/img/making_changes/ss14.png) +![status screen showing no changes](../../../static/img/making_changes/ss14.png) You can now start making your changes to the repository. There is no need to publish your branch at this time, we can make all of your changes first and then publish it. ### If your changes are for a release + You will need to copy the release branch from the remote repository to start. This is called pulling a remote. To do is in GH desktop, you will simple search for the branch on the server and double click it. Click on the current branch tab, type `release` into the search and double click the release branch you want to update. It should pre prefixed with `origin/` like you see below for `origin/release/v1.12.0`. Click the branch name and your GH Desktop will pull down that branch history and change to that branch for you. -![](../../../static/img/making_changes/ss15.png) +![searching for a release branch](../../../static/img/making_changes/ss15.png) Now that we have our starting place, we can then create a branch based on `release/v1.12.0`. Create a new branch any of the ways listed above, but when the create branch modal pops up, you will need to change the base branch from develop to the correct release branch. -![](../../../static/img/making_changes/ss16.png) +![release branch appearing in search results](../../../static/img/making_changes/ss16.png) Click the `release/vx.y.x` that is the correct version and click `Create Branch` You now have a branch that will update for only the release branch that you can now start making changes on. ## Open the repository in Sublime text + Open Sublime Text from your applications folder or using quick search `⌘ + Space` In GitHub Desktop, click on the Current Repository tab at the top and right click on `va-mobile-app`. Select `Reveal in Finder` -![](../../../static/img/making_changes/ss17.png) +![opening the repo](../../../static/img/making_changes/ss17.png) Click on the `va-mobile-app` text at the top of finder so that a folder icon pops up. Drag that icon onto the sublime text icon that should be visible in your dock area. -![](../../../static/img/making_changes/ss18.gif) +![a mac desktop opening a code editor](../../../static/img/making_changes/ss18.gif) Sublime text should open a new window with your files in a sidebar on the left and a black text editor in the middle. You can now navigate the files in the repo in order to make your changes. ## Making and saving changes + Once you have made changes to the files you want to update, you will need to save the changes in sublime to make them show up in GH Desktop. You can Save All changes with `Option(⌥) + ⌘ + S` If you now look at GH Desktop, you should see a list of changes in the left-hand tab. -![](../../../static/img/making_changes/ss19.png) +![changes active in the app UI](../../../static/img/making_changes/ss19.png) If you click on a file, you can see the set of changes for each file (called a diff). Green indicates a line was added. Red indicates the line was deleted. -![](../../../static/img/making_changes/ss20.png) -![](../../../static/img/making_changes/ss21.png) +![example of viewing changed files](../../../static/img/making_changes/ss20.png) +![another example of viewing changed files](../../../static/img/making_changes/ss21.png) ## Committing Changes + Once we have all the changes we want to make, we need to save the changes to our git history so that the repository is updated. We call this committing changes to git. To do so in GH Desktop, simple check the box to the left of each file that you want to save changes from. You can save all the changes at once or split up changes in a couple of commits if you want to add changes by some type of change grouping (i.e. all image updates in one commit, all text updates in a second). Its not necessary to do more than one commit, but if you make a lot of changes it can be helpful to break it up in case you make a mistake you need to undo(revert). -![](../../../static/img/making_changes/ss22.png) +![three circled checkboxes](../../../static/img/making_changes/ss22.png) Once you have selected all the changes you want to commit, you will need to enter a summary message and commit the changes. Add a summary message that explains the changes in case someone needs to review the history and can easily tell what you were up to. In this case I am making my message “update what’s new text for iOS and android”. Click `Commit to ` to save the changes to git. -![](../../../static/img/making_changes/ss23.png) +![example commit](../../../static/img/making_changes/ss23.png) GH Desktop should then show you a screen that says No local changes again. If you have more changes or more commits, go ahead and do those now. Once you have all the changes you want to make, you will need to publish your branch so that you can make a pull request. ## Publish your branch + In order to make a Pull Request and add your changes back onto the base branch, you will need to copy your local branch up onto the GitHub server. To do this, you just need to go to the GH Desktop app, and click either the `Publish Branch` tab at the top or the `Publish Branch` button in the Publish your branch area. The branch should get pushed up to the repository and you should then see an area to `Create Pull Request` -![](../../../static/img/making_changes/ss24.png) +![publish branch options circled](../../../static/img/making_changes/ss24.png) -![](../../../static/img/making_changes/ss25.png) +![status screen showing no changes](../../../static/img/making_changes/ss25.png) Now the only thing left to do is create a pull request so that others can review your changes before they are added to the repository. ## Create a Pull Request + Click the Create Pull Request button. This should open a browser window that takes you to a Pull Request template in the repository. -![](../../../static/img/making_changes/ss26.png) +![Github UI with an open pull request](../../../static/img/making_changes/ss26.png) Follow the template to add changes and explain to reviewers what is being added or subtracted from the code base. You should also connect the ticket to this PR request so that the two move through the ZenHub pipelines together. To do this, you will need the [ZenHub Browser Extension for Chrome and Firefox](https://www.zenhub.com/extension?utm_term=zenhub%20chrome%20extension&utm_campaign=Brand&utm_source=adwords&utm_medium=ppc&hsa_acc=8479887336&hsa_cam=14577630669&hsa_grp=127140912459&hsa_ad=544547662444&hsa_src=g&hsa_tgt=kwd-865948335962&hsa_kw=zenhub%20chrome%20extension&hsa_mt=e&hsa_net=adwords&hsa_ver=3&gclid=Cj0KCQiAuP-OBhDqARIsAD4XHpeArSRObIEEcSVF64ECWjuMc6zvVhYdBryYnkuwlxx1H2SghSnixR4aAlVyEALw_wcB) installed. Once this is installed, there should be a button under the text input for you to search the issues in our repo. -![](../../../static/img/making_changes/ss27.png) +![connecting an issue to zenhub](../../../static/img/making_changes/ss27.png) Click `Connect Issue` and search for the ticket by title or number -![](../../../static/img/making_changes/ss28.png) -![](../../../static/img/making_changes/ss29.png) +![searching for an issue](../../../static/img/making_changes/ss28.png) +![finding the issue you need](../../../static/img/making_changes/ss29.png) Once you have connected the issue, you should see something like this: -![](../../../static/img/making_changes/ss30.png) - -Next, you will need to add any specific reviewers you need. If you don’t know, you can leave it empty. Click the reviewers section on the right-hand side and search for folks you need to review. - -![](../../../static/img/making_changes/ss31.png) -![](../../../static/img/making_changes/ss32.png) - -Click on the user’s name to add them as a reviewer. You should see a check next to their name if you’re successful - -![](../../../static/img/making_changes/ss33.png) - -Click outside the box when you are done adding people. You should now see a list of reviewers with orange dots next to their names to indicate that they have not yet started a review - -![](../../../static/img/making_changes/ss34.png) +![github UI with the issue connected](../../../static/img/making_changes/ss30.png) Click the green `Create pull request` button to finish your work and send the PR for review. diff --git a/VAMobile/documentation/docs/Engineering/DevOps/Overview.md b/VAMobile/documentation/docs/Engineering/DevOps/Overview.md index cf370ccc995..ce9363015bf 100644 --- a/VAMobile/documentation/docs/Engineering/DevOps/Overview.md +++ b/VAMobile/documentation/docs/Engineering/DevOps/Overview.md @@ -4,6 +4,7 @@ postion: 1 --- ## Releases + Our releases are made live every other Tuesday morning. A GitHub Action runs every Tuesday morning to check and see if there is a staged build ready for developer release in the Apple App Store. For Play Store, it checks to see if there is a newer build than the production lane waiting in the Pre-Prod Stash lane. If there is, they are released to production at that time and sends a message to the main va-mobile-app channel in DSVA slack. If not, it completes silently. Release branches are cut by an Action every other Wednesday that follows a release. The release branch acts as a freeze on the develop branch for the next release that allows QA to run regressions from a static point and allows any last-minute changes to be added before being merged to main and build for review in the stores. This release branch being created then starts automation that creates the release ticket in GitHub and assigns the relevant people. @@ -13,13 +14,19 @@ Releases coincide with the last day of a sprint and new release branches are cut Release process approval ends with an authorized person (currently a VA Product Owner) releasing the app for build and upload to the stores by running the `/approve` command in the automated release ticket. This is accomplish by adding a comment to the issue in the form of `/approve vX.Y.Z` where X.Y.Z is the next version number. This version number should be present in the title of the ticket. Once the release is approved, the build system will create and upload production versions of the app to the App Stores for review. Barring any issues, these should be released on the next Tuesday when the release Action runs. -##### NOTE: *Because chrontab notation doesn't have a way to schedule a job at an interval , i.e. every two weeks, the release action has to be scheduled for EVERY Tuesday. This means that if the approve command is run before the Tuesday in the middle of the sprint, the releases will go out a week early.* + +:::note +Because chrontab notation doesn't have a way to schedule a job at an interval , i.e. every two weeks, the release action has to be scheduled for EVERY Tuesday. This means that if the approve command is run before the Tuesday in the middle of the sprint, the releases will go out a week early. +::: ## QA Builds + ### Daily Builds + Regular QA builds are distributed every weekday. These builds are based on the most current commit on the develop branch in order to provide QA with the most up-to-date versions as possible and can be augmented with the other types of builds. ### On Demand Builds + In addition to our automatically scheduled builds, we also have the ability to create QA or UAT builds at any time from any branch, also known as On Demand builds. The [On Demand Build Workflow](https://github.com/department-of-veterans-affairs/va-mobile-app/actions/workflows/on_demand_build.yml), which can also be found on the left hand sidebar in [GitHub Actions](https://github.com/department-of-veterans-affairs/va-mobile-app/actions), allows us to specify a branch and an environment to create a build from ([steps listed out in QA documentation](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/QA/QualityAssuranceProcess/Resources#on-demand-build)). ### On Demand Build Script diff --git a/VAMobile/documentation/docs/Engineering/FrontEnd/RemoteConfig/index.md b/VAMobile/documentation/docs/Engineering/FrontEnd/RemoteConfig/index.md new file mode 100644 index 00000000000..6412b2003ee --- /dev/null +++ b/VAMobile/documentation/docs/Engineering/FrontEnd/RemoteConfig/index.md @@ -0,0 +1,48 @@ +--- +title: Remote Config +--- + +Remote Configuration (Feature Flipper/Toggles) + +## Background + +Due of the growing complexity of the Flagship app and the types of features we are incorporating, we have an increasing need for the ability to manage aspects of the app remotely. In mobile, as in web, the best way to do this is by incorporating a remote configuration that allows features, behavior, and appearance aspects of the app to be updated without issuing a full app update. + +[Firebase's Remote Config](https://firebase.google.com/docs/remote-config) product allows us to store and modify values remotely, enable or disable certain app features, as well as roll them out to a certain percentage of users at a time. + +## Environments + +The values set in Firebase are for production only. Any overrides we'll use for development or in QA will be stored and overridden in our FE code in `src/utils/remoteConfig.ts`. The app will only fetch values from Firebase if it detects that our `ENVIRONMENT === 'Production'`. Otherwise it will use the defaults for staging/dev that are set in `remoteConfig.ts` + +## Guidelines + +1. The feature for consideration should be relatively self-contained and require a minimal amount of logic to switch between its enabled and disabled state (e.g. request appointment flow) +2. Addition of a new remote config value should be approved by the mobile platform team +3. Values should be named using snake case (i.e. `my_test_value`) +4. Values should be named using the feature by itself, and not any boolean indicating prefix or suffix such as `is` or `enabled` + +## Data Schema + +While the number of remote config values we have will be small, it's important that we set some guidelines about naming conventions and structure of our configurations as they grow. + +Firebase allows for 4 different data types: + +* String +* Boolean +* Number +* JSON + +For the foreseeable future, we'll only make use of the Boolean data type. + +The data schema will be a flat structure consisting of booleans: + +### Example + +```json +{ + "SIS": true, + "prescriptions": false, + "appointment_requests": false +} +``` + diff --git a/VAMobile/documentation/docs/Flagship design library/Components/documentation-guide.md b/VAMobile/documentation/docs/Flagship design library/Components/documentation-guide.md new file mode 100644 index 00000000000..a4eed3ed9c5 --- /dev/null +++ b/VAMobile/documentation/docs/Flagship design library/Components/documentation-guide.md @@ -0,0 +1,42 @@ +--- +title: Documentation Guide +sidebar_position: 1 +--- + +# Flagship Component Documentation Guide + +## Who does the work? + +Updating the documentation for a new component should be a collaboration between the design system team and the Flagship team when the component either currently lives within the design system or will be moved there in the future. It is recommended that you reach out to the Design System team to determine if a new component will remain in the Flagship team’s library or if it will be moved to the design system. + +If a new component is exclusive to the VAHB app and will **not** become part of the design system, the Flagship team member should move forward with detailed documentation of the component. When possible, please align with the current documentation outline that is being used by the design system team for consistency (see the [button component](https://department-of-veterans-affairs.github.io/va-mobile-app/design/Components/Buttons%20and%20links/Button) as an example). + +:::note +Guidance on writing documentation and templates for the documentation are included in the “Documentation resources” section below. +::: + +If the new component **will** eventually live within the design system, please coordinate with the Design System team so that they can update the [design system documentation](https://department-of-veterans-affairs.github.io/va-mobile-app/design/Intro) with the new component. The Flagship team member should document how the component is used with the VAHB mobile app, while the Design System team will focus on documenting how the component can be used universally. + +* **Design system team** documents: + * The various ways a component can be used. +* **Flagship team** documents: + * How the mobile app uses the component specifically (where, when, etc.). + +## Where does the documentation live? +We have an area on the documentation site for the [Flagship design library](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/Intro#). Within that section, there is another section for [Components](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/Flagship%20design%20library/Components/Overview). Currently, most of the documentation is engineering-focused and is not used to document the components (or their usage) themselves. Please use this area of the documentation site to house this documentation moving forward. + +Reference the list in the “What should we document?” section below as a guide to what should be updated (including the name of the page itself) vs. what should be added as a new page on the documentation site. + +## What should we document? +The design system team is responsible for documenting any components where the master lives (or will eventually live) within their library. The Flagship team is responsible for documenting any components where the master lives within their library. + +However, in many cases, the master component lives within the design system’s library (or will in the future) and the Flagship team will use instances of the master component in a specific way. In those cases, the Flagship team should document how they are using the component within the VA: Health and Benefits mobile app. + +## Documentation resources +We have several resources available to assist with writing documentation. + +* [Writing component documentation](https://department-of-veterans-affairs.github.io/va-mobile-app/design/About/Contributing%20to%20the%20design%20system/writing-component-documentation/) (documentation / guidance) +* [Documentation template](https://github.com/department-of-veterans-affairs/va-mobile-app/issues/new?assignees=&labels=component-documentation%2C+ux&template=common_component.md&title=Common+Component+Ticket%3A%5BInsert+name+of+component+here%5D) (in Github) + * _Can copy the markdown out of the template_ +* [Documentation template](https://docs.google.com/document/d/1DJoTdwXxUrjmCv8S9XwNvn4uVbd66jyE0XUwqzgZtc4/edit#heading=h.bhvl2fy62vsv) (in Google Docs) + * _Can use this and then convert to markdown_ \ No newline at end of file diff --git a/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md b/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md index 4f3fd64b994..ee1952145be 100644 --- a/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md +++ b/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md @@ -37,9 +37,9 @@ Understanding what’s guiding the app’s current information architecture and ### Sitemap/flow diagram A sitemap is a planning tool that visually shows how information will be grouped and labeled, where content will be located, and how a user will move through the app. This adaptation of a standard sitemap includes the system display logic for screens that have variants, key actions (buttons, links), common processes and points where it makes use of native mobile integrations. **This is the source of truth for the app’s IA.** - + -[VA Mobile App - Detailed sitemap 2.0 (FigJam)](https://www.figma.com/file/TEEgHdlibzCilCj4LviHVF/VA-Mobile-app---Detailed-Sitemap-2.0?type=whiteboard&node-id=0%3A1&t=NOXEk15mCNO0XQ5Q-1) +[VA Mobile App - Detailed sitemap 2.0](https://www.figma.com/design/bTPnmfYSuj1ICA4AqHMiQg/Sitemap%2FFlow-Diagram-2.0---%F0%9F%9A%A2-Shipped-(FJ)---VA-Mobile?node-id=0-1&t=5sKeYKmQ1pUk0rr1-1) diff --git a/VAMobile/documentation/docs/UX/How-We-Work/designing-ui.md b/VAMobile/documentation/docs/UX/How-We-Work/designing-ui.md index b81043d94ed..ef42b3d57ef 100644 --- a/VAMobile/documentation/docs/UX/How-We-Work/designing-ui.md +++ b/VAMobile/documentation/docs/UX/How-We-Work/designing-ui.md @@ -58,7 +58,7 @@ Once designs are ready to be handed off to the engineering team, you can review ### IA/Flows 1. Document the IA of your feature & where it lives in the app - - See: [Determining Navigation & Information Architecture Placement for New VA Mobile App Features](https://docs.google.com/document/d/1XQcYxnCifloaBFNKL2C9JNS7KIj6wEhb4VokPGxBZU8/edit) and [VA Mobile app: Detailed sitemap (future state 9-30-22](https://app.mural.co/invitation/mural/adhoccorporateworkspace2583/1655989910332?sender=u28718b63c8993f515e0b2240&key=6f96be43-72c9-4ae6-b529-a2941eb14ba9) + - See: [VA Mobile app - IA documentation](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/UX/Foundations/Information-Architecture#ia-documentation) for the app's sitemap and guidance on adding new features 2. Update category screens, if needed 3. Document intended flow 4. Defined back labels and screen title diff --git a/VAMobile/e2e/detoxMapping.json b/VAMobile/e2e/detoxMapping.json new file mode 100644 index 00000000000..44ea6ce829f --- /dev/null +++ b/VAMobile/e2e/detoxMapping.json @@ -0,0 +1,380 @@ +{ + "directory": { + "appointments": ["Appointments", "AppointmentsExpanded"], + "authorizedServices": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "Claims", + "DirectDeposit", + "DisabilityRatings", + "PersonalInformationScreen", + "VALetters", + "MilitaryInformation", + "Payments", + "Prescriptions", + "Messages", + "VeteranStatusCard" + ], + "claimsAndAppeals": ["Appeals", "AppealsExpanded", "Claims"], + "contactInformation": ["ContactInformation", "VALetters"], + "decisionLetters": ["DecisionLetters"], + "demographics": ["PersonalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"], + "directDeposit": ["DirectDeposit"], + "disabilityRating": ["DisabilityRatings", "VeteranStatusCard"], + "facilities": ["Cerner"], + "letters": ["VALetters"], + "militaryService": ["MilitaryInformation", "VeteranStatusCard"], + "notifications": ["SettingsScreen", "PushNotifications"], + "payments": ["Payments"], + "personalInformation": ["PersonalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"], + "prescriptions": ["Prescriptions"], + "secureMessaging": ["Messages"], + "types": [ + "AvailabilityFramework", + "Cerner", + "ContactInformation", + "VALetters", + "LoginScreen", + "Onboarding", + "ProfileScreen", + "PushNotifications", + "SettingsScreen", + "SignIn", + "VaccineRecords", + "Claims", + "Appeals", + "AppealsExpanded", + "DisabilityRatings", + "Appointments", + "AppointmentsExpanded", + "Prescriptions", + "Messages", + "MilitaryInformation", + "HomeScreen", + "VeteransCrisisLine", + "VeteranStatusCard", + "DirectDeposit", + "Payments", + "PersonalInformationScreen" + ], + "vaccines": ["VaccineRecords"], + "components": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "LoginScreen": ["LoginScreen"], + "AppealDetailsScreen": ["Appeals", "AppealsExpanded"], + "ClaimDetailsScreen": ["Claims"], + "ClaimLettersScreen": ["Claims"], + "ClaimsAndAppealsListView": ["Appeals", "AppealsExpanded", "Claims"], + "ClaimsHistoryScreen": ["Claims"], + "NeedHelpData": ["Appeals", "AppealsExpanded", "Claims"], + "NoClaimsAndAppeals": ["Appeals", "AppealsExpanded", "Claims"], + "NoClaimsAndAppealsAccess": ["Appeals", "AppealsExpanded", "Claims"], + "ClaimsScreen": ["Appeals", "AppealsExpanded", "Claims"], + "DisabilityRatingsScreen": ["DisabilityRatings", "VeteranStatusCard"], + "Letters": ["VALetters"], + "BenefitsScreen": ["DisabilityRatings", "Claims", "Appeals", "VALetters"], + "HealthScreen": ["Appointments", "AppointmentsExpanded", "Cerner", "Prescriptions", "Messages", "VaccineRecords"], + "Appointments": ["Appointments", "AppointmentsExpanded"], + "CernerAlert": ["Cerner"], + "HealthHelp": ["Cerner"], + "Pharmacy": ["Prescriptions"], + "SecureMessaging": ["Messages"], + "Vaccines": ["VaccineRecords"], + "HomeScreen": ["HomeScreen", "ProfileScreen", "VeteranStatusCard"], + "ContactVAScreen": ["HomeScreen"], + "ProfileScreen": [ + "ProfileScreen", + "ContactInformation", + "MilitaryInformation", + "PersonalInformationScreen", + "SettingsScreen", + "VALetters", + "Payments" + ], + "ContactInformationScreen": ["ContactInformation", "VALetters"], + "MilitaryInformationScreen": ["MilitaryInformation", "VeteranStatusCard"], + "PersonalInformationScreen": ["PersonalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"], + "SettingsScreen": ["SettingsScreen"], + "VeteransCrisisLineScreen": ["VeteransCrisisLine", "SignIn"], + "VeteranStatusScreen": ["VeteranStatusCard"], + "OnboardingCarousel": ["Onboarding"], + "PaymentsScreen": ["Payments", "DirectDeposit"], + "DirectDepositScreen": ["DirectDeposit"], + "PaymentHistory": ["Payments"], + "SplashScreen": ["Onboarding", "LoginScreen"], + "slices": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "translations": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "utils": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "device": [], + "BiometricsPreferenceScreen": [], + "SyncScreen": [], + "WebviewScreen": [], + "styles": [] + }, + "files": { + "accounts.ts": ["DirectDeposit"], + "appointments.ts": ["Appointments", "AppointmentsExpanded"], + "claims.ts": ["Claims", "Appeals", "AppealsExpanded"], + "common.ts": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "countries.ts": ["ContactInformation"], + "militaryPostOffices.ts": ["ContactInformation"], + "militaryStates.ts": ["ContactInformation"], + "screens.ts": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "secureMessaging.ts": ["Messages"], + "states.ts": ["ContactInformation"], + "appointments.json": ["Appointments", "AppointmentsExpanded"], + "claims.json": ["Claims", "Appeals", "AppealsExpanded"], + "contactInformation.json": ["ContactInformation", "VALetters"], + "decisionLetters.json": ["DecisionLetters"], + "disablityRating.json": ["DisabilityRatings"], + "getAuthorizedServices.json": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "Claims", + "DirectDeposit", + "DisabilityRatings", + "PersonalInformationScreen", + "VALetters", + "MilitaryInformation", + "Payments", + "Prescriptions", + "Messages", + "VeteranStatusCard" + ], + "getFacilitiesInfo.json": ["Cerner"], + "getFacilitiesInfoCerner.json": ["Cerner"], + "letters.json": ["VALetters"], + "notifications.json": ["SettingsScreen", "PushNotifications"], + "payments.json": ["Payments"], + "personalInformation.json": ["PersonalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"], + "prescriptions.json": ["Prescriptions"], + "profile.json": [ + "ProfileScreen", + "ContactInformation", + "MilitaryInformation", + "PersonalInformationScreen", + "SettingsScreen", + "VALetters", + "Payments" + ], + "secureMessaging.json": ["Messages"], + "vaccine.json": ["VaccineRecords"], + "decisionLetters.ts": ["DecisionLetters"], + "demographics.ts": ["PersonalInformationScreen", "VeteranStatusCard", "HomeScreen", "ProfileScreen"], + "disabilityRating.ts": ["DisabilityRatings"], + "letters.ts": ["VALetters"], + "notifications.ts": ["SettingsScreen", "PushNotifications"], + "payments.ts": ["Payments"], + "profile.ts": [ + "ProfileScreen", + "ContactInformation", + "MilitaryInformation", + "PersonalInformationScreen", + "SettingsScreen", + "VALetters", + "Payments" + ], + "vaccine.ts": ["VaccineRecords"], + "api.ts": [ + "Appeals", + "AppealsExpanded", + "Appointments", + "AppointmentsExpanded", + "AvailabilityFramework", + "Cerner", + "Claims", + "ContactInformation", + "DecisionLetters", + "DirectDeposit", + "DisabilityRatings", + "HomeScreen", + "LoginScreen", + "Messages", + "MilitaryInformation", + "Navigation", + "Onboarding", + "Payments", + "PersonalInformationScreen", + "Prescriptions", + "ProfileScreen", + "SettingsScreen", + "VaccineRecords", + "VALetters", + "VeteransCrisisLine", + "VeteranStatusCard" + ], + "analytics.ts": [], + "backButtonLabels.ts": [], + "documentTypes.ts": [], + "errors.ts": [], + "linking.tsx": [], + "namespaces.ts": [], + "store.ts": [], + "utils.ts": [] + } +} diff --git a/VAMobile/e2e/tests/Appeals.e2e.ts b/VAMobile/e2e/tests/Appeals.e2e.ts index 1ac75e392fa..e9ebacf7ed7 100644 --- a/VAMobile/e2e/tests/Appeals.e2e.ts +++ b/VAMobile/e2e/tests/Appeals.e2e.ts @@ -14,7 +14,6 @@ export const AppealsIdConstants = { REVIEW_PAST_EVENTS_ID: 'reviewPastEventsTestID', ISSUES_TAB_ID: 'appealIssues', STATUS_TAB_ID: 'appealStatus', - APPEALS_DETAILS_ID: 'appealsDetailsTestID', APPEAL_DETAILS_TEXT: 'Appeal details', APPEAL_TYPE_TEXT: 'Appeal for compensation', APPEAL_SUBMITTED_TEXT: 'Received June 12, 2008', @@ -86,7 +85,7 @@ describe('Appeals', () => { }) it('should scroll to the bottom of the appeals screen', async () => { - await element(by.id(AppealsIdConstants.APPEALS_DETAILS_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.APPEALS_DETAILS_ID)).scrollTo('bottom') }) it('should tap on the links in the need help section', async () => { diff --git a/VAMobile/e2e/tests/AppealsExpanded.e2e.ts b/VAMobile/e2e/tests/AppealsExpanded.e2e.ts index 46f4779e9f1..aee827a2d70 100644 --- a/VAMobile/e2e/tests/AppealsExpanded.e2e.ts +++ b/VAMobile/e2e/tests/AppealsExpanded.e2e.ts @@ -180,7 +180,7 @@ describe('AppealsExpanded', () => { if (appealInfo[2] === 'Opt in to the new decision review process') { await waitFor(element(by.text(appealInfo[2]))) .toBeVisible() - .whileElement(by.id('appealsDetailsTestID')) + .whileElement(by.id(CommonE2eIdConstants.APPEALS_DETAILS_ID)) .scroll(300, 'down') await element(by.text(appealInfo[2])).tap() await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap() diff --git a/VAMobile/e2e/tests/Appointments.e2e.ts b/VAMobile/e2e/tests/Appointments.e2e.ts index bb4322740c9..ba247203cfd 100644 --- a/VAMobile/e2e/tests/Appointments.e2e.ts +++ b/VAMobile/e2e/tests/Appointments.e2e.ts @@ -23,13 +23,7 @@ const lastYear = lastYearDateTime.get('year') export const Appointmentse2eConstants = { APPOINTMENT_DESCRIPTION: "Here are your appointments. This list includes appointments you've requested but not yet confirmed.", - ADD_TO_CALENDAR_ID: 'addToCalendarTestID', - GET_DIRECTIONS_ID: 'directionsTestID', - PHONE_NUMBER_ASSISTANCE_LINK_ID: 'CallVATestID', - PHONE_NUMBER_ID: 'CallTTYTestID', - PATIENT_CANCELLATION: 'You canceled this appointment.', VA_PAST_APPOINTMENT: 'To schedule another appointment, please visit VA.gov or call your VA medical center.', - DATE_RANGE_INITIAL_TEXT: 'Past 3 months', APPOINTMENT_CANCEL_REQUEST_TEXT: device.getPlatform() === 'ios' ? 'Cancel Request' : 'Cancel Request ', } @@ -47,31 +41,31 @@ describe('Appointments Screen', () => { .scroll(200, 'down') await element(by.text('Vilanisi Reddy')).tap() if (device.getPlatform() === 'android') { - await element(by.id(Appointmentse2eConstants.ADD_TO_CALENDAR_ID)).atIndex(0).tap() + await element(by.id(CommonE2eIdConstants.ADD_TO_CALENDAR_ID)).atIndex(0).tap() await device.takeScreenshot('appointmentCalendar') await device.launchApp({ newInstance: false }) - await element(by.id(Appointmentse2eConstants.GET_DIRECTIONS_ID)).atIndex(0).tap() + await element(by.id(CommonE2eIdConstants.GET_DIRECTIONS_ID)).atIndex(0).tap() await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap() await device.takeScreenshot('appointmentGetDirections') await device.launchApp({ newInstance: false }) await device.disableSynchronization() - await element(by.id(Appointmentse2eConstants.PHONE_NUMBER_ID)).atIndex(0).tap() + await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0).tap() await device.takeScreenshot('appointmentVALocationPhoneNumber') await device.launchApp({ newInstance: false }) - await element(by.id(Appointmentse2eConstants.PHONE_NUMBER_ASSISTANCE_LINK_ID)).atIndex(0).tap() + await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0).tap() await device.takeScreenshot('apointmentVALocationTTY') await device.launchApp({ newInstance: false }) await element(by.id('UpcomingApptDetailsTestID')).scrollTo('bottom') - await element(by.id(Appointmentse2eConstants.PHONE_NUMBER_ID)).atIndex(1).tap() + await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(1).tap() await device.takeScreenshot('appointmentCancelPhoneNumber') await device.launchApp({ newInstance: false }) - await element(by.id(Appointmentse2eConstants.PHONE_NUMBER_ASSISTANCE_LINK_ID)).atIndex(1).tap() + await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(1).tap() await device.takeScreenshot('appointmentCancelTTY') await device.launchApp({ newInstance: false }) await device.enableSynchronization() @@ -89,7 +83,7 @@ describe('Appointments Screen', () => { await element(by.id('Cancel request')).tap() await element(by.text(Appointmentse2eConstants.APPOINTMENT_CANCEL_REQUEST_TEXT)).tap() await expect(element(by.text('Request canceled'))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() }) it('verify the appointment details after cancel', async () => { @@ -106,21 +100,21 @@ describe('Appointments Screen', () => { await element(by.id(CommonE2eIdConstants.APPOINTMENTS_SCROLL_ID)).scrollTo('top') await element(by.id('apptsPastID')).tap() if (device.getPlatform() === 'android') { - await expect(element(by.text(Appointmentse2eConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0)).toExist() + await expect(element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0)).toExist() } else { - await expect(element(by.text(Appointmentse2eConstants.DATE_RANGE_INITIAL_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT))).toExist() } }) it('should show the same date field after cancelling', async () => { await element(by.id('getDateRangeTestID')).tap() if (device.getPlatform() === 'android') { - await element(by.text(Appointmentse2eConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0).tap() + await element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0).tap() await element(by.id('pastApptsDateRangeCancelID')).tap() - await expect(element(by.text(Appointmentse2eConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0)).toExist() + await expect(element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0)).toExist() } else { await element(by.id('pastApptsDateRangeCancelID')).tap() - await expect(element(by.text(Appointmentse2eConstants.DATE_RANGE_INITIAL_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT))).toExist() } }) diff --git a/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts b/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts index 46d00f5bd0f..ad24d0f609f 100644 --- a/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts +++ b/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts @@ -2,8 +2,8 @@ import { by, device, element, expect, waitFor } from 'detox' import { CommonE2eIdConstants, loginToDemoMode, openAppointments, openHealth, toggleRemoteConfigFlag } from './utils' -export const Appointmentse2eConstants = { - GET_DIRECTIONS_ID: 'directionsTestID', +export const AppointmentsExpandede2eConstants = { + PATIENT_CANCELLATION: 'You canceled this appointment.', } const checkMedicationWording = async ({ @@ -192,15 +192,15 @@ const checkUpcomingApptDetails = async ( await expect(element(by.text(locationAddress))).toExist() if (appointmentStatus !== 'Pending' && appointmentType !== 'CC') { await expect(element(by.id('directionsTestID'))).toExist() - await expect(element(by.id('CallVATestID')).atIndex(0)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist() } } else { await expect(element(by.text('Where to attend'))).not.toExist() } if (!pastAppointment) { if (appointmentStatus === 'Confirmed') { - await expect(element(by.id('addToCalendarTestID'))).toExist() + await expect(element(by.id(CommonE2eIdConstants.ADD_TO_CALENDAR_ID))).toExist() if ( appointmentType === 'Atlas' || appointmentType === 'Home' || @@ -226,8 +226,8 @@ const checkUpcomingApptDetails = async ( await expect(element(by.text('Middletown VA Clinic'))).toExist() } } - await expect(element(by.id('CallVATestID')).atIndex(1)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(1)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(1)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(1)).toExist() } } else if (appointmentStatus === 'Canceled') { if ( @@ -267,8 +267,8 @@ const checkUpcomingApptDetails = async ( await expect(element(by.text('Middletown VA Clinic'))).toExist() } } - await expect(element(by.id('CallVATestID')).atIndex(1)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(1)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(1)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(1)).toExist() await expect(element(by.id('vaLinkApptsCancelTestID'))).toExist() } } else if (appointmentStatus === 'Pending') { @@ -330,8 +330,8 @@ const checkUpcomingApptDetails = async ( if (appointmentType != 'Phone' && appointmentType != 'CC') { await expect(element(by.text('Middletown VA Clinic'))).toExist() } - await expect(element(by.id('CallVATestID')).atIndex(1)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(1)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(1)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(1)).toExist() } } await checkMedicationWording({ appointmentType, appointmentStatus, pastAppointment }) @@ -423,7 +423,7 @@ export async function apppointmentVerification(pastAppointment = false) { it(pastAppointmentString + 'verify canceled CC appt', async () => { await scrollToThenTap('Jim Smith', pastAppointmentString) await expect(element(by.text('Canceled community care appointment'))).toExist() - await expect(element(by.text('You canceled this appointment.'))).toExist() + await expect(element(by.text(AppointmentsExpandede2eConstants.PATIENT_CANCELLATION))).toExist() await checkUpcomingApptDetails( 'CC', @@ -489,7 +489,7 @@ export async function apppointmentVerification(pastAppointment = false) { it(pastAppointmentString + 'verify canceled VA video connect - Onsite appt', async () => { await scrollToThenTap('Sami Alsahhar - Onsite - Canceled', pastAppointmentString) - await expect(element(by.text('You canceled this appointment.'))).toExist() + await expect(element(by.text(AppointmentsExpandede2eConstants.PATIENT_CANCELLATION))).toExist() await expect(element(by.text('Canceled video appointment at VA location'))).toExist() await expect( element(by.text('If you need to reschedule this appointment, call us or schedule a new appointment on VA.gov.')), @@ -515,9 +515,9 @@ export async function apppointmentVerification(pastAppointment = false) { if (pastAppointment) { await element(by.text('Past')).tap() if (device.getPlatform() === 'android') { - await element(by.text('Past 3 months')).atIndex(1).tap() + await element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(1).tap() } else { - await element(by.text('Past 3 months')).atIndex(0).tap() + await element(by.text(CommonE2eIdConstants.DATE_RANGE_INITIAL_TEXT)).atIndex(0).tap() } await element(by.text('All of 2023')).tap() await element(by.text('Done')).tap() @@ -570,7 +570,7 @@ export async function apppointmentVerification(pastAppointment = false) { it(pastAppointmentString + 'verify canceled VA video connect - ATLAS appt', async () => { await scrollToThenTap('Sami Alsahhar - ATLAS - Canceled', pastAppointmentString) await expect(element(by.text('Canceled video appointment at an ATLAS location'))).toExist() - await expect(element(by.text('You canceled this appointment.'))).toExist() + await expect(element(by.text(AppointmentsExpandede2eConstants.PATIENT_CANCELLATION))).toExist() await expect( element( by.text( @@ -632,7 +632,7 @@ export async function apppointmentVerification(pastAppointment = false) { it(pastAppointmentString + 'verify canceled VA video connect - Home appt', async () => { await scrollToThenTap('Sami Alsahhar - HOME - Canceled', pastAppointmentString) - await expect(element(by.text('You canceled this appointment.'))).toExist() + await expect(element(by.text(AppointmentsExpandede2eConstants.PATIENT_CANCELLATION))).toExist() await expect(element(by.text('Canceled video appointment'))).toExist() await checkUpcomingApptDetails( 'Home', @@ -681,7 +681,7 @@ export async function apppointmentVerification(pastAppointment = false) { it(pastAppointmentString + 'verify canceled VA video connect - GFE appt', async () => { await scrollToThenTap('Sami Alsahhar - GFE - Canceled', pastAppointmentString) - await expect(element(by.text('You canceled this appointment.'))).toExist() + await expect(element(by.text(AppointmentsExpandede2eConstants.PATIENT_CANCELLATION))).toExist() await checkUpcomingApptDetails( 'GFE', 'Canceled', @@ -857,7 +857,7 @@ export async function apppointmentVerification(pastAppointment = false) { ), ).toExist() if (!pastAppointment) { - await expect(element(by.id(Appointmentse2eConstants.GET_DIRECTIONS_ID))).toExist() + await expect(element(by.id(CommonE2eIdConstants.GET_DIRECTIONS_ID))).toExist() } await expect(element(by.text('Go to VA.gov to find your VA facility'))).toExist() await element(by.text('Appointments')).tap() @@ -872,8 +872,8 @@ export async function apppointmentVerification(pastAppointment = false) { ), ), ).toExist() - await expect(element(by.id('CallVATestID')).atIndex(0)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist() await element(by.text('Appointments')).tap() }) @@ -887,10 +887,10 @@ export async function apppointmentVerification(pastAppointment = false) { ), ).toExist() if (!pastAppointment) { - await expect(element(by.id(Appointmentse2eConstants.GET_DIRECTIONS_ID))).toExist() + await expect(element(by.id(CommonE2eIdConstants.GET_DIRECTIONS_ID))).toExist() } - await expect(element(by.id('CallVATestID')).atIndex(0)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist() await element(by.text('Appointments')).tap() }) @@ -935,7 +935,7 @@ export async function apppointmentVerification(pastAppointment = false) { ), ).toExist() if (!pastAppointment) { - await expect(element(by.id(Appointmentse2eConstants.GET_DIRECTIONS_ID))).toExist() + await expect(element(by.id(CommonE2eIdConstants.GET_DIRECTIONS_ID))).toExist() } await expect(element(by.text('Go to VA.gov to find your VA facility'))).toExist() await element(by.text('Appointments')).tap() @@ -976,8 +976,8 @@ export async function apppointmentVerification(pastAppointment = false) { ), ), ).toExist() - await expect(element(by.id('CallVATestID')).atIndex(0)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist() await element(by.text('Appointments')).tap() }) @@ -990,8 +990,8 @@ export async function apppointmentVerification(pastAppointment = false) { ), ), ).toExist() - await expect(element(by.id('CallVATestID')).atIndex(0)).toExist() - await expect(element(by.id('CallTTYTestID')).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0)).toExist() + await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist() await element(by.text('Appointments')).tap() }) @@ -1068,7 +1068,7 @@ export async function apppointmentVerification(pastAppointment = false) { it(pastAppointmentString + 'verify canceled phone appt', async () => { await scrollToThenTap('Phone consultation-Canceled', pastAppointmentString) - await expect(element(by.text('You canceled this appointment.'))).toExist() + await expect(element(by.text(AppointmentsExpandede2eConstants.PATIENT_CANCELLATION))).toExist() await checkUpcomingApptDetails( 'Phone', 'Canceled', diff --git a/VAMobile/e2e/tests/Cerner.e2e.ts b/VAMobile/e2e/tests/Cerner.e2e.ts index 3831539e16b..286b7e4f658 100644 --- a/VAMobile/e2e/tests/Cerner.e2e.ts +++ b/VAMobile/e2e/tests/Cerner.e2e.ts @@ -20,7 +20,6 @@ export const CernerIdConstants = { CERNER_NOTE_HEADING_ID: 'cernerAlertTestID', CERNER_NOTE_RECORDS_SHOW_TEXT: "You'll need to use our My VA Health portal to manage your care at these facilities:", CERNER_NOTE_FACILITY_TEXT: 'Cary VA Medical Center', - CERNER_NOTE_FACILITY_2_TEXT: 'Cheyenne VA Medical Center', CERNER_NOTE_MESSAGES_TEXT: 'Sending a message to a care team at these facilities:', CERNER_NOTE_MESSAGES_HEADER_TEXT: 'Your care team uses My VA Health', CERNER_HOME_SUBTEXT_TEXT: 'Information from My VA Health portal not included.', @@ -40,17 +39,17 @@ beforeAll(async () => { await openDeveloperScreen() await waitFor(element(by.text('Remote Config'))) .toBeVisible() - .whileElement(by.id('developerScreenTestID')) + .whileElement(by.id(CommonE2eIdConstants.DEVELOPER_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text('Remote Config')).tap() await waitFor(element(by.text('cernerTrueForDemo'))) .toBeVisible() - .whileElement(by.id('remoteConfigTestID')) + .whileElement(by.id(CommonE2eIdConstants.REMOTE_CONFIG_TEST_ID)) .scroll(200, 'down') await element(by.text('cernerTrueForDemo')).tap() await waitFor(element(by.text('Apply Overrides'))) .toBeVisible() - .whileElement(by.id('remoteConfigTestID')) + .whileElement(by.id(CommonE2eIdConstants.REMOTE_CONFIG_TEST_ID)) .scroll(200, 'down') await element(by.text('Apply Overrides')).tap() @@ -63,7 +62,7 @@ describe(':android: Cerner Notice', () => { it('should match the cerner subtext on home screen', async () => { await waitFor(element(by.text(CernerIdConstants.CERNER_HOME_SUBTEXT_TEXT))) .toBeVisible() - .whileElement(by.id('homeScreenID')) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await expect(element(by.text(CernerIdConstants.CERNER_HOME_SUBTEXT_TEXT))).toExist() }) @@ -96,9 +95,7 @@ describe(':android: Cerner Notice', () => { await element(by.id(CernerIdConstants.HEALTH_CATEGORY_ID)).scrollTo('top') await openAppointments() await expect(element(by.id(CernerIdConstants.CERNER_NOTE_HEADING_ID))).toExist() - await expect( - element(by.text("You'll need to use our My VA Health portal to manage your care at these facilities:")), - ).not.toExist() + await expect(element(by.text(CernerIdConstants.CERNER_NOTE_RECORDS_SHOW_TEXT))).not.toExist() }) it('should match the cerner notice design', async () => { @@ -108,7 +105,7 @@ describe(':android: Cerner Notice', () => { .whileElement(by.id(CommonE2eIdConstants.APPOINTMENTS_SCROLL_ID)) .scroll(200, 'down') await expect(element(by.text(CernerIdConstants.CERNER_NOTE_FACILITY_TEXT))).toExist() - await expect(element(by.text(CernerIdConstants.CERNER_NOTE_FACILITY_2_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CHEYENNE_FACILITY_TEXT))).toExist() await expect(element(by.id(CernerIdConstants.GO_TO_VA_HEALTH_LINK_ID))).toExist() }) @@ -124,7 +121,7 @@ describe(':android: Cerner Notice', () => { await element(by.id(CommonE2eIdConstants.APPOINTMENTS_SCROLL_ID)).swipe('down') await element(by.text(CernerIdConstants.CERNER_NOTE_HEADING_TEXT)).tap() await expect(element(by.text(CernerIdConstants.CERNER_NOTE_FACILITY_TEXT))).not.toExist() - await expect(element(by.text(CernerIdConstants.CERNER_NOTE_FACILITY_2_TEXT))).not.toExist() + await expect(element(by.text(CommonE2eIdConstants.CHEYENNE_FACILITY_TEXT))).not.toExist() }) it('tap on messages and verify the cerner notification is present and collapsed', async () => { @@ -136,9 +133,9 @@ describe(':android: Cerner Notice', () => { it('verify the correct information is displayed for multiple facilities', async () => { await element(by.id(CernerIdConstants.CERNER_NOTE_HEADING_ID)).tap() - await expect(element(by.text('Sending a message to a care team at these facilities:'))).toExist() - await expect(element(by.text('Cheyenne VA Medical Center'))).toExist() - await expect(element(by.text('Cary VA Medical Center'))).toExist() + await expect(element(by.text(CernerIdConstants.CERNER_NOTE_MESSAGES_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CHEYENNE_FACILITY_TEXT))).toExist() + await expect(element(by.text(CernerIdConstants.CERNER_NOTE_FACILITY_TEXT))).toExist() await expect(element(by.text("You'll need to use our My VA Health portal to send your message"))).toExist() await expect(element(by.id(CernerIdConstants.GO_TO_VA_HEALTH_LINK_ID))).toExist() }) diff --git a/VAMobile/e2e/tests/Claims.e2e.ts b/VAMobile/e2e/tests/Claims.e2e.ts index 3e1cbe51138..4309db11d83 100644 --- a/VAMobile/e2e/tests/Claims.e2e.ts +++ b/VAMobile/e2e/tests/Claims.e2e.ts @@ -12,7 +12,6 @@ import { } from './utils' export const ClaimsE2eIdConstants = { - ALERT_FILE_REQUEST_BUTTON_ID: 'Review file requests', CLAIM_1_ID: 'Compensation Received December 05, 2021 Step 1 of 5: Claim received Moved to this step on December 05, 2021', CLAIM_2_ID: 'Compensation Received December 04, 2021 Step 5 of 5: Complete Moved to this step on December 04, 2021', @@ -23,8 +22,6 @@ export const ClaimsE2eIdConstants = { 'Compensation Received March 22, 2019 Step 3 of 5: Evidence gathering, review, and decision Moved to this step on July 18, 2019', CLAIM_6_ID: 'Dependency Received January 01, 2016 Step 4 of 5: Preparation for notification Moved to this step on July 30, 2016', - CLOSED_CLAIM_DECISION_LETTER_ID: - 'Compensation Decision letter ready Received January 01, 2021 Step 5 of 5: Complete Moved to this step on April 09, 2021', CLAIM_3_STATUS_STEP_1_ID: 'Step 1 of 5. Claim received. Complete.', CLAIM_3_STATUS_STEP_2_ID: 'Step 2 of 5. Initial review. Current step. Step 1 complete.', CLAIM_3_STATUS_STEP_3_ID: 'Step 3 of 5. Evidence gathering, review, and decision. Incomplete.', @@ -38,18 +35,12 @@ export const ClaimsE2eIdConstants = { CLAIM_4_STATUS_STEP_6_ID: 'Step 6 of 8. Preparing decision letter. Incomplete.', CLAIM_4_STATUS_STEP_7_ID: 'Step 7 of 8. Final review. Incomplete.', CLAIM_4_STATUS_STEP_8_ID: 'Step 8 of 8. Claim decided. Incomplete.', - GET_CLAIMS_LETTER_BUTTON_ID: 'getClaimLettersTestID', FILE_REQUEST_BUTTON_ID: 'Step3FileRequestButton', 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 ', SELECT_A_FILE_TEXT: 'Select a file', TAKE_OR_SELECT_PHOTOS_TEXT: 'Take or select photos', ACCEPTED_FILE_TYPES_TEXT: 'PDF (unlocked), GIF, JPEG, JPG, BMP, TXT', MAXIMUM_FILE_SIZE_LABEL: '50 megabytes', - CLAIMS_HISTORY_SCREEN_ID: 'claimsHistoryID', - CLAIMS_DETAILS_BACK_ID: 'claimsDetailsBackTestID', CLAIMS_STATUS_ID: 'claimsStatusID', CLAIMS_FILES_ID: 'claimsFilesID', CLAIMS_WHY_COMBINE_LINK_ID: 'claimDetailsWhyWeCombineLinkID', @@ -85,7 +76,7 @@ describe('Claims Screen', () => { }) it('Verify the claim status detail page (8-step claim)', async () => { - await scrollToIDThenTap(ClaimsE2eIdConstants.CLAIM_4_ID, ClaimsE2eIdConstants.CLAIMS_HISTORY_SCREEN_ID) + await scrollToIDThenTap(ClaimsE2eIdConstants.CLAIM_4_ID, CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID) await expect(element(by.id(ClaimsE2eIdConstants.CLAIMS_STATUS_ID))).toExist() await expect(element(by.id(ClaimsE2eIdConstants.CLAIMS_FILES_ID))).toExist() await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_4_STATUS_STEP_1_ID))).toExist() @@ -97,11 +88,11 @@ describe('Claims Screen', () => { 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(CommonE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)).scrollTo('top') - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() }) it('Verify the claim status detail page (5-step claim)', async () => { - await scrollToIDThenTap(ClaimsE2eIdConstants.CLAIM_3_ID, ClaimsE2eIdConstants.CLAIMS_HISTORY_SCREEN_ID) + await scrollToIDThenTap(ClaimsE2eIdConstants.CLAIM_3_ID, CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID) await expect(element(by.id(ClaimsE2eIdConstants.CLAIMS_STATUS_ID))).toExist() await expect(element(by.id(ClaimsE2eIdConstants.CLAIMS_FILES_ID))).toExist() await expect(element(by.id(ClaimsE2eIdConstants.CLAIM_3_STATUS_STEP_1_ID))).toExist() @@ -165,7 +156,7 @@ describe('Claims Screen', () => { }) it('should navigate back to the claims history page', async () => { - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() }) it('automatically expands and scrolls to current step and dates match', async () => { @@ -175,11 +166,11 @@ describe('Claims Screen', () => { it('should verify that the review file request alert is visible', async () => { await expect(element(by.label('You have 3 file requests')).atIndex(1)).toExist() - await waitFor(element(by.id(ClaimsE2eIdConstants.ALERT_FILE_REQUEST_BUTTON_ID))).toExist() + await waitFor(element(by.id(CommonE2eIdConstants.ALERT_FILE_REQUEST_BUTTON_ID))).toExist() }) it('should verify that user is sent to File requests screen', async () => { - await element(by.id(ClaimsE2eIdConstants.ALERT_FILE_REQUEST_BUTTON_ID)).tap() + await element(by.id(CommonE2eIdConstants.ALERT_FILE_REQUEST_BUTTON_ID)).tap() await expect(element(by.text('You have 3 file requests from VA'))).toExist() await expect(element(by.text('Dental disability - More information needed'))).toExist() }) @@ -219,13 +210,13 @@ describe('Claims Screen', () => { it('should verify details of claim on step 1', async () => { await element(by.id(ClaimsE2eIdConstants.ASK_FOR_CLAIM_DECISION_BACK)).tap() await element(by.id(ClaimsE2eIdConstants.FILE_REQUEST_BACK)).tap() - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() - await element(by.id(ClaimsE2eIdConstants.CLAIMS_HISTORY_SCREEN_ID)).scrollTo('top') + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID)).scrollTo('top') await element(by.id(ClaimsE2eIdConstants.CLAIM_1_ID)).tap() await expect(element(by.id('Step 1 of 5. Claim received. Current step.'))).toExist() await expect(element(by.text(ClaimsE2eIdConstants.CURRENT_STEP_TEXT))).toExist() await expect(element(by.text('Thank you. VA received your claim'))).toExist() - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() }) it('should verify details of claim on step 2', async () => { @@ -272,7 +263,7 @@ describe('Claims Screen', () => { // } else { // await element(by.id(ClaimsE2eIdConstants.SELECT_A_FILE_TEXT)).atIndex(1).tap() // } - // await expect(element(by.text(ClaimsE2eIdConstants.SELECT_A_FILE_FILE_FOLDER_OPTION_TEXT))).toExist() + // await expect(element(by.text(CommonE2eIdConstants.FILE_FOLDER_TEXT))).toExist() // await expect(element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT))).toExist() // }) @@ -300,8 +291,8 @@ describe('Claims Screen', () => { // } 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() + // await expect(element(by.text(CommonE2eIdConstants.CAMERA_TEXT))).toExist() + // await expect(element(by.text(CommonE2eIdConstants.PHOTO_GALLERY_TEXT))).toExist() // }) // it('should navigate back to the claim details screen', async () => { @@ -315,10 +306,10 @@ describe('Claims Screen', () => { // }) it('should verify details of claim on step 3 w/ waiver', async () => { - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() await waitFor(element(by.id(ClaimsE2eIdConstants.CLAIM_5_ID))) .toBeVisible() - .whileElement(by.id(ClaimsE2eIdConstants.CLAIMS_HISTORY_SCREEN_ID)) + .whileElement(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID)) .scroll(100, 'down') await element(by.id(ClaimsE2eIdConstants.CLAIM_5_ID)).tap() await setTimeout(2000) @@ -341,29 +332,29 @@ describe('Claims Screen', () => { ), ), ).toExist() - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() }) it('should verify details of claim on step 4', async () => { await waitFor(element(by.id(ClaimsE2eIdConstants.CLAIM_6_ID))) .toBeVisible() - .whileElement(by.id(ClaimsE2eIdConstants.CLAIMS_HISTORY_SCREEN_ID)) + .whileElement(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID)) .scroll(100, 'down') await element(by.id(ClaimsE2eIdConstants.CLAIM_6_ID)).tap() await expect( element(by.id('Step 4 of 5. 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.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() }) it('should verify details of claim on step 5', async () => { - await element(by.id(ClaimsE2eIdConstants.CLAIMS_HISTORY_SCREEN_ID)).scrollTo('top') + await element(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID)).scrollTo('top') await element(by.id(ClaimsE2eIdConstants.CLAIM_2_ID)).tap() await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)).scrollTo('bottom') await element(by.id('Step 5 of 5. Complete. Complete.')).tap() await expect(element(by.text('Complete')).atIndex(1)).toExist() - await element(by.id(ClaimsE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap() }) it('should tap on the closed tab', async () => { @@ -371,7 +362,7 @@ describe('Claims Screen', () => { }) it('verify the status details page of closed claim with decision letter', async () => { - await element(by.id(ClaimsE2eIdConstants.CLOSED_CLAIM_DECISION_LETTER_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLOSED_CLAIM_DECISION_LETTER_ID)).tap() await expect(element(by.text('Decision letter ready'))).toExist() await expect( element( diff --git a/VAMobile/e2e/tests/ContactInformation.e2e.ts b/VAMobile/e2e/tests/ContactInformation.e2e.ts index 3660979a305..36a6a9a9d66 100644 --- a/VAMobile/e2e/tests/ContactInformation.e2e.ts +++ b/VAMobile/e2e/tests/ContactInformation.e2e.ts @@ -4,7 +4,6 @@ import { setTimeout } from 'timers/promises' import { CommonE2eIdConstants, loginToDemoMode, openContactInfo, openProfile, toggleRemoteConfigFlag } from './utils' export const ContactInfoE2eIdConstants = { - CONTACT_INFO_PAGE_ID: 'ContactInfoTestID', MAILING_ADDRESS_ID: 'Mailing address 3101 N Fort Valley Rd Flagstaff, AZ, 86001', MAILING_ADDRESS_2_ID: 'Mailing address 3101 N Fort Valley Rd, 2 Flagstaff, AZ, 86001', HOME_ADDRESS_ID: 'Home address Add your home address', @@ -15,7 +14,6 @@ export const ContactInfoE2eIdConstants = { HOW_WE_USE_TEXT: 'How we use your contact information', COUNTRY_PICKER_ID: 'countryPickerTestID', STREET_ADDRESS_LINE_1_ID: 'streetAddressLine1TestID', - STREET_ADDRESS_LINE_2_ID: 'streetAddressLine2TestID', STREET_ADDRESS_LINE_3_ID: 'streetAddressLine3TestID', MILITARY_POST_OFFICE_ID: 'militaryPostOfficeTestID', CITY_TEST_ID: 'cityTestID', @@ -23,12 +21,8 @@ export const ContactInfoE2eIdConstants = { ZIP_CODE_ID: 'zipCodeTestID', PHONE_NUMBER_EXTENSION_ID: 'phoneNumberExtensionTestID', PHONE_NUMBER_ID: 'phoneNumberTestID', - CANCEL_DELETE_TEXT: device.getPlatform() === 'ios' ? 'Delete Changes' : 'Delete Changes ', - CANCEL_KEEP_EDITING_TEXT: device.getPlatform() === 'ios' ? 'Keep Editing' : 'Keep Editing ', REMOVE_KEEP_TEXT: 'Keep', REMOVE_REMOVE_TEXT: 'Remove', - SAVE_TEXT: 'Save', - DISMISS_TEXT: 'Dismiss', EDIT_ADDRESS_ID: 'EditAddressTestID', COUNTRY_PICKER_CONFIRM_ID: 'countryPickerConfirmID', STATE_PICKER_CONFIRM_ID: 'statePickerConfirmID', @@ -82,10 +76,10 @@ export async function fillHomeAddressFields() { export async function validateAddresses(addressID: string, addressType: string) { it('update the ' + addressType + ' address', async () => { - await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)).scrollTo('top') + await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)).scrollTo('top') await waitFor(element(by.id(addressID))) .toBeVisible() - .whileElement(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(50, 'down') await element(by.id(addressID)).tap() }) @@ -103,12 +97,12 @@ export async function validateAddresses(addressID: string, addressType: string) await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_BACK_ID)).tap() await setTimeout(2000) await expect(element(by.text('Delete changes to your ' + addressType.toLowerCase() + ' address?'))).toExist() - await expect(element(by.text(ContactInfoE2eIdConstants.CANCEL_DELETE_TEXT))).toExist() - await expect(element(by.text(ContactInfoE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() }) it(addressType + ': verify fields are filled on keep editing', async () => { - await element(by.text(ContactInfoE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() await expect(element(by.text('United States'))).toExist() await expect(element(by.text('3101 N Fort Valley Rd')).atIndex(0)).toExist() await expect(element(by.text('2'))).toExist() @@ -119,15 +113,15 @@ export async function validateAddresses(addressID: string, addressType: string) it(addressType + ': verify contact info screen is displayed on delete', async () => { await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_BACK_ID)).tap() - await element(by.text(ContactInfoE2eIdConstants.CANCEL_DELETE_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT)).tap() await expect(element(by.id(addressID))).toExist() }) it('should open and update the ' + addressType + ' address', async () => { - await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)).scrollTo('top') + await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)).scrollTo('top') await waitFor(element(by.id(addressID))) .toBeVisible() - .whileElement(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(100, 'down') await element(by.id(addressID)).tap() await element(by.id(CommonE2eIdConstants.CONTACT_INFO_STREET_ADDRESS_LINE_2_ID)).typeText('2') @@ -170,7 +164,7 @@ export async function validateAddresses(addressID: string, addressType: string) try { await setTimeout(5000) await expect(element(by.text(addressType + ' address saved'))).toExist() - await element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() } catch (ex) {} }) @@ -183,7 +177,7 @@ export async function validatePhoneNumbers(phoneID: string, phoneType: string) { it('should open the ' + phoneType + ' phone number', async () => { await waitFor(element(by.id(phoneID))) .toBeVisible() - .whileElement(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(100, 'down') await element(by.id(phoneID)).tap() }) @@ -223,12 +217,12 @@ export async function validatePhoneNumbers(phoneID: string, phoneType: string) { await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_BACK_ID)).tap() await setTimeout(2000) await expect(element(by.text('Delete changes to your ' + phoneType.toLowerCase() + ' phone number?'))).toExist() - await expect(element(by.text(ContactInfoE2eIdConstants.CANCEL_DELETE_TEXT))).toExist() - await expect(element(by.text(ContactInfoE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() }) it(phoneType + ': verify fields are filled on keep editing', async () => { - await element(by.text(ContactInfoE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() await expect(element(by.text('276-608-6180')).atIndex(0)).toExist() await expect(element(by.text('1234'))).toExist() }) @@ -236,14 +230,14 @@ export async function validatePhoneNumbers(phoneID: string, phoneType: string) { it(phoneType + ': verify contact info screen is displayed on delete', async () => { await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_BACK_ID)).tap() await setTimeout(2000) - await element(by.text(ContactInfoE2eIdConstants.CANCEL_DELETE_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT)).tap() await expect(element(by.id(phoneID))).toExist() }) it('should update the ' + phoneType + ' with an extension', async () => { await waitFor(element(by.id(phoneID))) .toBeVisible() - .whileElement(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(100, 'down') await element(by.id(phoneID)).tap() if (phoneType === 'Work') { @@ -269,17 +263,17 @@ export async function validatePhoneNumbers(phoneID: string, phoneType: string) { try { await setTimeout(2000) await expect(element(by.text(phoneType + ' phone saved'))).toExist() - await waitFor(element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT))) + await waitFor(element(by.text(CommonE2eIdConstants.DISMISS_TEXT))) .toBeVisible() .withTimeout(4000) - await element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() } catch (ex) {} }) it(phoneType + ': verify user can remove the extension', async () => { await waitFor(element(by.id(phoneID))) .toBeVisible() - .whileElement(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(100, 'down') await element(by.id(phoneID)).tap() await element(by.id(ContactInfoE2eIdConstants.PHONE_NUMBER_EXTENSION_ID)).clearText() @@ -291,20 +285,20 @@ export async function validatePhoneNumbers(phoneID: string, phoneType: string) { try { await setTimeout(2000) await expect(element(by.text(phoneType + ' phone saved'))).toExist() - await waitFor(element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT))) + await waitFor(element(by.text(CommonE2eIdConstants.DISMISS_TEXT))) .toBeVisible() .withTimeout(4000) - await element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() } catch (ex) {} }) } export async function removeContactInfoFeature(contactInfoTypeText: string, type: string) { it('should tap remove ' + type + ' and verify remove pop up appears', async () => { - await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)).scrollTo('top') + await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)).scrollTo('top') await waitFor(element(by.id(contactInfoTypeText))) .toBeVisible() - .whileElement(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(100, 'down') await element(by.id(contactInfoTypeText)).tap() await element(by.text('Remove ' + type)).tap() @@ -333,10 +327,10 @@ export async function removeContactInfoFeature(contactInfoTypeText: string, type await setTimeout(2000) await element(by.text(ContactInfoE2eIdConstants.REMOVE_REMOVE_TEXT)).tap() try { - await waitFor(element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT))) + await waitFor(element(by.text(CommonE2eIdConstants.DISMISS_TEXT))) .toBeVisible() .withTimeout(4000) - await element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() } catch (ex) {} if (type === 'home phone' || type === 'work phone') { await expect(element(by.text('Add your ' + type + ' number'))).toExist() @@ -428,7 +422,7 @@ describe(':ios: Contact Info Screen', () => { it('verify how we use your contact information link', async () => { await expect(element(by.id(ContactInfoE2eIdConstants.HOW_WE_USE_CONTACT_INFO_LINK_ID))).toExist() await element(by.id(ContactInfoE2eIdConstants.HOW_WE_USE_CONTACT_INFO_LINK_ID)).tap() - await expect(element(by.text('How we use your contact information')).atIndex(0)).toExist() + await expect(element(by.text(ContactInfoE2eIdConstants.HOW_WE_USE_TEXT)).atIndex(0)).toExist() await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_CLOSE_ID)).atIndex(0).tap() }) @@ -443,7 +437,7 @@ describe(':ios: Contact Info Screen', () => { removeContactInfoFeature(ContactInfoE2eIdConstants.MOBILE_PHONE_ID, 'mobile phone') it('should open the email address', async () => { - await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)).scrollTo('bottom') await element(by.id(ContactInfoE2eIdConstants.EMAIL_ADDRESS_ID)).tap() }) @@ -464,12 +458,12 @@ describe(':ios: Contact Info Screen', () => { try { await setTimeout(5000) await expect(element(by.text('Email address saved'))).toExist() - await element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() } catch (ex) {} }) it('should update the email address and remove the +', async () => { - await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)).scrollTo('bottom') await element(by.id(ContactInfoE2eIdConstants.EMAIL_ADDRESS_ID)).tap() await element(by.id(ContactInfoE2eIdConstants.EMAIL_ADDRESS_EDIT_ID)).clearText() await element(by.id(ContactInfoE2eIdConstants.EMAIL_ADDRESS_EDIT_ID)).typeText('attended1@gmail.com') @@ -481,9 +475,9 @@ describe(':ios: Contact Info Screen', () => { try { await setTimeout(5000) await expect(element(by.text('Email address saved'))).toExist() - await element(by.text(ContactInfoE2eIdConstants.DISMISS_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() } catch (ex) {} - await element(by.id(ContactInfoE2eIdConstants.CONTACT_INFO_PAGE_ID)).scrollTo('top') + await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)).scrollTo('top') }) removeContactInfoFeature(ContactInfoE2eIdConstants.EMAIL_ADDRESS_ID, 'email address') diff --git a/VAMobile/e2e/tests/DecisionLetters.e2e.ts b/VAMobile/e2e/tests/DecisionLetters.e2e.ts index 0d348afbf13..f8436d5a95f 100644 --- a/VAMobile/e2e/tests/DecisionLetters.e2e.ts +++ b/VAMobile/e2e/tests/DecisionLetters.e2e.ts @@ -11,14 +11,12 @@ import { } from './utils' export const DecisionLettersE2eIDConstants = { - CLOSED_CLAIM_DECISION_LETTER_ID: - 'Compensation Decision letter ready Received January 01, 2021 Step 5 of 5: Complete Moved to this step on April 09, 2021', - GET_CLAIMS_LETTER_BUTTON_ID: 'getClaimLettersTestID', DECISION_CLAIM_LETTER_1_ID: 'March 11, 2023 letter Notification Letter (e.g. VA 20-8993, VA 21-0290, PCGL)', DECISION_CLAIM_LETTER_2_ID: 'September 21, 2022 letter Decision Rating Letter', CLAIMS_HISTORY_TEXT: 'Claims history', CLAIM_LETTERS_BACK_ID: 'claimLettersBackTestID', TO_DECISION_LETTERS_ID: 'toClaimLettersID', + GET_CLAIMS_LETTER_BUTTON_ID: 'getClaimLettersTestID', } beforeAll(async () => { @@ -35,7 +33,7 @@ describe('Decision Letters Screen', () => { }) it('verify the status details page of closed claim with decision letter', async () => { - await element(by.id(DecisionLettersE2eIDConstants.CLOSED_CLAIM_DECISION_LETTER_ID)).tap() + await element(by.id(CommonE2eIdConstants.CLOSED_CLAIM_DECISION_LETTER_ID)).tap() await expect(element(by.id(DecisionLettersE2eIDConstants.GET_CLAIMS_LETTER_BUTTON_ID))).toExist() }) diff --git a/VAMobile/e2e/tests/DirectDeposit.e2e.ts b/VAMobile/e2e/tests/DirectDeposit.e2e.ts index 8fdb94e1252..dd3ab57cef6 100644 --- a/VAMobile/e2e/tests/DirectDeposit.e2e.ts +++ b/VAMobile/e2e/tests/DirectDeposit.e2e.ts @@ -15,7 +15,6 @@ export const DirectDepositConstants = { 'You can find your 9-digit routing number on the bottom left side of a check. You can find your account number in the bottom center of a check.', WHERE_CAN_I_FIND_ID: 'directDepositFindTheseNumbersID', CANCEL_CONFIRM_TEXT: 'Delete changes to your direct deposit information?', - CANCEL_CONFIRM_BUTTON_TEXT: device.getPlatform() === 'ios' ? 'Delete Changes' : 'Delete Changes ', SAVE_ID: 'directDepositSaveID', BACK_ID: 'directDepositBackID', DIRECT_DEPOSIT_EDIT_SCROLL_ID: 'DirectDepositEditAccount', @@ -79,7 +78,7 @@ describe('Direct Deposit Screen', () => { await expect(element(by.text('Check your direct deposit information'))).toExist() await expect(element(by.text('Enter a 9-digit routing number'))).toExist() await element(by.id(DirectDepositConstants.BACK_ID)).tap() - await element(by.text(DirectDepositConstants.CANCEL_CONFIRM_BUTTON_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT)).tap() }) it('should fill out Account form for checking', async () => { @@ -100,7 +99,7 @@ describe('Direct Deposit Screen', () => { await expect(element(by.text('*************4567'))).toExist() await expect(element(by.text('Checking account'))).toExist() await expect(element(by.text('Direct deposit information saved'))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() }) it('should fill out Account form for savings', async () => { @@ -121,7 +120,7 @@ describe('Direct Deposit Screen', () => { await expect(element(by.text('Savings account'))).toExist() await setTimeout(2000) await expect(element(by.text('Direct deposit information saved'))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() }) it('should show cancel confirmation after user enters information', async () => { @@ -131,7 +130,7 @@ describe('Direct Deposit Screen', () => { await element(by.id(DirectDepositConstants.DIRECT_DEPOSIT_EDIT_ROUTING_NUM_ID)).typeText('053100300\n') await element(by.id(DirectDepositConstants.BACK_ID)).tap() await expect(element(by.text(DirectDepositConstants.CANCEL_CONFIRM_TEXT))).toExist() - await element(by.text(DirectDepositConstants.CANCEL_CONFIRM_BUTTON_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT)).tap() await expect(element(by.text(DirectDepositConstants.SCREEN_TITLE))).toExist() }) diff --git a/VAMobile/e2e/tests/HomeScreen.e2e.ts b/VAMobile/e2e/tests/HomeScreen.e2e.ts index a067ade839e..06f5abbbc6e 100644 --- a/VAMobile/e2e/tests/HomeScreen.e2e.ts +++ b/VAMobile/e2e/tests/HomeScreen.e2e.ts @@ -4,11 +4,9 @@ import { setTimeout } from 'timers/promises' import { CommonE2eIdConstants, checkImages, disableAF, enableAF, loginToDemoMode, verifyAF } from './utils' export const HomeE2eIdConstants = { - PAYMENTS_BTN_ID: 'Payments', VETERAN_STATUS_TEXT: 'Proof of Veteran status', - LOCATION_FINDER_ROW_TEXT: 'Find a VA location', + LOCATION_FINDER_TEXT: 'Find a VA location', CONTACT_VA_ROW_TEXT: 'Contact us', - HOME_PAGE_MILITARY_BRANCH: 'United States Coast Guard', CONTACT_VA_TITLE: 'Call My V-A 4 1 1', CONTACT_VA_BODY: 'My V-A 4 1 1 is our main V-A information line. We can help connect you to any of our V-A contact centers.', @@ -19,11 +17,9 @@ export const HomeE2eIdConstants = { PRESCRIPTIONS_BUTTON_SUBTEXT_TEXT: '10 ready to refill', ANNOUNCEMENT_BANNER_TEXT: 'Learn about PACT Act on VA.gov', DISABILITY_RATING_TITLE_TEXT: 'Disability rating', - DISABILITY_RATING_PERCENT_TEXT: '100%', DISABILITY_RATING_SUBTEXT_TEXT: 'service connected', MONTHLY_PAYMENT_TITLE_TEXT: 'Monthly compensation payment', MONTHLY_PAYMENT_AMOUNT_TEXT: '$3,084.75', - HOME_SCREEN_SCROLL_ID: 'homeScreenID', } beforeAll(async () => { @@ -112,7 +108,7 @@ describe('Home Screen', () => { await element(by.text(CommonE2eIdConstants.HOME_TAB_BUTTON_TEXT)).tap() await waitFor(element(by.text(HomeE2eIdConstants.APPOINTMENTS_BUTTON_SUBTEXT_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(HomeE2eIdConstants.APPOINTMENTS_BUTTON_SUBTEXT_TEXT)).atIndex(0).tap() await expect(element(by.text(CommonE2eIdConstants.UPCOMING_APPT_BUTTON_TEXT))).toExist() @@ -122,7 +118,7 @@ describe('Home Screen', () => { await element(by.text(CommonE2eIdConstants.HOME_TAB_BUTTON_TEXT)).tap() await waitFor(element(by.text(HomeE2eIdConstants.CLAIMS_BUTTON_SUBTEXT_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(HomeE2eIdConstants.CLAIMS_BUTTON_SUBTEXT_TEXT)).tap() await expect(element(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID))).toExist() @@ -132,7 +128,7 @@ describe('Home Screen', () => { await element(by.text(CommonE2eIdConstants.HOME_TAB_BUTTON_TEXT)).tap() await waitFor(element(by.text(HomeE2eIdConstants.MESSAGES_BUTTON_SUBTEXT_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(HomeE2eIdConstants.MESSAGES_BUTTON_SUBTEXT_TEXT)).tap() await expect(element(by.id(CommonE2eIdConstants.START_NEW_MESSAGE_BUTTON_ID))).toExist() @@ -142,7 +138,7 @@ describe('Home Screen', () => { await element(by.text(CommonE2eIdConstants.HOME_TAB_BUTTON_TEXT)).tap() await waitFor(element(by.text(HomeE2eIdConstants.PRESCRIPTIONS_BUTTON_SUBTEXT_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(HomeE2eIdConstants.PRESCRIPTIONS_BUTTON_SUBTEXT_TEXT)).tap() await expect(element(by.id(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_ID))).toExist() @@ -155,27 +151,27 @@ describe('Home Screen', () => { } catch (e) {} await waitFor(element(by.text(HomeE2eIdConstants.MONTHLY_PAYMENT_AMOUNT_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') - await expect(element(by.text(HomeE2eIdConstants.HOME_PAGE_MILITARY_BRANCH))).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_BRANCH_COAST_GUARD))).toExist() await expect(element(by.text(HomeE2eIdConstants.VETERAN_STATUS_TEXT))).toExist() const militaryBadge = await element(by.id('United States Coast Guard Emblem')).takeScreenshot( 'MilitaryServiceBadgeHome', ) checkImages(militaryBadge) await expect(element(by.text(HomeE2eIdConstants.DISABILITY_RATING_TITLE_TEXT))).toExist() - await expect(element(by.text(HomeE2eIdConstants.DISABILITY_RATING_PERCENT_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.DISABILITY_RATING_PERCENT_TEXT))).toExist() await expect(element(by.text(HomeE2eIdConstants.DISABILITY_RATING_SUBTEXT_TEXT))).toExist() await expect(element(by.text(HomeE2eIdConstants.MONTHLY_PAYMENT_TITLE_TEXT))).toExist() await expect(element(by.text(HomeE2eIdConstants.MONTHLY_PAYMENT_AMOUNT_TEXT))).toExist() }) it('should show home page VA Resources content', async () => { - await waitFor(element(by.text(HomeE2eIdConstants.LOCATION_FINDER_ROW_TEXT))) + await waitFor(element(by.text(HomeE2eIdConstants.LOCATION_FINDER_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') - await expect(element(by.text(HomeE2eIdConstants.LOCATION_FINDER_ROW_TEXT))).toExist() + await expect(element(by.text(HomeE2eIdConstants.LOCATION_FINDER_TEXT))).toExist() await expect(element(by.text(HomeE2eIdConstants.CONTACT_VA_ROW_TEXT))).toExist() }) @@ -206,7 +202,7 @@ describe('Home Screen', () => { try { await element(by.text('Skip this update')).tap() } catch (e) {} - await element(by.text(HomeE2eIdConstants.LOCATION_FINDER_ROW_TEXT)).tap() + await element(by.text(HomeE2eIdConstants.LOCATION_FINDER_TEXT)).tap() await setTimeout(5000) await device.takeScreenshot('HomeFindAVALocationScreenshot') }) @@ -215,7 +211,7 @@ describe('Home Screen', () => { await element(by.text('Done')).tap() await waitFor(element(by.text(HomeE2eIdConstants.ANNOUNCEMENT_BANNER_TEXT))) .toBeVisible() - .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID)) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await expect(element(by.text(HomeE2eIdConstants.ANNOUNCEMENT_BANNER_TEXT))).toExist() }) diff --git a/VAMobile/e2e/tests/LoginScreen.e2e.ts b/VAMobile/e2e/tests/LoginScreen.e2e.ts index 1be4a16dddf..e70374713a4 100644 --- a/VAMobile/e2e/tests/LoginScreen.e2e.ts +++ b/VAMobile/e2e/tests/LoginScreen.e2e.ts @@ -3,7 +3,6 @@ import { by, element, expect, waitFor } from 'detox' import { CommonE2eIdConstants, checkImages } from './utils' export const LoginE2eIdConstants = { - LOGIN_PAGE_ID: 'Login-page', LOGIN_FIND_VA_BUTTON_ID: 'Find a VA location', LOGIN_APP_VERSION_ID: 'AppVersionTestID', } diff --git a/VAMobile/e2e/tests/Messages.e2e.ts b/VAMobile/e2e/tests/Messages.e2e.ts index fa91c9bc234..e73ff99233c 100644 --- a/VAMobile/e2e/tests/Messages.e2e.ts +++ b/VAMobile/e2e/tests/Messages.e2e.ts @@ -27,9 +27,6 @@ export const MessagesE2eIdConstants = { REVIEW_MESSAGE_REPLY_ID: 'replyTestID', ONLY_USE_MESSAGES_TEXT: 'Only use messages for non-urgent needs', ATTACHMENTS_BUTTON_ID: 'messagesAttachmentsAddFilesID', - ATTACHMENT_CAMERA_TEXT: device.getPlatform() === 'ios' ? 'Camera' : 'Camera ', - ATTACHMENT_PHOTO_GALLERY_TEXT: device.getPlatform() === 'ios' ? 'Photo Gallery' : 'Photo gallery ', - ATTACHMENT_FILE_FOLDER_TEXT: device.getPlatform() === 'ios' ? 'File Folder' : 'File folder ', MESSAGE_INPUT_ID: 'reply field', SEND_BUTTON_ID: 'sendButtonTestID', SELECT_A_FILE_ID: 'messagesSelectAFileID', @@ -44,12 +41,9 @@ export const MessagesE2eIdConstants = { START_NEW_MESSAGE_SAVE_ID: 'startNewMessageSaveTestID', START_NEW_MESSAGE_CANCEL_ID: 'startNewMessageCancelTestID', MESSAGE_CANCEL_DELETE_TEXT: device.getPlatform() === 'ios' ? 'Delete' : 'Delete ', - MESSAGE_CANCEL_KEEP_EDITING_TEXT: device.getPlatform() === 'ios' ? 'Keep Editing' : 'Keep Editing ', MESSAGE_CANCEL_SAVE_TEXT: device.getPlatform() === 'ios' ? 'Save' : 'Save ', - VIEW_MESSAGE_ID: 'viewMessageTestID', EDIT_DRAFT_MESSAGE_FIELD_ID: 'messageText', EDIT_DRAFT_CANCEL_ID: 'editDraftCancelTestID', - EDIT_DRAFT_CANCEL_DELETE_TEXT: device.getPlatform() === 'ios' ? 'Delete Changes' : 'Delete Changes ', EDIT_DRAFT_CANCEL_SAVE_TEXT: device.getPlatform() === 'ios' ? 'Save Changes' : 'Save Changes ', EDIT_DRAFT_PAGE_TEST_ID: 'editDraftTestID', BACK_TO_MESSAGES_ID: 'backToMessagesID', @@ -65,12 +59,12 @@ export const MessagesE2eIdConstants = { const tapItems = async (items: string, type: string) => { // if (type === 'url' || type === 'map' || type === 'email') { // if (items != 'https://www.va.gov/') { - // await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') + // await element(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') // } // } await waitFor(element(by.text(items))) .toBeVisible() - .whileElement(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)) + .whileElement(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)) .scroll(50, 'down') await device.disableSynchronization() await element(by.text(items)).tap() @@ -247,7 +241,7 @@ describe('Messages Screen', () => { }) it('should tap reply and verify the correct information is displayed', async () => { - await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') await element(by.id(MessagesE2eIdConstants.REVIEW_MESSAGE_REPLY_ID)).tap() await expect(element(by.id('To RATANA, NARIN '))).toExist() await expect(element(by.id('Subject Medication: Naproxen side effects'))).toExist() @@ -258,7 +252,7 @@ describe('Messages Screen', () => { it('reply: verify talk to the veterans crisis line now is displayed', async () => { await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID)).tap() - await expect(element(by.text('Veterans Crisis Line'))).toExist() + await expect(element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_HEADING_TEXT))).toExist() await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BACK_ID)).tap() }) @@ -287,9 +281,9 @@ describe('Messages Screen', () => { it('verify tap select a file action sheet options are correct', async () => { await element(by.id(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_ID)).tap() await element(by.id(MessagesE2eIdConstants.SELECT_A_FILE_ID)).tap() - await expect(element(by.text(MessagesE2eIdConstants.ATTACHMENT_CAMERA_TEXT))).toExist() - await expect(element(by.text(MessagesE2eIdConstants.ATTACHMENT_PHOTO_GALLERY_TEXT))).toExist() - await expect(element(by.text(MessagesE2eIdConstants.ATTACHMENT_FILE_FOLDER_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CAMERA_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.PHOTO_GALLERY_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.FILE_FOLDER_TEXT))).toExist() }) it('should close the action sheet and tap cancel', async () => { @@ -312,15 +306,15 @@ describe('Messages Screen', () => { await expect(element(by.text("If you save as a draft, we'll remove the attachments."))).toExist() await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_DELETE_TEXT))).toExist() await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_SAVE_TEXT))).toExist() - await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_KEEP_EDITING_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() }) it('should tap keep editing and send the message', async () => { - await element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_KEEP_EDITING_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() await element(by.id(MessagesE2eIdConstants.REPLY_PAGE_TEST_ID)).scroll(300, 'down', NaN, 0.8) await element(by.id(MessagesE2eIdConstants.SEND_BUTTON_ID)).tap() await expect(element(by.text('Message sent'))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() }) it('should tap and move a message', async () => { @@ -329,7 +323,7 @@ describe('Messages Screen', () => { await element(by.text('Custom Folder 2')).tap() await element(by.id(MessagesE2eIdConstants.MOVE_PICKER_CONFIRM_ID)).tap() await expect(element(by.text('Message moved to Custom Folder 2'))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap() }) @@ -346,14 +340,14 @@ describe('Messages Screen', () => { it(':ios: new message: verify talk to the veterans crisis line now', async () => { await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID)).tap() - await expect(element(by.text('Veterans Crisis Line'))).toExist() + await expect(element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_HEADING_TEXT))).toExist() await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BACK_ID)).tap() }) it(':ios: verify only use messages for non-urgent needs information', async () => { await element(by.id(MessagesE2eIdConstants.START_NEW_MESSAGE_ID)).scroll(300, 'down', NaN, 0.8) await element(by.id(MessagesE2eIdConstants.START_NEW_MESSAGE_ONLY_USE_MESSAGES_ID)).tap() - await expect(element(by.text('Only use messages for non-urgent needs'))) + await expect(element(by.text(MessagesE2eIdConstants.ONLY_USE_MESSAGES_TEXT))) await expect(element(by.text('Your care team may take up to 3 business days to reply.'))).toExist() await expect(element(by.text('If you need help sooner, use one of these urgent communication options:'))).toExist() await device.disableSynchronization() @@ -434,11 +428,11 @@ describe('Messages Screen', () => { await expect(element(by.text("If you save as a draft, we'll remove the attachments."))).toExist() await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_DELETE_TEXT))).toExist() await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_SAVE_TEXT))).toExist() - await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_KEEP_EDITING_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() }) it(':ios: verify the previous made fields are filled on keep editing', async () => { - await element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_KEEP_EDITING_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() await expect(element(by.text('VA Flagship mobile applications interface_DAYT29'))).toExist() await expect(element(by.text('Medication'))).toExist() }) @@ -469,7 +463,7 @@ describe('Messages Screen', () => { 'Va Flagship Mobile Applications Interface 2_dayt29 November 16, 2024 Appointment: Preparing for your visit', ), ).tap() - await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') await expect(element(by.text('Melvin Freeman\nUSMC Veteran'))).toExist() await expect(element(by.text('See you at your appointment. Please do not forget to fast.'))).toExist() await expect(element(by.text('Testing '))).toExist() @@ -483,7 +477,7 @@ describe('Messages Screen', () => { }) it('verify message threads with more than two lines', async () => { - await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') messageCollapsed = await device.takeScreenshot('MessageCollapsed') checkImages(messageCollapsed) await element( @@ -491,7 +485,7 @@ describe('Messages Screen', () => { 'Please fast for at least 12 hours before your upcoming visit on October 19th. Eating or drinking anything besides water will have an effect on your blood lab results. Thank you.', ), ).tap() - await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') messageExpanded = await device.takeScreenshot('MessageExpanded') await element(by.text('Sent')).tap() await element(by.text('Messages')).tap() @@ -514,19 +508,19 @@ describe('Messages Screen', () => { await element(by.id(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_ID)).tap() await expect(element(by.text('Delete changes to draft?'))).toExist() await expect(element(by.text("If you save your changes, we'll remove the attachments."))).toExist() - await expect(element(by.text(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_DELETE_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT))).toExist() await expect(element(by.text(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_SAVE_TEXT))).toExist() - await expect(element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_KEEP_EDITING_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT))).toExist() }) it('drafts: verify the previous made fields are filled on keep editing', async () => { - await element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_KEEP_EDITING_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_KEEP_EDITING_TEXT)).tap() await expect(element(by.text('Testing'))).toExist() }) it('verify that the draft is still in the list after cancel', async () => { await element(by.id(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_ID)).tap() - await element(by.text(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_DELETE_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.CANCEL_DELETE_CHANGES_BUTTON_TEXT)).tap() await expect(element(by.text('Test: Test Inquiry'))).toExist() }) @@ -544,7 +538,7 @@ describe('Messages Screen', () => { await element(by.id(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_ID)).tap() await element(by.text(MessagesE2eIdConstants.EDIT_DRAFT_CANCEL_SAVE_TEXT)).tap() await expect(element(by.text('Draft saved'))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() }) it('should open a draft message and verify it can be deleted', async () => { diff --git a/VAMobile/e2e/tests/MilitaryInformation.e2e.ts b/VAMobile/e2e/tests/MilitaryInformation.e2e.ts index 18e7b514ed3..f3a243561fa 100644 --- a/VAMobile/e2e/tests/MilitaryInformation.e2e.ts +++ b/VAMobile/e2e/tests/MilitaryInformation.e2e.ts @@ -11,7 +11,6 @@ import { } from './utils' export const MilitaryInformationE2eIdConstants = { - MILITARY_DATE_TEXT: 'July 13, 1970 – August 31, 1998', SERVICE_INFORMATION_INCORRECT_ID: 'militaryServiceIncorrectLinkID', SERVICE_INFORMATION_INCORRECT_SWIPE: 'IncorrectServiceTestID', SERVICE_INFORMATION_INCORRECT_BODY_LABEL_1: @@ -45,7 +44,7 @@ export async function verifyMilitaryInfo(militaryBranch: string) { await expect(element(by.text(militaryBranch))).toExist() await openMilitaryInformation() await expect(element(by.text(militaryBranch)).atIndex(0)).toExist() - await expect(element(by.text(MilitaryInformationE2eIdConstants.MILITARY_DATE_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_PERIOD_OF_SERVICE))).toExist() }) } diff --git a/VAMobile/e2e/tests/Navigation.e2e.ts b/VAMobile/e2e/tests/Navigation.e2e.ts index 7288c8f382b..54ccefc04f1 100644 --- a/VAMobile/e2e/tests/Navigation.e2e.ts +++ b/VAMobile/e2e/tests/Navigation.e2e.ts @@ -1,3 +1,12 @@ +/* +Description: +Detox script that runs dark mode, landscape, and font size accessibility tests. +The script can run either as a full suite or a subset: +* Full suite: The script will check every page outlined in navigationDic. A full suite run occurs either on the nightly dev build or when you check "run full e2e test" in the workflow options (if running manually). +* Subset: The script will only check the pages where the test name given in the array matches the test name typed into the "List tests to test in" workflow option. +When to update: +This script should be updated whenever a new feature/new page that has the bottom nav bar is added to the app. See https://department-of-veterans-affairs.github.io/va-mobile-app/docs/QA/QualityAssuranceProcess/Automation/AddingNewFeatures for more information. +*/ import { by, device, element, expect, waitFor } from 'detox' import { setTimeout } from 'timers/promises' @@ -37,18 +46,6 @@ const navigationDic = { ['Claims.e2e', ['Claims', 'Claims history', 'Active'], 'Your active claims, decision reviews, and appeals'], ['Claims.e2e', ['Claims', 'Claims history', 'Received July 20, 2021'], 'Claim details'], //['Claims.e2e', ['Claims', 'Claims history', 'Received July 20, 2021', 'Submit evidence'], 'Submit evidence'], - ['Claims.e2e', ['Claims', 'Claims history', 'Received January 01, 2021', 'Review file requests'], 'File requests'], - [ - 'Claims.e2e', - [ - 'Claims', - 'Claims history', - 'Received January 01, 2021', - 'Review file requests', - 'Dental disability - More information needed', - ], - 'Dental disability - More information needed', - ], ['Claims.e2e', ['Claims', 'Claims history', 'Received July 20, 2021', 'Files'], 'JESSE_GRAY_600246732_526.pdf'], [['Appeals.e2e', 'AppealsExpanded.e2e'], ['Claims', 'Claims history', 'Received July 17, 2008'], 'Appeal details'], [ @@ -96,8 +93,6 @@ const featureID = { 'Received July 20, 2021': 'claimsHistoryID', 'Received January 01, 2021': 'claimsHistoryID', 'Received July 17, 2008': 'claimsHistoryID', - 'Review file requests': 'claimStatusDetailsID', - 'Dental disability - More information needed': 'fileRequestPageTestID', 'Review letters': 'lettersPageID', Health: 'healthCategoryTestID', Appointments: 'appointmentsTestID', @@ -110,6 +105,8 @@ const featureID = { let scrollID let textResized +/*Constants for accessibility related command line options. +Any new accessibility related command line options should be added here. */ export const NavigationE2eConstants = { DARK_MODE_OPTIONS: device.getPlatform() === 'ios' ? 'xcrun simctl ui booted appearance dark' : 'adb shell "cmd uimode night yes"', @@ -127,6 +124,12 @@ export const NavigationE2eConstants = { DISPLAY_RESIZING_RESET: 'adb shell wm density reset', } +/* +Takes a screenshot for each accessibility option and compares it to a known screenshot (when done locally). +param key: Dictionary key from navigationDic. Corresponds to the sections given on the lower nav bar (Home, Health, Benefits, Payments) +param navigationDicValue: Dictionary value from navigationDic. Corresponds to the feature in the section that has a lower nav bar +param accessibilityFeatureType: String value that tells the test what accessability test to run or null value that verifies that a feature is in the right place navigation wise +*/ const accessibilityOption = async (key, navigationDicValue, accessibilityFeatureType: string | null) => { const navigationArray = navigationDicValue if (accessibilityFeatureType === 'landscape') { @@ -215,12 +218,7 @@ const navigateToPage = async (key, navigationDicValue) => { } else { const subNavigationArray = navigationArray[1] for (let k = 0; k < subNavigationArray.length - 1; k++) { - if (subNavigationArray[k] === 'Review file requests') { - await waitFor(element(by.id(CommonE2eIdConstants.ALERT_FILE_REQUEST_BUTTON_ID))) - .toBeVisible() - .whileElement(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)) - .scroll(100, 'up') - } else if (subNavigationArray[k] === 'Received July 17, 2008') { + if (subNavigationArray[k] === 'Received July 17, 2008') { await waitFor(element(by.text('Received July 17, 2008'))) .toBeVisible() .whileElement(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_SCROLL_ID)) @@ -247,12 +245,7 @@ const navigateToPage = async (key, navigationDicValue) => { await element(by.text(subNavigationArray[k])).tap() } - if (subNavigationArray.slice(-1)[0] === 'Review file requests') { - await waitFor(element(by.id(CommonE2eIdConstants.ALERT_FILE_REQUEST_BUTTON_ID))) - .toBeVisible() - .whileElement(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_SCREEN_ID)) - .scroll(100, 'up') - } else if (subNavigationArray.slice(-1)[0] === 'Get prescription details') { + if (subNavigationArray.slice(-1)[0] === 'Get prescription details') { await waitFor(element(by.label('CAPECITABINE 500MG TAB.'))) .toBeVisible() .whileElement(by.id(CommonE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)) diff --git a/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts b/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts index 7e527f70531..56e72f1d57f 100644 --- a/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts +++ b/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts @@ -80,7 +80,7 @@ export async function updateGenderIdentify(genderIdentityOption) { await expect(element(by.text(PersonalInfoConstants.PERSONAL_INFORMATION_TEXT))).toExist() await expect(element(by.text('Gender identity saved'))).toExist() await expect(element(by.text(genderIdentityOption))).toExist() - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() await element(by.id(PersonalInfoConstants.PERSONAL_INFO_SCROLL_ID)).scrollTo('bottom') await element(by.id(PersonalInfoConstants.GENDER_IDENTITY_ROW_ID)).tap() @@ -102,10 +102,10 @@ describe('Personal Info Screen', () => { await expect(element(by.text('Date of birth'))).toExist() await expect(element(by.text('January 01, 1950'))).toExist() - await expect(element(by.text('Preferred name'))).toExist() + await expect(element(by.text(PersonalInfoConstants.PREFERRED_NAME_HEADER_TEXT))).toExist() await expect(element(by.text('Sharing your preferred name is optional.'))).toExist() - await expect(element(by.text('Gender identity'))).toExist() + await expect(element(by.text(PersonalInfoConstants.GENDER_IDENTITY_HEADER_TEXT))).toExist() await expect(element(by.text('Woman'))).toExist() }) @@ -143,7 +143,7 @@ describe('Personal Info Screen', () => { await expect(element(by.text(PersonalInfoConstants.PREFERRED_NAME_HEADER_TEXT)).atIndex(0)).toExist() await element(by.id(PersonalInfoConstants.PREFERRED_NAME_ID)).replaceText('Kimberlee') await element(by.id(PersonalInfoConstants.PREFERRED_NAME_ID)).tapReturnKey() - await element(by.text('Save')).tap() + await element(by.text(CommonE2eIdConstants.SAVE_TEXT)).tap() await expect(element(by.text(PersonalInfoConstants.PERSONAL_INFORMATION_TEXT)).atIndex(0)).toExist() await expect(element(by.text('Preferred name saved'))).toExist() diff --git a/VAMobile/e2e/tests/Prescriptions.e2e.ts b/VAMobile/e2e/tests/Prescriptions.e2e.ts index 23eced83151..1dee3829c45 100644 --- a/VAMobile/e2e/tests/Prescriptions.e2e.ts +++ b/VAMobile/e2e/tests/Prescriptions.e2e.ts @@ -38,7 +38,6 @@ export const PrescriptionsE2eIdConstants = { "This list shows refill requests you've submitted. It also shows refills the V-A pharmacy is processing.", PRESCRIPTION_TRACKING_GET_TRACKING_ID: 'getPrescriptionTrackingTestID', PRESCRIPTION_REFILL_NAME_TEXT: 'AMLODIPINE BESYLATE 10MG TAB', - PRESCRIPTION_REFILL_DIALOG_YES_TEXT: device.getPlatform() === 'ios' ? 'Request Refill' : 'Request Refill ', PRESCRIPTION_REFILL_REQUEST_SUMMARY_TEXT: 'We got your refill requests', PRESCRIPTION_REFILL_REQUEST_SUMMARY_HEADER_TEXT: 'Refill request summary', PRESCRIPTION_REFILL_REQUEST_SUMMARY_NAME_TEXT: 'AMLODIPINE BESYLATE 10MG TAB', @@ -422,7 +421,7 @@ describe('Prescriptions Screen', () => { it('verify refill request summary screen information', async () => { await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REQUEST_REFILL_ID)).tap() - await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap() await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_REQUEST_SUMMARY_TEXT))).toExist() await expect( element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_REQUEST_SUMMARY_HEADER_TEXT)), @@ -459,7 +458,7 @@ describe('Prescriptions Screen', () => { .scroll(500, 'down') await element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_DETAILS_LABEL)).atIndex(0).tap() await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REQUEST_REFILL_ID)).tap() - await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap() await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_REQUEST_SUMMARY_TEXT))).toExist() await expect( element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_REQUEST_SUMMARY_HEADER_TEXT)), diff --git a/VAMobile/e2e/tests/ProfileScreen.e2e.ts b/VAMobile/e2e/tests/ProfileScreen.e2e.ts index e63159af5e3..6fa0eef1c6b 100644 --- a/VAMobile/e2e/tests/ProfileScreen.e2e.ts +++ b/VAMobile/e2e/tests/ProfileScreen.e2e.ts @@ -5,7 +5,6 @@ import { CommonE2eIdConstants, loginToDemoMode, openProfile } from './utils' export const ProfileE2eIdConstants = { PROFILE_TEXT: 'Profile', BANNER_NAME_ID: 'Kimberly Washington', - BANNER_BRANCH_ID: 'United States Coast Guard', } beforeAll(async () => { @@ -27,6 +26,6 @@ describe('Profile Screen', () => { it('should show profile banner elements', async () => { await expect(element(by.text(ProfileE2eIdConstants.BANNER_NAME_ID))).toExist() - await expect(element(by.text(ProfileE2eIdConstants.BANNER_BRANCH_ID))).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_BRANCH_COAST_GUARD))).toExist() }) }) diff --git a/VAMobile/e2e/tests/PushNotifications.e2e.ts b/VAMobile/e2e/tests/PushNotifications.e2e.ts index ec3984364f6..54ad8fb9127 100644 --- a/VAMobile/e2e/tests/PushNotifications.e2e.ts +++ b/VAMobile/e2e/tests/PushNotifications.e2e.ts @@ -3,7 +3,6 @@ import { by, device, element, expect, waitFor } from 'detox' import { backButton, loginToDemoMode } from './utils' const PushNotificationsConstants = { - HEALTH_SCREEN_TITLE: 'Health', MESSAGE_COMPOSE_BUTTON_TEXT: 'Start new message', REVIEW_MESSAGE_SCREEN_TITLE: 'Review message', } diff --git a/VAMobile/e2e/tests/SignIn.e2e.ts b/VAMobile/e2e/tests/SignIn.e2e.ts index 30743d6eaee..c28c8449a77 100644 --- a/VAMobile/e2e/tests/SignIn.e2e.ts +++ b/VAMobile/e2e/tests/SignIn.e2e.ts @@ -4,14 +4,11 @@ import { setTimeout } from 'timers/promises' import { CommonE2eIdConstants } from './utils' export const SignE2eIdConstants = { - LOGIN_PAGE_ID: 'Login-page', LOA_P1_TEXT: - 'Before we give you access to your VA claim and health care information, we need to make sure you’re you. This helps us protect you from fraud and identity theft.', - LOA_P2_TEXT: 'If you haven’t yet verified your identity, we’ll help you complete the process when you sign in.', - LOA_GATE_EXPAND_MSG_ID: 'loaGateExpandMsgID', - LOA_GATE_READ_MORE_P1: - 'We’ll verify your identity through a secure process from ID.me or Login.gov. This trusted partner provides the strongest identity verification system available.', - LOA_GATE_READ_MORE_P2: 'To complete the process on your smartphone, you’ll need these items:', + 'You’ll need to sign in with an identity-verified account through one of our account providers. Identity verification helps us protect all Veterans’ information and prevent scammers from stealing your benefits.', + LOA_P2_TEXT: + 'Don’t yet have a verified account? Continue to the sign-in page. Follow the instructions to create a Login.gov or ID.me account. Then come back here and sign in. We’ll help you verify your identity for your account.', + LOA_P3_TEXT: 'Not sure if your account is verified? Sign in now. We’ll tell you if you need to verify.', CONTINUE_SIGN_IN_BTN_ID: 'Continue to sign in', } @@ -34,7 +31,7 @@ describe('Sign In', () => { await expect(element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID))).toExist() await expect(element(by.text(SignE2eIdConstants.LOA_P1_TEXT))).toExist() await expect(element(by.text(SignE2eIdConstants.LOA_P2_TEXT))).toExist() - await expect(element(by.id(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_ID))).toExist() + await expect(element(by.text(SignE2eIdConstants.LOA_P3_TEXT))).toExist() await expect(element(by.id(SignE2eIdConstants.CONTINUE_SIGN_IN_BTN_ID))).toExist() }) @@ -43,12 +40,6 @@ describe('Sign In', () => { await element(by.id(CommonE2eIdConstants.SIGN_IN_BTN_ID)).tap() await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID)).tap() await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BACK_ID)).tap() - await element(by.id(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_ID)).tap() - await expect(element(by.text(SignE2eIdConstants.LOA_GATE_READ_MORE_P1))).toExist() - await expect(element(by.text(SignE2eIdConstants.LOA_GATE_READ_MORE_P2))).toExist() - await element(by.id(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_ID)).tap() - await expect(element(by.text(SignE2eIdConstants.LOA_GATE_READ_MORE_P1))).not.toExist() - await expect(element(by.text(SignE2eIdConstants.LOA_GATE_READ_MORE_P2))).not.toExist() await element(by.id(SignE2eIdConstants.CONTINUE_SIGN_IN_BTN_ID)).tap() await setTimeout(7000) await device.takeScreenshot('VALoginWebview') diff --git a/VAMobile/e2e/tests/VaccineRecords.e2e.ts b/VAMobile/e2e/tests/VaccineRecords.e2e.ts index fb1d2a7cf4f..887010569cd 100644 --- a/VAMobile/e2e/tests/VaccineRecords.e2e.ts +++ b/VAMobile/e2e/tests/VaccineRecords.e2e.ts @@ -4,9 +4,10 @@ Detox script that follows the vaccines - view list of all immunization records a When to update: This script should be updated whenever new things are added/changed in vaccines or if anything is changed in src/store/api/demo/mocks/vaccine.json. */ +import { combineReducers } from '@reduxjs/toolkit' import { by, element, expect } from 'detox' -import { checkImages, loginToDemoMode, openHealth, openVaccineRecords } from './utils' +import { CommonE2eIdConstants, checkImages, loginToDemoMode, openHealth, openVaccineRecords } from './utils' export const VaccinesE2eIdConstants = { VACCINE_1_ID: 'COVID-19 vaccine January 14, 2021', @@ -43,7 +44,7 @@ describe('Vaccine Records Screen', () => { await expect(element(by.id('Type And Dosage COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose'))).toExist() await expect(element(by.id('Manufacturer Moderna US, Inc.'))).toExist() await expect(element(by.id('Series status None noted'))) - await expect(element(by.text('Cheyenne VA Medical Center'))).toExist() + await expect(element(by.text(CommonE2eIdConstants.CHEYENNE_FACILITY_TEXT))).toExist() await expect(element(by.text('2360 East Pershing Boulevard'))).toExist() await expect(element(by.text('Cheyenne, WY 82001-5356'))).toExist() await expect(element(by.text('Reaction'))).toExist() diff --git a/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts b/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts index d8356dda8b1..6339b541a77 100644 --- a/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts +++ b/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts @@ -20,11 +20,8 @@ import { export const VeteranStatusCardConstants = { VETERAN_STATUS_ID: 'veteranStatusButtonID', - VETERAN_STATUS_NAME_TEXT: 'Kimberly Washington', - VETERAN_STATUS_MILITARY_BRANCH_TEXT: 'United States Coast Guard', VETERAN_STATUS_DISABILITY_RATING_TEXT: '100% service connected', VETERAN_STATUS_PERIOD_OF_SERVICE_BRANCH_1_TEXT: 'United States Army', - VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_1_TEXT: 'July 13, 1970 – August 31, 1998', VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_2_TEXT: 'September 01, 1998 – January 01, 2000', VETERAN_STATUS_DISCLAIMER_TEXT: "You can use this Veteran status to prove you served in the United States Uniformed Services. This status doesn't entitle you to any VA benefits.", @@ -51,6 +48,7 @@ export async function validateVeteranStatusDesign() { await expect(element(by.id('veteranStatusBranchTestID'))).toExist() await expect(element(by.id('veteranStatusDisabilityRatingTestID'))).toExist() await expect(element(by.id('veteranStatusMilitaryServiceTestID')).atIndex(0)).toExist() + await expect(element(by.id('veteranStatusDODTestID'))).toExist() await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DISCLAIMER_TEXT))).toExist() await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DOB_DISABILITY_ERROR_PHONE_TEXT))).toExist() await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist() @@ -77,7 +75,7 @@ export async function tapPhoneAndTTYLinks() { await element(by.id('veteranStatusTestID')).scrollTo('bottom') await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0).tap() try { - await element(by.text('Dismiss')).tap() + await element(by.text(CommonE2eIdConstants.DISMISS_TEXT)).tap() await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0).tap() } catch (e) {} await setTimeout(2000) @@ -110,7 +108,7 @@ export async function verifyMilitaryInfo(militaryBranch) { await element(by.text('Home')).tap() await waitFor(element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID))) .toBeVisible() - .whileElement(by.id('homeScreenID')) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap() await expect(element(by.text(militaryBranch)).atIndex(1)).toExist() @@ -129,7 +127,7 @@ describe('Veteran Status Card', () => { it('should match design in the home screen', async () => { await waitFor(element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID))) .toBeVisible() - .whileElement(by.id('homeScreenID')) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap() await validateVeteranStatusDesign() @@ -149,15 +147,15 @@ describe('Veteran Status Card', () => { it('verify the period of service matches app', async () => { await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_BRANCH_1_TEXT))).toExist() - await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_1_TEXT))).toExist() - await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_MILITARY_BRANCH_TEXT)).atIndex(1)).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_PERIOD_OF_SERVICE))).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_BRANCH_COAST_GUARD)).atIndex(1)).toExist() await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_2_TEXT))).toExist() await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap() await setTimeout(2000) await openMilitaryInformation() await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_BRANCH_1_TEXT))).toExist() - await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_1_TEXT))).toExist() - await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_MILITARY_BRANCH_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_PERIOD_OF_SERVICE))).toExist() + await expect(element(by.text(CommonE2eIdConstants.MILITARY_BRANCH_COAST_GUARD))).toExist() await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_2_TEXT))).toExist() await element(by.id(VeteranStatusCardConstants.BACK_TO_PROFILE_ID)).tap() }) @@ -168,7 +166,7 @@ describe('Veteran Status Card', () => { await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap() await openBenefits() await openDisabilityRating() - await expect(element(by.text('100%')).atIndex(1)).toExist() + await expect(element(by.text(CommonE2eIdConstants.DISABILITY_RATING_PERCENT_TEXT)).atIndex(1)).toExist() }) verifyMilitaryInfo('United States Coast Guard') diff --git a/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts b/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts index 6edbc1c830a..85d33f4ebc0 100644 --- a/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts +++ b/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts @@ -10,17 +10,11 @@ import { setTimeout } from 'timers/promises' import { CommonE2eIdConstants, loginToDemoMode, openVeteransCrisisLine } from './utils' export const VCLConstants = { - HEADING_TEXT: 'Veterans Crisis Line', SUBHEADING_TEXT: 'We’re here anytime, day or night – 24/7', MESSAGE_TEXT: "If you're a Veteran in crisis or concerned about one, connect with our caring, qualified responders for confidential help. Many of them are Veterans themselves.", - PHONE_LINK_ID: 'veteransCrisisLineCallID', - TEXT_MESSAGE_LINK_ID: 'veteransCrisisLineTextNumberTestID', - CHAT_LINK_ID: 'veteransCrisisLineConfidentialChatTestID', - TTY_LINK_ID: 'veteransCrisisLineHearingLossNumberTestID', MORE_RESOURCES_TEXT: 'Get more resources', VCL_SITE_LINK_ID: 'veteransCrisisLineGetMoreResourcesTestID', - BACK_ID: 'veteranCrisisLineBackID', } const tapAndTakeScreenshot = async (text: string, screenshotName: string) => { @@ -39,7 +33,7 @@ beforeAll(async () => { describe('Veterans Crisis Line', () => { it('should match design', async () => { - await expect(element(by.text(VCLConstants.HEADING_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_HEADING_TEXT))).toExist() await expect(element(by.text(VCLConstants.SUBHEADING_TEXT))).toExist() await expect(element(by.text(VCLConstants.MESSAGE_TEXT))).toExist() await expect(element(by.text(VCLConstants.MORE_RESOURCES_TEXT))).toExist() @@ -47,19 +41,19 @@ describe('Veterans Crisis Line', () => { if (device.getPlatform() === 'android') { it('should open phone link', async () => { - await tapAndTakeScreenshot(VCLConstants.PHONE_LINK_ID, 'CrisisLinePhone') + await tapAndTakeScreenshot(CommonE2eIdConstants.VETERANS_CRISIS_LINE_CALL_ID, 'CrisisLinePhone') }) it('should open TTY link', async () => { - await tapAndTakeScreenshot(VCLConstants.TTY_LINK_ID, 'CrisisLineTTY') + await tapAndTakeScreenshot(CommonE2eIdConstants.VETERANS_CRISIS_LINE_TTY_ID, 'CrisisLineTTY') }) } it('should open text message link', async () => { - await tapAndTakeScreenshot(VCLConstants.TEXT_MESSAGE_LINK_ID, 'CrisisLineTextMessage') + await tapAndTakeScreenshot(CommonE2eIdConstants.VETERANS_CRISIS_LINE_TEXT_ID, 'CrisisLineTextMessage') }) it('should open chat link', async () => { - await element(by.id(VCLConstants.CHAT_LINK_ID)).tap() + await element(by.id(CommonE2eIdConstants.VETERANS_CRISIS_LINE_CHAT_ID)).tap() await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap() await setTimeout(5000) await device.takeScreenshot('CrisisLineChat') @@ -75,7 +69,7 @@ describe('Veterans Crisis Line', () => { }) it('should close panel', async () => { - await element(by.id(VCLConstants.BACK_ID)).tap() + await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BACK_ID)).tap() await expect(element(by.text(CommonE2eIdConstants.HOME_ACTIVITY_HEADER_TEXT))).toExist() }) }) diff --git a/VAMobile/e2e/tests/utils.ts b/VAMobile/e2e/tests/utils.ts index 294f9169987..564ed270373 100644 --- a/VAMobile/e2e/tests/utils.ts +++ b/VAMobile/e2e/tests/utils.ts @@ -1,3 +1,9 @@ +/* +Description: +Detox script for functions/constants that effect multiple other scripts. +When to update: +New functions/constants should be added when anything is created that might effect multiple scripts. +*/ import { expect as jestExpect } from '@jest/globals' import { by, device, element, expect, waitFor } from 'detox' import { setTimeout } from 'timers/promises' @@ -23,86 +29,127 @@ const mockNotification = { } export const CommonE2eIdConstants = { - VA_LOGO_ICON_ID: 'va-icon', - DEMO_MODE_INPUT_ID: 'demo-mode-password', - DEMO_BTN_ID: 'demo-btn', - SIGN_IN_BTN_ID: 'Sign in', - TURN_ON_NOTIFICATIONS_TEXT: 'Turn on notifications', - VETERAN_CRISIS_LINE_BTN_TEXT: 'Talk to the Veterans Crisis Line now', - VETERAN_CRISIS_LINE_BTN_ID: 'veteransCrisisLineID', - VETERAN_CRISIS_LINE_BACK_ID: 'veteranCrisisLineBackID', - HEALTH_TAB_BUTTON_TEXT: 'Health', - PAYMENTS_TAB_BUTTON_TEXT: 'Payments', - BENEFITS_TAB_BUTTON_TEXT: 'Benefits', - HOME_TAB_BUTTON_TEXT: 'Home', - SETTINGS_ROW_TEXT: 'Settings', + //device-specific + OK_PLATFORM_SPECIFIC_TEXT: device.getPlatform() === 'ios' ? 'Ok' : 'OK', + CANCEL_PLATFORM_SPECIFIC_TEXT: device.getPlatform() === 'ios' ? 'Cancel' : 'Cancel ', + CAMERA_TEXT: device.getPlatform() === 'ios' ? 'Camera' : 'Camera ', + PHOTO_GALLERY_TEXT: device.getPlatform() === 'ios' ? 'Photo Gallery' : 'Photo gallery ', + FILE_FOLDER_TEXT: device.getPlatform() === 'ios' ? 'File Folder' : 'File folder ', + CANCEL_DELETE_CHANGES_BUTTON_TEXT: device.getPlatform() === 'ios' ? 'Delete Changes' : 'Delete Changes ', + CANCEL_KEEP_EDITING_TEXT: device.getPlatform() === 'ios' ? 'Keep Editing' : 'Keep Editing ', + //universal + SAVE_TEXT: 'Save', + ENABLED_TEXT: 'Enabled', + PREVIOUS_PAGE_ID: 'previous-page', + NEXT_PAGE_ID: 'next-page', BACK_BTN_LABEL: 'Back', LEAVING_APP_POPUP_TEXT: 'Leave the mobile app?', LEAVING_APP_CANCEL_TEXT: 'Go back', LEAVING_APP_LEAVE_TEXT: 'Leave', CANCEL_UNIVERSAL_TEXT: 'Cancel', OK_UNIVERSAL_TEXT: 'OK', - CLAIMS_HISTORY_BUTTON_ID: 'toClaimsHistoryID', - CANCEL_PLATFORM_SPECIFIC_TEXT: device.getPlatform() === 'ios' ? 'Cancel' : 'Cancel ', - RESET_INAPP_REVIEW_BUTTON_TEXT: 'Reset in-app review actions', - REMOTE_CONFIG_TEST_ID: 'remoteConfigTestID', - REMOTE_CONFIG_BUTTON_TEXT: 'Remote Config', - APPLY_OVERRIDES_BUTTON_TEXT: 'Apply Overrides', - OK_PLATFORM_SPECIFIC_TEXT: device.getPlatform() === 'ios' ? 'Ok' : 'OK', - UPCOMING_APPT_BUTTON_TEXT: 'Upcoming', - START_NEW_MESSAGE_BUTTON_ID: 'startNewMessageButtonTestID', - PRESCRIPTION_REFILL_BUTTON_TEXT: 'Start refill request', - PRESCRIPTION_REFILL_BUTTON_ID: 'refillRequestTestID', - HOME_ACTIVITY_HEADER_TEXT: 'Activity', - IN_APP_REVIEW_TOGGLE_TEXT: 'inAppReview', - CONTACT_INFO_SAVE_ID: 'contactInfoSaveTestID', - CONTACT_INFO_SUGGESTED_ADDRESS_ID: 'suggestedAddressTestID', - CONTACT_INFO_USE_THIS_ADDRESS_ID: 'Use this address', - CONTACT_INFO_STREET_ADDRESS_LINE_2_ID: 'streetAddressLine2TestID', + DISMISS_TEXT: 'Dismiss', CALL_VA_PHONE_NUMBER_ID: 'CallVATestID', CALL_VA_TTY_PHONE_NUMBER_ID: 'CallTTYTestID', - APPOINTMENTS_SCROLL_ID: 'appointmentsTestID', GO_TO_VA_GOV_LINK_ID: 'goToVAGovID', - CLAIMS_HISTORY_SCROLL_ID: 'claimsHistoryID', - NEXT_PAGE_ID: 'next-page', + VETERAN_CRISIS_LINE_HEADING_TEXT: 'Veterans Crisis Line', + VETERAN_CRISIS_LINE_BTN_TEXT: 'Talk to the Veterans Crisis Line now', + VETERAN_CRISIS_LINE_BTN_ID: 'veteransCrisisLineID', + VETERAN_CRISIS_LINE_BACK_ID: 'veteranCrisisLineBackID', VETERANS_CRISIS_LINE_CALL_ID: 'veteransCrisisLineCallID', VETERANS_CRISIS_LINE_TTY_ID: 'veteransCrisisLineHearingLossNumberTestID', VETERANS_CRISIS_LINE_TEXT_ID: 'veteransCrisisLineTextNumberTestID', VETERANS_CRISIS_LINE_CHAT_ID: 'veteransCrisisLineConfidentialChatTestID', - PREVIOUS_PAGE_ID: 'previous-page', - CLAIMS_DETAILS_BACK_ID: 'claimsDetailsBackTestID', - CLAIMS_HISTORY_BACK_ID: 'claimsHistoryBackTestID', - CLAIMS_HISTORY_CLOSED_TAB_ID: 'claimsHistoryClosedID', + MILITARY_BRANCH_COAST_GUARD: 'United States Coast Guard', + MILITARY_PERIOD_OF_SERVICE: 'July 13, 1970 – August 31, 1998', + //login, home, nav bar + VA_LOGO_ICON_ID: 'va-icon', + DEMO_MODE_INPUT_ID: 'demo-mode-password', + DEMO_BTN_ID: 'demo-btn', + SIGN_IN_BTN_ID: 'Sign in', SKIP_BACK_BUTTON_ID: 'onboardingSkipBackButtonID', + TURN_ON_NOTIFICATIONS_TEXT: 'Turn on notifications', + HOME_ACTIVITY_HEADER_TEXT: 'Activity', + HEALTH_TAB_BUTTON_TEXT: 'Health', + PAYMENTS_TAB_BUTTON_TEXT: 'Payments', + BENEFITS_TAB_BUTTON_TEXT: 'Benefits', + HOME_TAB_BUTTON_TEXT: 'Home', HEALTH_TAB_BUTTON_ID: 'Health', PAYMENTS_TAB_BUTTON_ID: 'Payments', BENEFITS_TAB_BUTTON_ID: 'Benefits', HOME_TAB_BUTTON_ID: 'Home', - AF_APP_UPDATE_BUTTON_TOGGLE_ID: 'remoteConfigAppUpdateTestID', - AF_ENABLE_TOGGLE_ID: 'remoteConfigEnableTestID', + PROFILE_HEADER_BUTTON_ID: 'toProfileScreenID', + HOME_SCREEN_SCROLL_ID: 'homeScreenID', + DISABILITY_RATING_PERCENT_TEXT: '100%', + //health + UPCOMING_APPT_BUTTON_TEXT: 'Upcoming', + APPOINTMENTS_SCROLL_ID: 'appointmentsTestID', + APPOINTMENTS_BUTTON_ID: 'toAppointmentsID', + ADD_TO_CALENDAR_ID: 'addToCalendarTestID', + GET_DIRECTIONS_ID: 'directionsTestID', + DATE_RANGE_INITIAL_TEXT: 'Past 3 months', + START_NEW_MESSAGE_BUTTON_ID: 'startNewMessageButtonTestID', + MESSAGES_INBOX_BUTTON_ID: 'toMessageInboxID', + VIEW_MESSAGE_ID: 'viewMessageTestID', + PRESCRIPTION_REFILL_BUTTON_TEXT: 'Start refill request', + PRESCRIPTION_REFILL_BUTTON_ID: 'refillRequestTestID', + PRESCRIPTION_HISTORY_SCROLL_ID: 'PrescriptionHistory', + PRESCRIPTIONS_BUTTON_ID: 'toPrescriptionsID', + PRESCRIPTION_REFILL_DIALOG_YES_TEXT: device.getPlatform() === 'ios' ? 'Request Refill' : 'Request Refill ', + VACCINES_BUTTON_ID: 'toVaccineListID', + CHEYENNE_FACILITY_TEXT: 'Cheyenne VA Medical Center', + //benefits + CLAIMS_HISTORY_BUTTON_ID: 'toClaimsHistoryID', + CLAIMS_HISTORY_SCROLL_ID: 'claimsHistoryID', + CLAIMS_DETAILS_BACK_ID: 'claimsDetailsBackTestID', + CLAIMS_HISTORY_BACK_ID: 'claimsHistoryBackTestID', + CLAIMS_HISTORY_CLOSED_TAB_ID: 'claimsHistoryClosedID', CLAIMS_DETAILS_SCREEN_ID: 'ClaimDetailsScreen', ALERT_FILE_REQUEST_BUTTON_ID: 'Review file requests', - PRESCRIPTION_HISTORY_SCROLL_ID: 'PrescriptionHistory', - PERSONAL_INFO_BUTTON_ID: 'toPersonalInfoID', - CONTACT_INFO_BUTTON_ID: 'toContactInfoID', - MILITARY_HISTORY_BUTTON_ID: 'toMilitaryHistoryID', - SETTINGS_BUTTON_ID: 'toSettingsID', - PROFILE_SCROLL_ID: 'profileID', CLAIMS_LANDING_BUTTON_ID: 'toClaimsLandingID', + APPEALS_DETAILS_ID: 'appealsDetailsTestID', + CLOSED_CLAIM_DECISION_LETTER_ID: + 'Compensation Decision letter ready Received January 01, 2021 Step 5 of 5: Complete Moved to this step on April 09, 2021', LETTERS_LANDING_BUTTON_ID: 'toLettersLandingID', DISABILITY_RATING_BUTTON_ID: 'toDisabilityRatingID', + //payments PAYMENT_HISTORY_BUTTON_ID: 'toPaymentHistoryID', DIRECT_DEPOSIT_BUTTON_ID: 'toDirectDepositID', - APPOINTMENTS_BUTTON_ID: 'toAppointmentsID', - MESSAGES_INBOX_BUTTON_ID: 'toMessageInboxID', - PRESCRIPTIONS_BUTTON_ID: 'toPrescriptionsID', - VACCINES_BUTTON_ID: 'toVaccineListID', + //profile, settings + PROFILE_SCROLL_ID: 'profileID', + PERSONAL_INFO_BUTTON_ID: 'toPersonalInfoID', + CONTACT_INFO_BUTTON_ID: 'toContactInfoID', + MILITARY_HISTORY_BUTTON_ID: 'toMilitaryHistoryID', + SETTINGS_BUTTON_ID: 'toSettingsID', + SETTINGS_ROW_TEXT: 'Settings', + CONTACT_INFO_SCREEN_ID: 'ContactInfoTestID', + CONTACT_INFO_SAVE_ID: 'contactInfoSaveTestID', + CONTACT_INFO_SUGGESTED_ADDRESS_ID: 'suggestedAddressTestID', + CONTACT_INFO_USE_THIS_ADDRESS_ID: 'Use this address', + CONTACT_INFO_STREET_ADDRESS_LINE_2_ID: 'streetAddressLine2TestID', DEVELOPER_SCREEN_BUTTON_ID: 'toDeveloperScreenID', - PROFILE_HEADER_BUTTON_ID: 'toProfileScreenID', -} - -/** Log the automation into demo mode - * */ + DEVELOPER_SCREEN_SCROLL_ID: 'developerScreenTestID', + RESET_INAPP_REVIEW_BUTTON_TEXT: 'Reset in-app review actions', + REMOTE_CONFIG_TEST_ID: 'remoteConfigTestID', + REMOTE_CONFIG_BUTTON_TEXT: 'Remote Config', + APPLY_OVERRIDES_BUTTON_TEXT: 'Apply Overrides', + IN_APP_REVIEW_TOGGLE_TEXT: 'inAppReview', + AF_APP_UPDATE_BUTTON_TOGGLE_ID: 'remoteConfigAppUpdateTestID', + AF_ENABLE_TOGGLE_ID: 'remoteConfigEnableTestID', + AF_UPDATE_NOW_BUTTON_TEXT: 'Update now', + AF_ERROR_MSG_TITLE_INPUT_ID: 'AFErrorMsgTitleTestID', + AF_ERROR_MSG_TITLE_ENTERED_TEXT: 'AF Heading Test', + AF_ERROR_MSG_BODY_INPUT_ID: 'AFErrorMsgBodyTestID', + AF_BODY_ENTERED_TEXT: 'AF Body Test', + AF_ERROR_MSG_PHONE_ID: 'AFErrorPhoneNumberTestID', + AF_TYPE_INPUT_ID: 'AFTypeTestID', + AF_USE_CASE_TWO_ID: 'AFUseCase2TestID', +} + +/** Logs into demo mode. +* @param skipOnboarding: Boolean value that defaults to true. Set this to false if you want the detox test to view the onboarding carasoul on login +* @param pushNotifications: Boolean value that tells the detox tests whether to turn on/off push notifications +* */ export async function loginToDemoMode(skipOnboarding = true, pushNotifications?: boolean) { try { await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID))) @@ -125,6 +172,10 @@ export async function loginToDemoMode(skipOnboarding = true, pushNotifications?: .toExist() .withTimeout(60000) } + await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID))) + .toBeVisible() + .whileElement(by.id('Login-page')) + .scroll(100, 'down') await element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)).multiTap(7) if (DEMO_PASSWORD !== undefined) { @@ -134,6 +185,10 @@ export async function loginToDemoMode(skipOnboarding = true, pushNotifications?: await element(by.id(CommonE2eIdConstants.DEMO_MODE_INPUT_ID)).tapReturnKey() await element(by.id(CommonE2eIdConstants.DEMO_BTN_ID)).multiTap(2) + await waitFor(element(by.id(CommonE2eIdConstants.SIGN_IN_BTN_ID))) + .toBeVisible() + .whileElement(by.id('Login-page')) + .scroll(100, 'down') await element(by.id(CommonE2eIdConstants.SIGN_IN_BTN_ID)).tap() if (skipOnboarding === true) { @@ -160,7 +215,6 @@ export async function loginToDemoMode(skipOnboarding = true, pushNotifications?: * @param waitForElement - boolean to wait for an element * @param timeOut - time to wait for the element * */ - export async function checkIfElementIsPresent( matchString: string, findbyText = false, @@ -191,7 +245,7 @@ export async function checkIfElementIsPresent( } } -/* Scroll down inside container until specified text is found, then tap the text +/** Scroll down inside container until specified text is found, then tap the text * * @param text - string of the text to match * @param containerID - testID of the container @@ -204,7 +258,7 @@ export async function scrollToThenTap(text: string, containerID: string) { await element(by.text(text)).tap() } -/* Scroll down inside container until specified testID is found, then tap the testID +/** Scroll down inside container until specified testID is found, then tap the testID * * @param scrollToID - testID of the item to scroll to * @param containerID - testID of the container @@ -217,7 +271,7 @@ export async function scrollToIDThenTap(scrollToID: string, containerID: string) await element(by.id(scrollToID)).tap() } -/*This function will open, check for, and dismiss the leaving app popup from a specified launching point +/** This function will open, check for, and dismiss the leaving app popup from a specified launching point * * @param matchString - string of the text or id to match * @param findbyText - boolean to search by testID or Text @@ -405,6 +459,11 @@ export async function backButton(backButtonName: string) { } } +/** Enables the availibility banner. +* @param AFFeature: Name of the AF waygate. +* @param AFUseCase: Name of the AF type. +* @param AFAppUpdate: Boolean value that tells the script whether to enable the update now button or not +* */ export async function enableAF(AFFeature, AFUseCase, AFAppUpdate = false) { await device.launchApp({ newInstance: true, permissions: { notifications: 'YES' } }) await loginToDemoMode() @@ -413,19 +472,19 @@ export async function enableAF(AFFeature, AFUseCase, AFAppUpdate = false) { await openDeveloperScreen() await waitFor(element(by.text(CommonE2eIdConstants.REMOTE_CONFIG_BUTTON_TEXT))) .toBeVisible() - .whileElement(by.id('developerScreenTestID')) + .whileElement(by.id(CommonE2eIdConstants.DEVELOPER_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(CommonE2eIdConstants.REMOTE_CONFIG_BUTTON_TEXT)).tap() if (AFUseCase === 'DenyAccess') { await waitFor(element(by.text(CommonE2eIdConstants.IN_APP_REVIEW_TOGGLE_TEXT))) .toBeVisible() - .whileElement(by.id('remoteConfigTestID')) + .whileElement(by.id(CommonE2eIdConstants.REMOTE_CONFIG_TEST_ID)) .scroll(600, 'down') await element(by.text(CommonE2eIdConstants.IN_APP_REVIEW_TOGGLE_TEXT)).tap() } await waitFor(element(by.text(AFFeature))) .toBeVisible() - .whileElement(by.id('remoteConfigTestID')) + .whileElement(by.id(CommonE2eIdConstants.REMOTE_CONFIG_TEST_ID)) .scroll(600, 'down') await element(by.text(AFFeature)).tap() @@ -458,21 +517,21 @@ export async function enableAF(AFFeature, AFUseCase, AFAppUpdate = false) { } } } - await element(by.id('AFTypeTestID')).replaceText(AFUseCase) - await element(by.id('AFTypeTestID')).tapReturnKey() - await element(by.id('AFErrorMsgTitleTestID')).replaceText('AF Heading Test') - await element(by.id('AFErrorMsgTitleTestID')).tapReturnKey() - await element(by.id('AFErrorMsgBodyTestID')).replaceText('AF Body Test') - await element(by.id('AFErrorMsgBodyTestID')).tapReturnKey() + await element(by.id(CommonE2eIdConstants.AF_TYPE_INPUT_ID)).replaceText(AFUseCase) + await element(by.id(CommonE2eIdConstants.AF_TYPE_INPUT_ID)).tapReturnKey() + await element(by.id(CommonE2eIdConstants.AF_ERROR_MSG_TITLE_INPUT_ID)).replaceText('AF Heading Test') + await element(by.id(CommonE2eIdConstants.AF_ERROR_MSG_TITLE_INPUT_ID)).tapReturnKey() + await element(by.id(CommonE2eIdConstants.AF_ERROR_MSG_BODY_INPUT_ID)).replaceText('AF Body Test') + await element(by.id(CommonE2eIdConstants.AF_ERROR_MSG_BODY_INPUT_ID)).tapReturnKey() await setTimeout(3000) - await element(by.id('AFErrorPhoneNumberTestID')).replaceText('8006982411') - await element(by.id('AFErrorPhoneNumberTestID')).tapReturnKey() + await element(by.id(CommonE2eIdConstants.AF_ERROR_MSG_PHONE_ID)).replaceText('8006982411') + await element(by.id(CommonE2eIdConstants.AF_ERROR_MSG_PHONE_ID)).tapReturnKey() - await element(by.text('Save')).tap() + await element(by.text(CommonE2eIdConstants.SAVE_TEXT)).tap() if (AFUseCase === 'DenyAccess') { await waitFor(element(by.text(CommonE2eIdConstants.APPLY_OVERRIDES_BUTTON_TEXT))) .toBeVisible() - .whileElement(by.id('remoteConfigTestID')) + .whileElement(by.id(CommonE2eIdConstants.REMOTE_CONFIG_TEST_ID)) .scroll(600, 'up') await element(by.text(CommonE2eIdConstants.APPLY_OVERRIDES_BUTTON_TEXT)).tap() if (AFFeature !== 'WG_Login' && AFFeature !== 'WG_VeteransCrisisLine') { @@ -483,9 +542,15 @@ export async function enableAF(AFFeature, AFUseCase, AFAppUpdate = false) { } } +/** Disables the availibility banner. +* @param featureNavigationArray: Array that tells the AF script how to navigate to the feature +* @param AFFeature: Name of the AF waygate. +* @param AFUseCaseName: Name of the AF type. +* @param AFAppUpdate: Boolean value that tells the script whether to enable the update now button or not +* */ export async function disableAF(featureNavigationArray, AFFeature, AFFeatureName, AFUseCaseName) { if (AFUseCaseName === 'AllowFunction') { - await element(by.id('Home')).tap() + await element(by.id(CommonE2eIdConstants.HOME_TAB_BUTTON_ID)).tap() } else { await device.launchApp({ newInstance: true, permissions: { notifications: 'YES' } }) await loginToDemoMode() @@ -495,7 +560,7 @@ export async function disableAF(featureNavigationArray, AFFeature, AFFeatureName await openDeveloperScreen() await waitFor(element(by.text(CommonE2eIdConstants.REMOTE_CONFIG_BUTTON_TEXT))) .toBeVisible() - .whileElement(by.id('developerScreenTestID')) + .whileElement(by.id(CommonE2eIdConstants.DEVELOPER_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(CommonE2eIdConstants.REMOTE_CONFIG_BUTTON_TEXT)).tap() await waitFor(element(by.text(AFFeature))) @@ -503,20 +568,22 @@ export async function disableAF(featureNavigationArray, AFFeature, AFFeatureName .whileElement(by.id(CommonE2eIdConstants.REMOTE_CONFIG_TEST_ID)) .scroll(600, 'down') await element(by.text(AFFeature)).tap() - await element(by.text('Enabled')).tap() - await element(by.text('Save')).tap() + await element(by.text(CommonE2eIdConstants.ENABLED_TEXT)).tap() + await element(by.text(CommonE2eIdConstants.SAVE_TEXT)).tap() await element(by.id(CommonE2eIdConstants.HOME_TAB_BUTTON_ID)).tap() if (featureNavigationArray !== undefined) { await navigateToFeature(featureNavigationArray) - await expect(element(by.text('AF Heading Test'))).not.toExist() - await expect(element(by.text('AF Body Test'))).not.toExist() + await expect(element(by.text(CommonE2eIdConstants.AF_ERROR_MSG_TITLE_ENTERED_TEXT))).not.toExist() + await expect(element(by.text(CommonE2eIdConstants.AF_BODY_ENTERED_TEXT))).not.toExist() } await device.uninstallApp() await device.installApp() } +/** Function that allows the AF script to navigate to a certain feature +* */ const navigateToFeature = async (featureNavigationArray) => { for (let j = 2; j < featureNavigationArray.length; j++) { if (featureNavigationArray[j] === 'Talk to the Veterans Crisis Line now') { @@ -537,12 +604,12 @@ const navigateToFeature = async (featureNavigationArray) => { featureNavigationArray[j] === 'Reply' || featureNavigationArray[j] === 'Only use messages for non-urgent needs' ) { - await element(by.id('viewMessageTestID')).scrollTo('bottom') + await element(by.id(CommonE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom') await element(by.text(featureNavigationArray[j])).atIndex(0).tap() } else if (featureNavigationArray[j] === 'Email address') { await waitFor(element(by.text(featureNavigationArray[j]))) .toBeVisible() - .whileElement(by.id('ContactInfoTestID')) + .whileElement(by.id(CommonE2eIdConstants.CONTACT_INFO_SCREEN_ID)) .scroll(50, 'down') await element(by.text(featureNavigationArray[j])).tap() } else if (featureNavigationArray[j] === 'Received July 17, 2008') { @@ -561,21 +628,17 @@ const navigateToFeature = async (featureNavigationArray) => { .scroll(50, 'down') await element(by.text(featureNavigationArray[j])).tap() } else if (featureNavigationArray[j] === 'Request Refill') { - if (device.getPlatform() === 'ios') { - await element(by.text(featureNavigationArray[j])).tap() - } else { - await element(by.text('Request Refill ')).tap() - } + await element(by.text(CommonE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap() } else if (featureNavigationArray[j] === 'Contact us' || featureNavigationArray[j] === 'Proof of Veteran status') { await waitFor(element(by.text(featureNavigationArray[j]))) .toBeVisible() - .whileElement(by.id('homeScreenID')) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(featureNavigationArray[j])).tap() } else if (featureNavigationArray[0] === 'HomeScreen.e2e' && featureNavigationArray[j] !== 'Appointments') { await waitFor(element(by.text(featureNavigationArray[j]))) .toBeVisible() - .whileElement(by.id('homeScreenID')) + .whileElement(by.id(CommonE2eIdConstants.HOME_SCREEN_SCROLL_ID)) .scroll(200, 'down') await element(by.text(featureNavigationArray[j])).tap() } else { @@ -588,19 +651,24 @@ const navigateToFeature = async (featureNavigationArray) => { } } +/** Verifies that the availibility banner is the correct type and is populated with the correct information. +* @param featureNavigationArray: Array that tells the AF script how to navigate to the feature +* @param AFUseCaseName: Name of the AF type. +* @param AFUseCaseUpgrade: Boolean value that tells the script whether to enable the update now button or not +* */ export async function verifyAF(featureNavigationArray, AFUseCase, AFUseCaseUpgrade = false) { let featureName if (AFUseCase !== 'AllowFunction') { featureName = featureNavigationArray[featureNavigationArray.length - 1] await navigateToFeature(featureNavigationArray) } - await expect(element(by.text('AF Heading Test'))).toExist() - await expect(element(by.text('AF Body Test'))).toExist() + await expect(element(by.text(CommonE2eIdConstants.AF_ERROR_MSG_TITLE_ENTERED_TEXT))).toExist() + await expect(element(by.text(CommonE2eIdConstants.AF_BODY_ENTERED_TEXT))).toExist() if (AFUseCase === 'DenyAccess') { try { - await element(by.text('OK')).tap() + await element(by.text(CommonE2eIdConstants.OK_UNIVERSAL_TEXT)).tap() } catch (ex) { - await element(by.text('OK')).atIndex(0).tap() + await element(by.text(CommonE2eIdConstants.OK_UNIVERSAL_TEXT)).atIndex(0).tap() } } else if (AFUseCase === 'DenyContent' || AFUseCase === 'AllowFunction') { if (device.getPlatform() === 'android') { @@ -608,7 +676,11 @@ export async function verifyAF(featureNavigationArray, AFUseCase, AFUseCaseUpgra try { await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0).tap() } catch (ex) { - await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID).withAncestor(by.id('AFUseCase2TestID'))).tap() + await element( + by + .id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID) + .withAncestor(by.id(CommonE2eIdConstants.AF_USE_CASE_TWO_ID)), + ).tap() } await setTimeout(5000) await device.takeScreenshot(featureName + 'AFUseCase2PhoneNumber') @@ -617,7 +689,9 @@ export async function verifyAF(featureNavigationArray, AFUseCase, AFUseCaseUpgra await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0).tap() } catch (ex) { await element( - by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID).withAncestor(by.id('AFUseCase2TestID')), + by + .id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID) + .withAncestor(by.id(CommonE2eIdConstants.AF_USE_CASE_TWO_ID)), ).tap() } await setTimeout(5000) @@ -628,9 +702,9 @@ export async function verifyAF(featureNavigationArray, AFUseCase, AFUseCaseUpgra if (AFUseCaseUpgrade) { try { - await expect(element(by.text('Update now'))).toExist() + await expect(element(by.text(CommonE2eIdConstants.AF_UPDATE_NOW_BUTTON_TEXT))).toExist() } catch (ex) { - await expect(element(by.text('Update now')).atIndex(1)).toExist() + await expect(element(by.text(CommonE2eIdConstants.AF_UPDATE_NOW_BUTTON_TEXT)).atIndex(1)).toExist() } } } @@ -642,10 +716,9 @@ export async function verifyAF(featureNavigationArray, AFUseCase, AFUseCaseUpgra } } -/* Toggle the specified remote config feature flag - * +/** Toggle the specified remote config feature flag * @param flagName - name of flag to toggle - */ +* */ export async function toggleRemoteConfigFlag(flagName: string) { await loginToDemoMode() await openProfile() diff --git a/VAMobile/ios/Gemfile.lock b/VAMobile/ios/Gemfile.lock index 5c6b9eda936..aa3ca83f091 100644 --- a/VAMobile/ios/Gemfile.lock +++ b/VAMobile/ios/Gemfile.lock @@ -25,8 +25,8 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.1010.0) - aws-sdk-core (3.213.0) + aws-partitions (1.1013.0) + aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -34,7 +34,7 @@ GEM aws-sdk-kms (1.96.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.172.0) + aws-sdk-s3 (1.174.0) aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) @@ -227,7 +227,7 @@ GEM logger (1.6.1) mini_magick (4.13.2) mini_mime (1.1.5) - minitest (5.25.1) + minitest (5.25.2) molinillo (0.8.0) multi_json (1.15.0) multipart-post (2.4.1) diff --git a/VAMobile/ios/fastlane/Fastfile b/VAMobile/ios/fastlane/Fastfile index 1b28d55cbab..bef78707464 100644 --- a/VAMobile/ios/fastlane/Fastfile +++ b/VAMobile/ios/fastlane/Fastfile @@ -118,6 +118,14 @@ platform :ios do puts('Begin Demo lane') end + desc "makes a test build to ensure changes to native directories did not break build process. DOES NOT DISTRIBUTE" + lane :test_build_only do |options| + ensure_xcode_version(version: "15.2", strict: false) + update_version(options[:version]) + sign + build + end + after_all do |lane, options| # This block is called, only if the executed lane was successful end diff --git a/VAMobile/ios/fastlane/metadata/en-US/release_notes.txt b/VAMobile/ios/fastlane/metadata/en-US/release_notes.txt index cb218d76a9f..71941198bb1 100644 --- a/VAMobile/ios/fastlane/metadata/en-US/release_notes.txt +++ b/VAMobile/ios/fastlane/metadata/en-US/release_notes.txt @@ -1 +1 @@ -You can now view and download files from your claim in the app. +We added general improvements and fixed a few bugs. diff --git a/VAMobile/package.json b/VAMobile/package.json index 77bcecb5bc9..0dff0f1082d 100644 --- a/VAMobile/package.json +++ b/VAMobile/package.json @@ -37,9 +37,9 @@ "pods": "cd ios && pod install && cd .." }, "dependencies": { - "@department-of-veterans-affairs/mobile-assets": "0.13.0", - "@department-of-veterans-affairs/mobile-component-library": "0.21.0", - "@department-of-veterans-affairs/mobile-tokens": "0.17.1", + "@department-of-veterans-affairs/mobile-assets": "0.14.0", + "@department-of-veterans-affairs/mobile-component-library": "0.27.1", + "@department-of-veterans-affairs/mobile-tokens": "0.20.0", "@expo/react-native-action-sheet": "^4.1.0", "@react-native-async-storage/async-storage": "^1.24.0", "@react-native-cookies/cookies": "^6.2.1", @@ -54,7 +54,7 @@ "@react-navigation/stack": "^6.4.1", "@reduxjs/toolkit": "^2.3.0", "@tanstack/react-query": "^5.59.15", - "eslint-plugin-tsdoc": "^0.3.0", + "eslint-plugin-tsdoc": "^0.4.0", "i18next": "^23.7.18", "jsc-android": "^250231.0.0", "lottie-react-native": "^5.1.6", @@ -119,7 +119,7 @@ "babel-jest": "^29.7.0", "babel-plugin-module-resolver": "^5.0.2", "concurrently": "^8.2.2", - "detox": "^20.25.5", + "detox": "^20.28.0", "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^27.9.0", diff --git a/VAMobile/src/api/types/PersonalInformationData.ts b/VAMobile/src/api/types/PersonalInformationData.ts index 7b849b39263..45f276a2563 100644 --- a/VAMobile/src/api/types/PersonalInformationData.ts +++ b/VAMobile/src/api/types/PersonalInformationData.ts @@ -10,6 +10,7 @@ export type PersonalInformationPayload = { signinService: string birthDate: string | null hasFacilityTransitioningToCerner: boolean + edipi: string | null } } } diff --git a/VAMobile/src/components/Pagination.test.tsx b/VAMobile/src/components/Pagination.test.tsx index 23322b667ad..c149bac4e47 100644 --- a/VAMobile/src/components/Pagination.test.tsx +++ b/VAMobile/src/components/Pagination.test.tsx @@ -34,7 +34,7 @@ context('Pagination', () => { it('calls onPrev when previous arrow is pressed', () => { renderWithProps({ page: 2 }) - fireEvent.press(screen.getByA11yHint('Previous page')) + fireEvent.press(screen.getByTestId('previous-page')) expect(prevSpy).toHaveBeenCalled() }) @@ -45,7 +45,7 @@ context('Pagination', () => { it('calls onNext when next arrow is pressed', () => { renderWithProps() - fireEvent.press(screen.getByA11yHint('Next page')) + fireEvent.press(screen.getByTestId('next-page')) expect(nextSpy).toHaveBeenCalled() }) diff --git a/VAMobile/src/components/Pagination.tsx b/VAMobile/src/components/Pagination.tsx index e55ba6c19a3..a46fcad7737 100644 --- a/VAMobile/src/components/Pagination.tsx +++ b/VAMobile/src/components/Pagination.tsx @@ -30,8 +30,8 @@ export type PaginationProps = { type PaginationArrowProps = { /** function called when pressed */ onPress: () => void - /** optional accessibility hint */ - a11yHint?: string + /** optional accessibility label */ + a11yLabel?: string /** whether or not this button is disabled */ disabled: boolean /** test id */ @@ -40,7 +40,7 @@ type PaginationArrowProps = { iconProps: IconProps } -export const PaginationArrow: FC = ({ onPress, a11yHint, iconProps, testID, disabled }) => { +export const PaginationArrow: FC = ({ onPress, a11yLabel, iconProps, testID, disabled }) => { const theme = useTheme() const pressableProps: PressableProps = { @@ -48,7 +48,6 @@ export const PaginationArrow: FC = ({ onPress, a11yHint, i accessibilityRole: 'link', disabled, accessible: true, - accessibilityHint: a11yHint, accessibilityState: disabled ? { disabled: true } : {}, } @@ -59,7 +58,7 @@ export const PaginationArrow: FC = ({ onPress, a11yHint, i borderRadius: 5, } return ( - + @@ -92,7 +91,7 @@ const Pagination: FC = ({ page, pageSize, totalEntries, onPrev, const previousProps: PaginationArrowProps = { onPress: onPrevPress, testID: 'previous-page', - a11yHint: t('pagination.previous'), + a11yLabel: t('pagination.previous'), iconProps: { name: 'ChevronLeft', fill: theme.colors.icon.pagination }, disabled: page === 1, } @@ -100,7 +99,7 @@ const Pagination: FC = ({ page, pageSize, totalEntries, onPrev, const nextProps: PaginationArrowProps = { onPress: onNextPress, testID: 'next-page', - a11yHint: t('pagination.next'), + a11yLabel: t('pagination.next'), iconProps: { name: 'ChevronRight', fill: theme.colors.icon.pagination }, disabled: page * pageSize >= totalEntries, } diff --git a/VAMobile/src/components/VALogo/VALogo.tsx b/VAMobile/src/components/VALogo/VALogo.tsx index 38344e2e76f..65cbd1f9112 100644 --- a/VAMobile/src/components/VALogo/VALogo.tsx +++ b/VAMobile/src/components/VALogo/VALogo.tsx @@ -14,7 +14,7 @@ export const VALogo: FC = ({ variant, testID }) => { const theme = useTheme() const logoProps: ImageProps = { - width: 270, + width: 256, height: 57, } diff --git a/VAMobile/src/constants/common.ts b/VAMobile/src/constants/common.ts index 44a1ff0df2b..31a71876e17 100644 --- a/VAMobile/src/constants/common.ts +++ b/VAMobile/src/constants/common.ts @@ -57,6 +57,9 @@ export const MAIL_TO_REGEX_EXP = new RegExp( export const PHONE_REGEX_EXP = new RegExp( /^\s*(?:\+?(\d{0,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *(x)(\d+))?,?.?\s*$/, ) + +export const SSN_REGEX_EXP = new RegExp(/^\d{3}-?\d{2}-?\d{4}$/) + export const NUMBERS_ONLY_REGEX_EXP = new RegExp(/^[0-9]/) export const URL_REGEX_EXP = new RegExp(/^((https:|http:)\S*)/) diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentLocation.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentLocation.tsx index 5cb2fc60079..21223e4a7d5 100644 --- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentLocation.tsx +++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentLocation.tsx @@ -205,7 +205,7 @@ const getClinicInfo = ( ) default: - return Spacer({ size: theme.dimensions.standardMarginBetween }) + return Spacer({ size: 'lg' }) } } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/ProfileScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/ProfileScreen.tsx index ccc6f5bf5eb..b21afc5bc34 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/ProfileScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/ProfileScreen.tsx @@ -67,11 +67,15 @@ function ProfileScreen({ navigation }: ProfileScreenProps) { ) : getUserAuthorizedServicesError ? ( - + <> + + {/* Need to ALWAYS include the settings page so a user may logout despite circumstance */} + navigateTo('Settings')} testID="toSettingsID" /> + ) : ( <> {displayName} diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/InAppFeedbackScreen/InAppFeedbackScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/InAppFeedbackScreen/InAppFeedbackScreen.tsx index 460de551d53..a0697269668 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/InAppFeedbackScreen/InAppFeedbackScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/InAppFeedbackScreen/InAppFeedbackScreen.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react' import { useTranslation } from 'react-i18next' -import { Pressable } from 'react-native' +import { Alert, Pressable } from 'react-native' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' @@ -9,6 +9,7 @@ import { RootNavStackParamList } from 'App' import { BorderColorVariant, Box, LargePanel, RadioGroup, RadioGroupProps, TextView, VATextInput } from 'components' import { NAMESPACE } from 'constants/namespaces' +import { checkStringForPII } from 'utils/common' import getEnv from 'utils/env' import { useExternalLink, useTheme } from 'utils/hooks' @@ -28,8 +29,26 @@ function InAppFeedbackScreen({ navigation }: InAppFeedbackScreenProps) { // }) const onSubmit = (): void => { + const { found, newText } = checkStringForPII(task) // logAnalyticsEvent(Events.vama_feedback_submitted(taskCompleted, satisfaction)) - navigation.goBack() + if (found) { + Alert.alert(t('inAppFeedback.personalInfo.title'), t('inAppFeedback.personalInfo.body'), [ + { + text: t('inAppFeedback.personalInfo.edit'), + style: 'cancel', + }, + { + text: t('inAppFeedback.personalInfo.submit'), + onPress: () => { + setTaskOverride(newText) + navigation.goBack() + }, + style: 'default', + }, + ]) + } else { + navigation.goBack() + } } const radioGroupProps: RadioGroupProps = { diff --git a/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx b/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx index d917054cb56..2fcaacdae2c 100644 --- a/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx @@ -142,13 +142,23 @@ function VeteranStatusScreen({ navigation }: VeteranStatusScreenProps) { )} - + {t('veteranStatus.periodOfService')} {getPeriodOfService} - + {personalInfo?.edipi && ( + + + {t('veteranStatus.dodIdNumber')} + + + {personalInfo?.edipi} + + + )} + {t('veteranStatus.uniformedServices')} diff --git a/VAMobile/src/screens/OnboardingCarousel/OnboardingCarousel.tsx b/VAMobile/src/screens/OnboardingCarousel/OnboardingCarousel.tsx index f5bf036ee75..af80cc0d9e6 100644 --- a/VAMobile/src/screens/OnboardingCarousel/OnboardingCarousel.tsx +++ b/VAMobile/src/screens/OnboardingCarousel/OnboardingCarousel.tsx @@ -121,7 +121,6 @@ function OnboardingCarousel() { name: 'OnboardingAppOverview', component: OnboardingAppOverview, a11yHints: { - skipHint: t('onboarding.skipA11yHint'), carouselIndicatorsHint: t('onboarding.progressBarA11yHint.viewingPage', { currPage: 1 }), continueHint: t('onboarding.continueA11yHint.healthOnboarding'), }, @@ -130,7 +129,6 @@ function OnboardingCarousel() { name: 'OnboardingHealth', component: OnboardingHealth, a11yHints: { - skipHint: t('onboarding.skipA11yHint'), carouselIndicatorsHint: t('onboarding.progressBarA11yHint.viewingPage', { currPage: 2 }), continueHint: t('onboarding.continueA11yHint.benefitsOnboarding'), backHint: t('onboarding.backA11yHint.overviewOnboarding'), @@ -140,7 +138,6 @@ function OnboardingCarousel() { name: 'OnboardingBenefits', component: OnboardingBenefits, a11yHints: { - skipHint: t('onboarding.skipA11yHint'), carouselIndicatorsHint: t('onboarding.progressBarA11yHint.viewingPage', { currPage: 3 }), continueHint: t('onboarding.continueA11yHint.paymentsOnboarding'), backHint: t('onboarding.backA11yHint.healthOnboarding'), @@ -151,7 +148,6 @@ function OnboardingCarousel() { component: OnboardingPayments, a11yHints: { carouselIndicatorsHint: t('onboarding.progressBarA11yHint.viewingPage', { currPage: 4 }), - doneHint: t('onboarding.skipA11yHint'), backHint: t('onboarding.backA11yHint.benefitsOnboarding'), }, }, diff --git a/VAMobile/src/screens/auth/LoaGate/LoaGate.test.tsx b/VAMobile/src/screens/auth/LoaGate/LoaGate.test.tsx index 7ea655b3787..15ca5421659 100644 --- a/VAMobile/src/screens/auth/LoaGate/LoaGate.test.tsx +++ b/VAMobile/src/screens/auth/LoaGate/LoaGate.test.tsx @@ -12,18 +12,20 @@ context('LoaGate', () => { }) it('initializes correctly', () => { - expect(screen.getByRole('header', { name: 'Sign in' })).toBeTruthy() + expect(screen.getByRole('header', { name: 'Sign in with a verified account' })).toBeTruthy() expect( screen.getByText( - 'Before we give you access to your VA claim and health care information, we need to make sure you’re you. This helps us protect you from fraud and identity theft.', + 'You’ll need to sign in with an identity-verified account through one of our account providers. Identity verification helps us protect all Veterans’ information and prevent scammers from stealing your benefits.', ), ).toBeTruthy() expect( screen.getByText( - 'If you haven’t yet verified your identity, we’ll help you complete the process when you sign in.', + 'Don’t yet have a verified account? Continue to the sign-in page. Follow the instructions to create a Login.gov or ID.me account. Then come back here and sign in. We’ll help you verify your identity for your account.', ), ).toBeTruthy() - expect(screen.getByRole('tab', { name: "Read more if you haven't yet verified" })).toBeTruthy() + expect( + screen.getByText('Not sure if your account is verified? Sign in now. We’ll tell you if you need to verify.'), + ).toBeTruthy() expect(screen.getByRole('button', { name: 'Continue to sign in' })).toBeTruthy() }) }) diff --git a/VAMobile/src/screens/auth/LoaGate/LoaGate.tsx b/VAMobile/src/screens/auth/LoaGate/LoaGate.tsx index 051e6737142..fecdcb54177 100644 --- a/VAMobile/src/screens/auth/LoaGate/LoaGate.tsx +++ b/VAMobile/src/screens/auth/LoaGate/LoaGate.tsx @@ -5,7 +5,7 @@ import { useNavigation } from '@react-navigation/native' import { Button } from '@department-of-veterans-affairs/mobile-component-library' -import { Box, CollapsibleView, FullScreenSubtask, TextView, TextViewProps, VABulletList } from 'components' +import { Box, FullScreenSubtask, TextView, TextViewProps } from 'components' import { NAMESPACE } from 'constants/namespaces' import { useTheme } from 'utils/hooks' import { useStartAuth } from 'utils/hooks/auth' @@ -18,11 +18,6 @@ function LoaGate({}: LoaGateProps) { const startAuth = useStartAuth() const navigation = useNavigation() - const bulletOne = { - text: t('loaGate.readMore.bulletOne'), - boldedText: ' ' + t('loaGate.readMore.or'), - } - const bodyTextProps: TextViewProps = { variant: 'MobileBody', } @@ -34,7 +29,7 @@ function LoaGate({}: LoaGateProps) { return ( + {t('loaGate.p2.noVerifiedAccount')} {t('loaGate.p2')} - - - {t('loaGate.readMore.p1')} - - {t('loaGate.readMore.p2')} - - - {t('loaGate.readMore.itemOne')} - {t('and')} - - - - {t('loaGate.readMore.itemTwo.proofOfID')} - - - {t('loaGate.readMore.itemTwo.OfferProof')} - - - - - + + {t('loaGate.p3.notSureOfAccount')} + {t('loaGate.p3')} +