diff --git a/.github/ISSUE_TEMPLATE/External Bug Submission Template.md b/.github/ISSUE_TEMPLATE/External Bug Submission Template.md
index cb7f91ddd1d..f428f5ef592 100644
--- a/.github/ISSUE_TEMPLATE/External Bug Submission Template.md
+++ b/.github/ISSUE_TEMPLATE/External Bug Submission Template.md
@@ -3,7 +3,7 @@ name: External Bug Report Template
about: This bug template should be used by external parties (non-VA / non-mobile) when submitting concerns
title: BUG - [iOS/Android/All] - [Short description]
labels: bug,qa, external-submission
-assignees: DJUltraTom
+assignees: TKDickson
---
## Summary of the bug
General overview of what happened and where it happened.
diff --git a/.github/ISSUE_TEMPLATE/Post_RC_Code_Change.md b/.github/ISSUE_TEMPLATE/Post_RC_Code_Change.md
index 3b0b8616e3b..0bb1da5594c 100644
--- a/.github/ISSUE_TEMPLATE/Post_RC_Code_Change.md
+++ b/.github/ISSUE_TEMPLATE/Post_RC_Code_Change.md
@@ -3,7 +3,7 @@ name: Post RC Code Change
about: Template for Adding Code After RC is Cut requiring a new RC build
title: Post RC Code Change Template
labels: release
-assignees: djultratom, bischoffa
+assignees: TKDickson, bischoffa
---
diff --git a/.github/ISSUE_TEMPLATE/QA_feature_signoff.md b/.github/ISSUE_TEMPLATE/QA_feature_signoff.md
index 02c424cd0e8..ef94786ef05 100644
--- a/.github/ISSUE_TEMPLATE/QA_feature_signoff.md
+++ b/.github/ISSUE_TEMPLATE/QA_feature_signoff.md
@@ -15,7 +15,7 @@ _'Relevant for this epic?' column to include Y or N, and explanation if a N_
| -- | -- | -- |
| Standards | Test plan was peer reviewed | |
| Standards | All tickets found during testing have been prioritized | |
-| Standards | Feature testing summary written and reviewed with feature team ([example](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/products/va-mobile-app/features/design-personalization/qa/findings.md)) | |
+| Standards | [Feature testing summary](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/QA/QualityAssuranceProcess/Testing%20Summary) written and reviewed with feature team | |
| Testing | ACs met on all implementation tickets | |
| Testing | Accessibility testing per accessibility design annotations | |
| Testing | [API errors](https://dsvavsp.testrail.io/index.php?/suites/view/92&group_by=cases:section_id&group_order=desc&display_deleted_cases=0&group_id=8943) handled well | |
diff --git a/.github/ISSUE_TEMPLATE/detox_nightly_build_failure.md b/.github/ISSUE_TEMPLATE/detox_nightly_build_failure.md
index 2f654b51763..b6f8b0aaf0f 100644
--- a/.github/ISSUE_TEMPLATE/detox_nightly_build_failure.md
+++ b/.github/ISSUE_TEMPLATE/detox_nightly_build_failure.md
@@ -3,7 +3,7 @@ name: Detox Nightly Build Failure Template
about: Template for reporting a detox nightly build failure
title: "Bug - Detox - Fix Overnight Failures"
labels: bug, QA and Release
-assignees: rbontrager
+assignees: rbontrager, TKDickson
---
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
index 0763d234b24..927030a135d 100644
--- a/.github/ISSUE_TEMPLATE/feature-request.yml
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -1,7 +1,7 @@
name: VAHB Mobile App Change Request Form
description: Use this template to formally request a new feature, enhancement to a feature, discovery, research, analytics request or other ask/change for the VA Mobile App team to evaluate.
title: "Change Request: [name of change]"
-labels: [ "Epic", "Leads team" ]
+labels: [ "Epic", "Leads team", "needs-review" ]
projects: ["department-of-veterans-affairs/823"]
assignees: [ DonMcCaugheyUSDS, rtwell, Hallm13, kellylein ]
body:
diff --git a/.github/ISSUE_TEMPLATE/release_ticket.md b/.github/ISSUE_TEMPLATE/release_ticket.md
index b57b9147018..faa9246b6d8 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, DJUltraTom, chrisj-usds, drjecker, dumathane, rachelhanster, kellylein, DonMcCaugheyUSDS
+assignees: timwright12, chrisj-usds, dumathane, rachelhanster, kellylein, DonMcCaugheyUSDS, TKDickson
---
@@ -51,15 +51,4 @@ Indicate NA if no changes.
## Regression Testing
[QA Testrail Regression Test Run Here](^^^Testrail-url^^^)
-
- ```mermaid
- %%{init: {'theme': 'base', 'themeVariables': { 'pie1': '#00ff00', 'pie2': '#212121', 'pie3': '#FFE000', 'pie4': '#ff0000', 'pie5': '#cccccc', 'pieLegendTextSize': '20px', 'pieLegendTextColor':'#777777', 'pieSectionTextSize': '24px', 'pieTitleTextColor': '#777777'}}}%%
- pie showData
- title Regression pass for v2.1.0 Tuesday Apr 25, 2023 release
- "Passed": 0
- "Blocked": 0
- "Retest": 0
- "Failed": 0
- "Untested": 1
- ```
diff --git a/.github/workflows/e2e_android.yml b/.github/workflows/e2e_android.yml
index 31352e70549..07079320794 100644
--- a/.github/workflows/e2e_android.yml
+++ b/.github/workflows/e2e_android.yml
@@ -340,6 +340,7 @@ jobs:
dateOfIssue: ${{ env.DATE_OF_ISSUE }}
OS: "Android"
issues: ${{steps.failing_tests.outputs.FAILING_TEST}}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
id: create-issue
matrix-send_test_results_to_testrail:
diff --git a/.github/workflows/e2e_ios.yml b/.github/workflows/e2e_ios.yml
index bd6d4029e05..4cf563640aa 100644
--- a/.github/workflows/e2e_ios.yml
+++ b/.github/workflows/e2e_ios.yml
@@ -192,11 +192,11 @@ jobs:
id: run_e2e_tests
run: |
if [[ "${{needs.output_detox_tests_to_run.outputs.output2}}" == "" ]]; then
- yarn e2e:ios-test /e2e/tests/${{matrix.testsuite}} --updateSnapshot
+ yarn e2e:ios-test /e2e/tests/${{matrix.testsuite}} --updateSnapshot --debug-synchronization 15000
echo "NAV_AF_TEST_RUN=" >> "$GITHUB_OUTPUT"
else
echo "NAV_AF_TEST_RUN=true" >> "$GITHUB_OUTPUT"
- yarn e2e:ios-test /e2e/tests/Navigation.e2e AvailabilityFramework.e2e ${{matrix.testsuite}}.e2e --updateSnapshot
+ yarn e2e:ios-test /e2e/tests/Navigation.e2e AvailabilityFramework.e2e ${{matrix.testsuite}}.e2e --updateSnapshot --debug-synchronization 15000
fi
continue-on-error: true
@@ -206,9 +206,9 @@ jobs:
run: |
yarn jest:clear;
if [[ "${{ steps.run_e2e_tests.outputs.NAV_AF_TEST_RUN}}" != "" ]]; then
- yarn e2e:ios-test /e2e/tests/Navigation.e2e AvailabilityFramework.e2e ${{matrix.testsuite}}.e2e --updateSnapshot
+ yarn e2e:ios-test /e2e/tests/Navigation.e2e AvailabilityFramework.e2e ${{matrix.testsuite}}.e2e --updateSnapshot --debug-synchronization 15000
else
- yarn e2e:ios-test /e2e/tests/${{matrix.testsuite}} --updateSnapshot
+ yarn e2e:ios-test /e2e/tests/${{matrix.testsuite}} --updateSnapshot --debug-synchronization 15000
fi
- name: Upload e2e-junit
@@ -318,6 +318,7 @@ jobs:
dateOfIssue: ${{ env.DATE_OF_ISSUE }}
OS: "iOS"
issues: ${{steps.failing_tests.outputs.FAILING_TEST}}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
id: create-issue
matrix-send_test_results_to_testrail:
diff --git a/.github/workflows/label_pull_request_onCreate.yml b/.github/workflows/label_pull_request_onCreate.yml
deleted file mode 100644
index ea6b13a9a17..00000000000
--- a/.github/workflows/label_pull_request_onCreate.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# Workflow that labels a pr with the correct label
-name: "[Github Management] Pull Request Labeler on create or taken out of draft"
-
-on:
- pull_request:
- types: [opened, ready_for_review]
-
-jobs:
- needs_review:
- if: github.event.requested_team.name == 'flagship-mobile-reviewers' && github.event.pull_request.draft == false
- permissions:
- pull-requests: write
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v3
-
- - name: Add FE-Needs Reviewv
- run: |
- gh pr edit ${{ github.event.pull_request.number }} --add-label "FE-Needs Review"
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/label_pull_request_onReview.yml b/.github/workflows/label_pull_request_onReview.yml
index 2751d5ce279..aad4113b01d 100644
--- a/.github/workflows/label_pull_request_onReview.yml
+++ b/.github/workflows/label_pull_request_onReview.yml
@@ -17,7 +17,7 @@ jobs:
- name: Remove old labels and add FE-Changes Requested
run: |
- gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-Needs Review,FE-With QA" --add-label "FE-Changes Requested"
+ gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-With QA" --add-label "FE-Changes Requested"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -29,9 +29,9 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- - name: Remove old labels and add FE-Needs Review
+ - name: Remove old labels
run: |
- gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-Changes Requested" --add-label "FE-Needs Review"
+ gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-Changes Requested"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -59,10 +59,10 @@ jobs:
if [[ $(jq '[.[] | select(. | IN("timwright12", "rbontrager", "DJUltraTom", "TKDickson"))] | length' <<< "$approvals") -gt 0 ]]
then
echo 'This PR has QA approval and one other'
- gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-Needs Review,FE-With QA" --add-label "FE-Ready to Merge"
+ gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-With QA" --add-label "FE-Ready to Merge"
else
echo 'This PR requires QA approval'
- gh pr edit ${{ github.event.pull_request.number }} --remove-label "FE-Needs Review" --add-label "FE-With QA"
+ gh pr edit ${{ github.event.pull_request.number }} --add-label "FE-With QA"
fi
else
echo 'This PR requires 2 approvals, including one QA approval'
diff --git a/.github/workflows/new_release_branch.yml b/.github/workflows/new_release_branch.yml
index f72b27ccc46..f452e3568c4 100644
--- a/.github/workflows/new_release_branch.yml
+++ b/.github/workflows/new_release_branch.yml
@@ -41,4 +41,9 @@ jobs:
- name: Cut release branch
env:
GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_PAT }}
- run: ./release_branch.sh
+ run: |
+ if [[ "${{ needs.get-workflow-environment.outputs.environment_name }}" == "manual-release" ]]; then
+ ./release_branch.sh --bypass-date-check
+ else
+ ./release_branch.sh
+ fi
\ No newline at end of file
diff --git a/.github/workflows/release_branch_issue.yml b/.github/workflows/release_branch_issue.yml
index c07274f1ac7..40db9d7f871 100644
--- a/.github/workflows/release_branch_issue.yml
+++ b/.github/workflows/release_branch_issue.yml
@@ -93,7 +93,7 @@ jobs:
id: map_slack_ids
run: |
declare -A GITHUB_TO_SLACK_MAP
- GITHUB_TO_SLACK_MAP["DJUltraTom"]="U02BBL9L0CU"
+ GITHUB_TO_SLACK_MAP["TKDickson"]="U02PJLJ0H6H"
GITHUB_TO_SLACK_MAP["kellylein"]="UJHA49K6X"
GITHUB_TO_SLACK_MAP["dumathane"]="U02RC1BRZBP"
GITHUB_TO_SLACK_MAP["timwright12"]="U01DBDAJZ18"
@@ -110,7 +110,7 @@ jobs:
- name: Notify Slack for release coordination
env:
SLACK_API_TOKEN: ${{ secrets.SLACK_API_TOKEN }}
- SLACK_DJUltraTom: $DJUltraTom
+ SLACK_TKDickson: $TKDickson
SLACK_kellylein: $kellylein
SLACK_dumathane: $dumathane
SLACK_timwright12: $timwright12
@@ -132,7 +132,7 @@ jobs:
- *Release Manager Approval Due:* ${{ needs.release_ticket.outputs.vaDueDate }}\n\
- *Tickets Tagged Appropriately:* ${{ needs.release_ticket.outputs.qaDueDate }}\n\n\
*Contacts:*\n\
- - *Release Testing:* <@${SLACK_DJUltraTom}>\n\
+ - *Release Testing:* <@${SLACK_TKDickson}>\n\
- *Release Manager:* <@${SLACK_kellylein}>\n\
- *Release Ticket Validation:* <@${SLACK_dumathane}>\n\
- *Engineering:* <@${SLACK_dumathane}>, <@${SLACK_timwright12}>\n\
@@ -148,4 +148,4 @@ jobs:
-H 'Authorization: Bearer '"$SLACK_API_TOKEN" \
-H 'Content-type: application/json' \
-d @- \
- https://slack.com/api/chat.postMessage
\ No newline at end of file
+ https://slack.com/api/chat.postMessage
diff --git a/VAMobile/android/Gemfile.lock b/VAMobile/android/Gemfile.lock
index 57facfabfc9..a7ff0fb738e 100644
--- a/VAMobile/android/Gemfile.lock
+++ b/VAMobile/android/Gemfile.lock
@@ -10,7 +10,7 @@ GEM
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.0)
- aws-partitions (1.982.0)
+ aws-partitions (1.991.0)
aws-sdk-core (3.209.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
@@ -19,7 +19,7 @@ GEM
aws-sdk-kms (1.94.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.166.0)
+ aws-sdk-s3 (1.167.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
@@ -113,7 +113,7 @@ GEM
google-apis-firebaseappdistribution_v1alpha (~> 0.2.0)
fastlane-plugin-slack_bot (1.4.0)
gh_inspector (1.1.3)
- google-apis-androidpublisher_v3 (0.72.0)
+ google-apis-androidpublisher_v3 (0.73.0)
google-apis-core (>= 0.15.0, < 2.a)
google-apis-core (0.15.1)
addressable (~> 2.5, >= 2.5.1)
@@ -131,12 +131,12 @@ GEM
google-apis-core (>= 0.15.0, < 2.a)
google-apis-playcustomapp_v1 (0.16.0)
google-apis-core (>= 0.15.0, < 2.a)
- google-apis-storage_v1 (0.46.0)
+ google-apis-storage_v1 (0.47.0)
google-apis-core (>= 0.15.0, < 2.a)
google-cloud-core (1.7.1)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
- google-cloud-env (2.2.0)
+ google-cloud-env (2.2.1)
faraday (>= 1.0, < 3.a)
google-cloud-errors (1.4.0)
google-cloud-storage (1.52.0)
@@ -148,7 +148,7 @@ GEM
google-cloud-core (~> 1.6)
googleauth (~> 1.9)
mini_mime (~> 1.0)
- googleauth (1.11.0)
+ googleauth (1.11.1)
faraday (>= 1.0, < 3.a)
google-cloud-env (~> 2.1)
jwt (>= 1.4, < 3.0)
@@ -161,7 +161,7 @@ GEM
httpclient (2.8.3)
jmespath (1.6.2)
json (2.7.2)
- jwt (2.9.1)
+ jwt (2.9.3)
base64
mini_magick (4.13.2)
mini_mime (1.1.5)
@@ -205,13 +205,13 @@ GEM
uber (0.1.0)
unicode-display_width (2.6.0)
word_wrap (1.0.0)
- xcodeproj (1.25.0)
+ xcodeproj (1.25.1)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
- rexml (>= 3.3.2, < 4.0)
+ rexml (>= 3.3.6, < 4.0)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
diff --git a/VAMobile/android/app/src/main/java/gov/va/mobileapp/native_modules/CustomTabsIntentModule.kt b/VAMobile/android/app/src/main/java/gov/va/mobileapp/native_modules/CustomTabsIntentModule.kt
index 4f9827e73b9..a61312e8a4b 100644
--- a/VAMobile/android/app/src/main/java/gov/va/mobileapp/native_modules/CustomTabsIntentModule.kt
+++ b/VAMobile/android/app/src/main/java/gov/va/mobileapp/native_modules/CustomTabsIntentModule.kt
@@ -47,6 +47,7 @@ class CustomTabsIntentModule(private val context: ReactApplicationContext) :
appendQueryParameter("code_challenge", codeChallenge)
appendQueryParameter("application", "vamobile")
appendQueryParameter("oauth", "true")
+ appendQueryParameter("scope", "device_sso")
}
}
.build()
diff --git a/VAMobile/documentation/design/Components/Selection and input/Checkbox.md b/VAMobile/documentation/design/Components/Selection and input/Checkbox.md
new file mode 100644
index 00000000000..944ece80c14
--- /dev/null
+++ b/VAMobile/documentation/design/Components/Selection and input/Checkbox.md
@@ -0,0 +1,53 @@
+---
+title: Checkbox
+---
+
+Allows users to select one or more items from a list. Checkboxes are an easily understandable way to indicate that users can select one or more answers to a question or items from a list.
+
+## Examples
+
+### Checkbox
+
+#### Default
+**Open in**: [Storybook](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox--default) | [Figma](https://www.figma.com/design/Zzt8z60hCtdEzXx2GFWghH/%F0%9F%93%90-Component-Library---Design-System---VA-Mobile?node-id=1415-384&t=iHMS9U3pTWPZb8Qb-4)
+
+
+#### Tile
+**Open in**: [Storybook](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox--tile) | [Figma](https://www.figma.com/design/Zzt8z60hCtdEzXx2GFWghH/%F0%9F%93%90-Component-Library---Design-System---VA-Mobile?node-id=1415-384&t=iHMS9U3pTWPZb8Qb-4)
+
+
+#### Error
+**Open in**: [Storybook](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox--error) | [Figma](https://www.figma.com/design/Zzt8z60hCtdEzXx2GFWghH/%F0%9F%93%90-Component-Library---Design-System---VA-Mobile?node-id=1415-384&t=iHMS9U3pTWPZb8Qb-4)
+
+
+### Checkbox Group
+
+#### Default
+**Open in**: [Storybook](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox-group--default) | [Figma](https://www.figma.com/design/Zzt8z60hCtdEzXx2GFWghH/%F0%9F%93%90-Component-Library---Design-System---VA-Mobile?node-id=1415-441&t=iHMS9U3pTWPZb8Qb-4)
+
+
+#### Tile
+**Open in**: [Storybook](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox-group--tile) | [Figma](https://www.figma.com/design/Zzt8z60hCtdEzXx2GFWghH/%F0%9F%93%90-Component-Library---Design-System---VA-Mobile?node-id=1415-441&t=iHMS9U3pTWPZb8Qb-4)
+
+
+#### Error
+**Open in**: [Storybook](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox-group--error) | [Figma](https://www.figma.com/design/Zzt8z60hCtdEzXx2GFWghH/%F0%9F%93%90-Component-Library---Design-System---VA-Mobile?node-id=1415-441&t=iHMS9U3pTWPZb8Qb-4)
+
+
+## Usage
+[Refer to the VA Design System for usage guidance](https://design.va.gov/components/form/checkbox)
+
+## Code usage
+**Open Storybook**: [Checkbox](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox--docs) | [Checkbox Group](https://department-of-veterans-affairs.github.io/va-mobile-library/?path=/docs/checkbox-group--docs)
+
+## Content considerations
+* Refer to the [VA Design System for content considerations](https://design.va.gov/components/form/checkbox#usage)
+
+## Accessibility considerations
+* Refer to the [VA Design System for accessibility considerations](https://design.va.gov/components/form/checkbox#accessibility-considerations)
+* Screenreaders should announce the name, role, and state of each checkbox.
+
+### Related
+* [Checkbox - VA Design System](https://design.va.gov/components/form/checkbox)
+* [Checkbox - USWDS](https://designsystem.digital.gov/components/checkbox/)
+* [Checkbox - Material Design](https://m3.material.io/components/checkbox/overview)
\ No newline at end of file
diff --git a/VAMobile/documentation/design/intro.md b/VAMobile/documentation/design/intro.md
index 4c2a3194b5d..1ac79477e1d 100644
--- a/VAMobile/documentation/design/intro.md
+++ b/VAMobile/documentation/design/intro.md
@@ -32,6 +32,9 @@ A system to help you write, design, and build digital services on the VA Mobile
### Navigation
- [Segmented control](/va-mobile-app/design/Components/Navigation/Secondary/SegmentedControl)
+### Selection and input
+- [Checkbox](/va-mobile-app/design/Components/Selection%20and%20input/Checkbox)
+
-----
## Design system team
diff --git a/VAMobile/documentation/docs/About our team/_category_.json b/VAMobile/documentation/docs/About our team/_category_.json
index eb13411165b..997fb675c43 100644
--- a/VAMobile/documentation/docs/About our team/_category_.json
+++ b/VAMobile/documentation/docs/About our team/_category_.json
@@ -1,4 +1,4 @@
{
"label": "About our team",
- "position": 7
+ "position": 9
}
diff --git a/VAMobile/documentation/docs/App Features/_category_.json b/VAMobile/documentation/docs/App Features/_category_.json
new file mode 100644
index 00000000000..cc93fa1470c
--- /dev/null
+++ b/VAMobile/documentation/docs/App Features/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "App Features",
+ "position": 10
+}
diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Endpoint Creation Checklist.md b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Endpoint Creation Checklist.md
index 82fcd132721..02bb817cf6b 100644
--- a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Endpoint Creation Checklist.md
+++ b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/Endpoint Creation Checklist.md
@@ -42,7 +42,7 @@ title: Endpoint Creation Checklist
$ref: '#/components/responses/504'
```
-Regenerated HTML file by running `generate_static_docs.sh` command (`modules/mobile/docs/generate_static_docs.sh`)
+Regenerated [OpenAPI documentation](./OpenAPIDocumentation.md) HTML file by running `modules/mobile/docs/generate_static_docs.sh`
### Monitoring
diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ErrorHandling.md b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ErrorHandling.md
index 2cb495de19f..5cabc0971b6 100644
--- a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ErrorHandling.md
+++ b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ErrorHandling.md
@@ -12,7 +12,7 @@ The vets-api mobile endpoints generally follow the following pattern:
- the controller then uses [service objects](#outbound-request-service-objects) to communicate with other servers in the vets-api ecosystem. those service objects may perform their own validations. These will generally be the same as the ones performed in the controller but may occasionally differ.
- the external service processes that request and responds or times out
- the service object processes the response.
-- when the request fails (status is >= 400), the service objects will raise corresponding errors. These errors are rescued by [ExceptionHandling](#exception-handling) and responds with error details to the client.
+- when the request fails (status is >= 400), the service objects will raise corresponding errors. These errors are rescued by [ExceptionHandling](#exception-handling) and responds with error details to the client. (Note: this is only true if the service configuration uses the Faraday plug `faraday.use Faraday::Response::RaiseError`. Most services that make requests for data do use this plug.)
- when the request is successful (status is < 400), any additional business logic will be applied by the service object. This often includes parsing and converting the data to models.
- the data is then returned to the controller.
- the controller then performs any additional modifications that are necessary, serializes the data, and returns it to the client with an appropriate status code.
diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ModelsAndSerializers.md b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ModelsAndSerializers.md
new file mode 100644
index 00000000000..7d99e7782ae
--- /dev/null
+++ b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/ModelsAndSerializers.md
@@ -0,0 +1,31 @@
+# Models
+
+Unlike a typical Rails app, most of the models in the mobile module do not use ActiveRecord. Most of our models are populated from upstream data sources, so there's no need to store the data in a local database, which makes them a bad fit for ActiveRecord. As a result, most vets-api models inherit from `Dry::Struct` instead of `ActiveRecord::Base` to represent data. Dry structs use [`Dry::Types`](https://dry-rb.org/gems/dry-types) to validate attribute data types.
+
+
+## Serializers
+
+Mobile serializers use `JSONAPI::Serializer` and they do two things:
+- ensure that our responses are formatted as valid [JSONAPI](./JSONAPI.md)
+- determine which attributes from the model are included in the response
+
+## Best Practice
+
+- all data should be converted to models in order to use type validation
+- all nested attributes should be fully detailed within the data model in order to whitelist and validate all attributes that will be serialized. In other words, if a model has an attribute that is a hash or an array of hashes, all attributes in the hash should also be validated with `Dry::Types`. For example, a hash could look like:
+```
+ attribute :debt_history do
+ attribute :date, Types::Date
+ attribute :letter_code, Types::String
+ attribute :description, Types::String
+ end
+```
+an array of hashes could look like:
+```
+ attribute :debt_history, Types::Array do
+ attribute :date, Types::Date
+ attribute :letter_code, Types::String
+ attribute :description, Types::String
+ end
+```
+- all data should be serialized to ensure JSONAPI compliance
diff --git a/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/OpenAPIDocumentation.md b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/OpenAPIDocumentation.md
new file mode 100644
index 00000000000..8e9fb27134d
--- /dev/null
+++ b/VAMobile/documentation/docs/Engineering/BackEnd/Architecture/OpenAPIDocumentation.md
@@ -0,0 +1,27 @@
+# OpenAPI Documentation
+
+## OpenAPI Creation and Artifact Generation
+
+We document our API endpoints using [OpenAPI3](https://swagger.io/specification/). The documentation is recorded in a group of yaml files, which are converted to [HTML](../API/index.md) and JSON via the `modules/mobile/docs/generate_static_docs.sh` script. Developers must run that script each time they change the yaml to ensure that our documentation is up to date.
+
+## Setup
+
+Developers will need to install [redocly](https://redocly.com/docs/cli/installation#install-globally) in order to run the `generate_static_docs` script.
+
+## Using OpenAPI in RSpec
+
+The backend team uses the [committee-rails gem](https://github.com/willnet/committee-rails) to tie our documentation and specs together. This gem should be used in request specs to validate requests and responses against the JSON file generated by the `generate_static_docs` script. To add it to a request spec, simply call the method `assert_schema_conform(expected_status)`. This will use the uri path from the `request` object and the expected status (e.g., 200) to look up which schema the response should match and validate the `response.body` against it.
+
+## Limitations
+
+Our schema tests are only as good as the data we're testing against. These tests run against VCR cassettes we've either recorded or been given. These cassettes will not necessarily cover all cases. It's also possible for cassettes to become out of date, which can cause drift between our specs/OpenAPI documentation and reality.
+
+Schema tests are also only as good as the schema they're testing against. Schema should be written as strictly as possible. That means indicating when properties are required or nullable, when additional properties are not permitted in objects, indicating string formats, and specifying which strings are possible via the enum type. Greater specificity results in better documentation.
+
+## Best Practices
+
+- use [models and serializers](./ModelsAndSerializers.md) to lock down the schema
+- use all VCR cassettes available to ensure broad test coverage
+- only validate the schema once per unique case. In other words, if you need to run several tests with the same data setup and you expect the same response each time, there's no need to validate the schema each time.
+- use `nullable: true` when you know an attribute may be null. This should also be reflected in the model.
+- use `additionalProperties: false` on all objects. Additional properties should be prevented by the model and serializer.
diff --git a/VAMobile/documentation/docs/Engineering/FrontEnd/SingleSignOn.md b/VAMobile/documentation/docs/Engineering/FrontEnd/SingleSignOn.md
new file mode 100644
index 00000000000..ecd00656881
--- /dev/null
+++ b/VAMobile/documentation/docs/Engineering/FrontEnd/SingleSignOn.md
@@ -0,0 +1,43 @@
+# Single Sign-On
+
+Single sign-on (SSO) allows users to access the VA.gov website within the mobile app without having to manually authenticate in the browser.
+
+## Architecture
+
+The SSO process begins with the normal [authentication flow](../BackEnd/Architecture/Auth%20Diagrams.md), with the user signing in via the login screen. When the user taps the `Sign in` button, the mobile app launches the website's login webpage (https://va.gov/sign-in) in the browser. This webpage is opened with query parameters attached to the URL, specifically `code_challenge_method`, `code_challenge`, `application`, and `oauth`. In order to have the ability to start SSO sessions, we pass an additional query parameter to the URL, `scope`, which is set to `device_sso`. This informs the https://api.va.gov/v0/sign_in/authorize API endpoint that's called by the website that in addition to returning an access token and refresh token, it should return a device secret (`device_secret`), which can be used to fetch cookies for starting SSO sessions.
+
+Once the device secret is received, it is securely stored in Keychain (iOS) or Keystore (Android).
+
+### Fetching SSO cookies
+
+To start an SSO session, cookies need to be fetched using the device secret and access token. SSO cookies are fetched from the https://api.va.gov/v0/sign_in/token endpoint with a few parameters, most importantly `subject_token` (access token) and `actor_token` (device secret). This endpoint will return a response with the `Set-Cookie` header, which will contain the SSO cookies `vagov_access_token`, `vagov_refresh_token`, `vagov_anti_csrf_token`, and `vagov_info_token`. Once received, these cookies are stored in the `CookieManager` using `@react-native-cookies/cookies`, and can be used to authenticate the user's session in the WebView. Cookies are fetched when the WebView component is first mounted. (Note: The `useSSO` prop must be passed to the WebView component in order for SSO cookies to be fetched.)
+
+New cookies are always fetched whenever a new WebView is launched in the app. This is to ensure the SSO cookies used in the WebView are not expired.
+
+### Authenticating the WebView
+
+Once the SSO cookies are stored in the `CookieManager`, the `hasSession` field is set to `true` in `localstorage` for the WebView. This allows the VA.gov website to recognize that the user's session is authenticated.
+
+### Persisting the device secret
+
+As mentioned above, the device secret is stored in Keychain/Keystore to ensure its persistence for biometric login. When a user logs into the app with biometrics, the app will use the stored device secret to start SSO sessions. The device secret has an expiration of 45 days, similar to the refresh token.
+
+When the user manually signs out, all sessions spawned with the device secret are revoked via the https://api.va.gov/v0/sign_in/revoke API endpoint. Likewise, whenever the user manually signs in to the mobile app, a new device secret will be retrieved and stored.
+
+## Usage
+
+SSO sessions can easily be started in WebViews within the app. Whenever you have a link/button that navigates to the WebView screen, you can pass the `useSSO` prop to the screen to start an authenticated SSO session, e.g.
+
+```
+navigateTo('Webview', {
+ url: LINK_TO_OPEN_IN_WEBVIEW,
+ displayTitle: t('webview.vagov'),
+ useSSO: true,
+})
+```
+
+This will open the WebView screen with an SSO session, allowing the user to access features on the website that require authentication.
+
+## API documentation
+
+For more information on API usage for SSO, view the [Device SSO Token Exchange]() documentation.
diff --git a/VAMobile/documentation/docs/Engineering/_category_.json b/VAMobile/documentation/docs/Engineering/_category_.json
index 2fc5457c048..37dd203f884 100644
--- a/VAMobile/documentation/docs/Engineering/_category_.json
+++ b/VAMobile/documentation/docs/Engineering/_category_.json
@@ -1,4 +1,4 @@
{
"label": "Engineering",
- "position": 4
+ "position": 5
}
diff --git a/VAMobile/documentation/docs/Flagship design library/Components/Selection and Input/Form Elements/Checkbox.md b/VAMobile/documentation/docs/Flagship design library/Components/Selection and Input/Form Elements/Checkbox.md
index b9a60d55352..a4211aeb5fb 100644
--- a/VAMobile/documentation/docs/Flagship design library/Components/Selection and Input/Form Elements/Checkbox.md
+++ b/VAMobile/documentation/docs/Flagship design library/Components/Selection and Input/Form Elements/Checkbox.md
@@ -2,41 +2,4 @@
title: Checkbox
---
-Allows users to select one or more items from a list. Checkboxes are an easily understandable way to indicate that users can select one or more answers to a question or items from a list.
-
-## Examples
-
-### Single
-
-#### Master component
-
-
-#### Examples
-
-
-### Group
-
-#### Master component
-
-
-#### Examples
-
-
-## Usage
-
-[Refer to the VA Design System for usage guidance](https://design.va.gov/components/form/checkbox)
-
-## Content considerations
-* Refer to the [VA Design System for content considerations](https://design.va.gov/components/form/checkbox/#content-considerations)
-
-## Accessibility considerations
-* Refer to the [VA Design System for accessibility considerations](https://design.va.gov/components/form/checkbox/#accessibility-considerations)
-* Screenreaders should announce the name, role, and state of each checkbox.
-
-## Code usage
-Link to Storybook coming soon
-
-## Related
-* [Checkbox - VA Design System](https://design.va.gov/components/form/checkbox)
-* [Checkbox - USWDS](https://designsystem.digital.gov/components/checkbox/)
-* [Checkbox - Material Design](https://m3.material.io/components/checkbox/overview)
\ No newline at end of file
+See documentation in [Design System](/va-mobile-app/design/Components/Selection%20and%20input/Checkbox).
\ No newline at end of file
diff --git a/VAMobile/documentation/docs/Flagship design library/Templates/Home.md b/VAMobile/documentation/docs/Flagship design library/Templates/Home.md
new file mode 100644
index 00000000000..6f92d6acb06
--- /dev/null
+++ b/VAMobile/documentation/docs/Flagship design library/Templates/Home.md
@@ -0,0 +1,107 @@
+---
+title: Home Screen
+sidebar_position: 4
+---
+
+The Home screen is the initial/default screen of the VA Health & Benefits mobile app. It sits at the top level of the hierarchical navigation (as a peer to the Health, Benefits and Payments category screens) and displays a personalized summary of a Veteran's current tasks and interactions with features in the VA mobile app. It also contains the primary entry point for the Veteran's Profile information (including App Settings).
+
+
+
+
+## Anatomy:
+
+The VA mobile app’s personalized home screen combines content that is variable, fixed, personalized, and evergreen to deliver an experience that surfaces value to Veterans and supports understanding of the app’s capabilities, regardless of what a Veteran’s interactions are with the VA. To do this in a way that's predictable and performant, the Home screen displays a mix of content types within predetermined locations (zones).
+
+Having a mix of content, arranged into intentional zones, ensures that users:
+
+* Always see elements that help demonstrate the current & future value of the app
+* Always see "personalized" information even if they don't have any active tasks at a given moment (users don’t experience an empty home screen in the absence of tasks)
+* See the things that are likely relevant and valuable to them first
+* Get a consistent information structure for screen readers to tab through that is present even if load times lag
+* See things that are important to proper app functioning when necessary
+
+
+### Zones
+
+The VA Mobile app Home screen zones ensure that the most impactful content items are getting the proper placement in the screen's hierarchy while also handling a variety of user contexts and technical situations.
+
+
+
+
+#### Zone 1: Mission-critical app info
+
+* **What it is:** Area for alerts and announcements from the app. It informs users when there’s something they need to do to ensure that the app is functioning and informs users of new features
+ * **Module appearance logic:** Variable & optional, can be personalized or universal: Modules appear to all users when in applicable situations. Otherwise, do not show.
+* **What lives in this zone:**
+ * [Encouraged update](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/App%20Features/EncouragedUpdate/) (MVP)
+ * [What’s new](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/App%20Features/WhatsNew/) (MVP)
+* **Guidelines for future module inclusion:**
+Information is appropriate for inclusion on the home screen within the mission-critical app info section when it:
+ * Conveys information that’s necessary for the app to function properly
+ * Conveys information about important changes within the app
+
+
+#### Zone 2: Activity
+
+* **What it is:** An alphabetical list of feature modules giving Veterans an overview of what VA is doing for them—includes any critical “in-flight” tasks or actions that may need attention. Each module contains personalized information briefly summarizing that activity and provides a secondary entry point into the app feature.
+ * **Module appearance logic:** Variable. Modules appear while that feature’s activity is still considered “in flight” or when there is a user action to take. Each feature has different periods of time/circumstances that determine how long they are visible on the home screen (ex: the Claims module stays until the claim closes, the Secure Message stays until any new messages have been viewed).
+ * **Module anatomy**
+ * **Title:** Feature name
+ * **Description text:** Indicates # of items with an in-flight status; terms used vary by feature; provides just enough information to accurately indicate what is happening/is needed.
+* **What lives in this zone:**
+ * Prescriptions (MVP)
+ * Appointments (MVP)
+ * Messages (MVP)
+ * Claims (MVP)
+ * Debts *(future)*
+ * Letters & documents *(future)*
+ * Payments *(future)*
+ * Vaccine/medical records *(future)*
+ * Travel pay *(future)*
+* **Guidelines for module inclusion:**
+A feature is appropriate for inclusion as an Activity module on the home screen when it:
+ * Has an “in-flight” status (ex: an open Claim, an upcoming Appointment)
+ * Has an action that is available for the user to take (ex: a refillable Prescription, an unread Message)
+
+
+#### Zone 3: About you:
+
+* **What it is:** A personalized, high-level snapshot of the individual Veteran at VA.
+ * **Module appearance logic:** Fixed appearance.
+* **What lives in this zone:**
+ * Branch of Service/Veteran Status card (MVP)
+ * Disability rating & monthly payment (MVP)
+* **Guidelines for module inclusion:**
+Information is appropriate for inclusion on the home screen within About you when it:
+ * **Is** or **provides access** to information relating to who the individual Veterans *is within VA* as opposed to relating to a specific activity or task
+ * Contains high-level data about the individual Veteran that changes infrequently
+
+
+#### Zone 4: VA resources:
+
+* **What it is:** Links to support/tools that are of universal interest to Veterans and a space for announcements from VA.
+ * **Module appearance logic:** Fixed appearance
+* **What lives in this zone:**
+ * Contact us (MVP)
+ * Find a VA Location (MVP)
+ * Banner space for VA announcements (MVP)
+ * Banner appearance is optional—use when needed.
+ * Display one banner at a time.
+ * Banner announcements should be of interest to all Veterans, and timely.
+* **Guidelines for module inclusion:**
+Information is appropriate for inclusion on the home screen within the VA resources section when it:
+ * Is a tool or information that is relevant to a general audience, and
+ * It does not fit within the Benefits, Health or Payment categories.
+
+
+### Screen Template
+The Home screen uses the [Category screen template](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/Flagship%20design%20library/Templates/ScreenTypes#category-landing-screen).
+
+
+### Resources
+* [Figma file: Home screen 2.0 Shipped File](https://www.figma.com/design/ddMWiCQCfmUKFhMcYG9fYv/Home-2.0---%F0%9F%9A%A2-Shipped---VA-Mobile?m=auto&node-id=1410-20598&t=a610026nBu9afD1A-1) (includes happy path as well as design for loading states, errors, and alternate statuses)
+* Mural: [Home screen 2.0 Appearance logic for error handling and edge cases](https://app.mural.co/t/adhoccorporateworkspace2583/m/adhoccorporateworkspace2583/1704381519703/cd6d78c5824a5fb0cc8b26597f0ad271072df8f2?wid=0-1705962128474)
+
+### Design Principles
+TBD (discussion of the role of surface and elevation in the home screen’s design)
+
diff --git a/VAMobile/documentation/docs/Flagship design library/Templates/ScreenTypes.md b/VAMobile/documentation/docs/Flagship design library/Templates/ScreenTypes.md
index 07948e4ddf5..0b50b46062e 100644
--- a/VAMobile/documentation/docs/Flagship design library/Templates/ScreenTypes.md
+++ b/VAMobile/documentation/docs/Flagship design library/Templates/ScreenTypes.md
@@ -16,26 +16,10 @@ The VA mobile app has 5 main screen types that fall into two categories:
## Hierarchical screens
-### Home screen
-
-
-* **Definition:** The Home screen is the initial/default screen of the app. It sits at the top level of the hierarchical navigation and summarizes a Veteran's interactions with the VA mobile app. It also provides access to the Veteran's profile information.
-
- The Home screen contains several zones of variable and fixed content:
- - **Activity:** Personalized modules that summarize "in-flight" activities and provide a secondary entry point to app features (variable appearance).
- - **About you:** Personalized high-level data, including the Veteran Status card (fixed appearance).
- - **VA resources:** General interest/evergreen links to VA tools as well as a banner space for announcements (fixed appearance).
-
- The Home screen displays the tab bar and a link to the Veteran Crisis line. It does not display a back button.
-- **Screen transition:** Screen transition between home and categories is top-level peer (fade through).
-- **Scroll behavior:** Content scrolls if it exceeds the panel height.
-- **Resources:**
- - [Figma file: Home screen template](https://www.figma.com/design/cdp7Be4UdYesq9fXeqaOgt/Navigation-2.0-Screen-Templates---%F0%9F%9A%A2-Shipped---VA-Mobile?node-id=7733-11182&t=GsZrpZDn1qDXDTr0-4)
-
### Category landing screen
-- **Definition:** Category screens sit at the top level of the hierarchical navigation (and are peers to the Home screen), grouping features of a similar type. Each category screen contains permanent entry points to features and variable description text when applicable. Features are grouped into subsections if the number of features in a category exceeds 6. Displays the tab bar and a link to the Veteran Crisis line. It does not display a back button.
+- **Definition:** The Category landing screen template is used by the navigation categories at the top of the app's hierarchy: Health, Benefits, and Payments. These navigation category landing screens group features of a similar type, providing permanent entry points to features and variable description text for each feature when applicable. The app's Home screen also uses this template, but has a special set of rules that distinguish it from the other top-level categories ([see Home Screen for a more detailed description](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/Flagship%20design%20library/Templates/Home)). The category landing screen template displays the tab bar and a link to the Veteran Crisis line. It does not display a back button.
- **Screen transition:** Screen transition between categories is top-level peer (fade through).
- **Scroll behavior:** Content scrolls if it exceeds the panel height.
- Screen title scroll behavior:
@@ -49,7 +33,7 @@ The VA mobile app has 5 main screen types that fall into two categories:
### Feature landing screen
-- **Definition:** The “home” screen of a feature. Features are parent sections with multiple children that generally live within a category. A complex feature (like pharmacy or secure messaging) can also have subsections. Displays the tab bar and a descriptive back button.
+- **Definition:** The “home” screen of a feature. Features are parent sections with multiple children that generally live within a category. A complex feature (like Prescriptions or Messages) can also have subsections. Displays the tab bar and a descriptive back button.
- **Screen transition:** Horizontal (pushing on & off from right).
- **Scroll behavior:** Content scrolls if it exceeds the panel height.
- Screen title scroll behavior:
diff --git a/VAMobile/documentation/docs/Flagship design library/Templates/image.png b/VAMobile/documentation/docs/Flagship design library/Templates/image.png
new file mode 100644
index 00000000000..fbcf1e907af
Binary files /dev/null and b/VAMobile/documentation/docs/Flagship design library/Templates/image.png differ
diff --git a/VAMobile/documentation/docs/Flagship design library/_category_.json b/VAMobile/documentation/docs/Flagship design library/_category_.json
index d4b4c000bbc..2a54e555dfd 100644
--- a/VAMobile/documentation/docs/Flagship design library/_category_.json
+++ b/VAMobile/documentation/docs/Flagship design library/_category_.json
@@ -1,4 +1,4 @@
{
"label": "Flagship design library",
- "position": 2
+ "position": 3
}
diff --git a/VAMobile/documentation/docs/Operations/Releases/index.md b/VAMobile/documentation/docs/Operations/Releases/index.md
index 84d77fb9317..93c0124cff1 100644
--- a/VAMobile/documentation/docs/Operations/Releases/index.md
+++ b/VAMobile/documentation/docs/Operations/Releases/index.md
@@ -4,4 +4,71 @@ sidebar_position: 1
---
## Release Cycle
+
Because VSP's Collaboration Cycle is designed for web features, the VA Mobile App team is going to leverage parts of the process that make sense for mobile and create other quality control processes where it doesn't. For example, the VA Mobile App team is creating its own Accessibility review that is tailored to mobile devices. These deviations will be noted within the [mobile product documentation](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/products/va-mobile-app/product).
+
+## Release Calendar
+
+### 2024
+
+| Sprint | Start Date | End Date | Release Date | QA Sign Off Due Date | PO Release Sign Off Date | App Review Submission Date | Release Number |
+| ------ | ---------- | -------- | ------------ | -------------------- | ------------------------ | -------------------------- | -------------- |
+| 88 | 1/3/24 | 1/16/24 | 1/30/24 | 1/19/24 | 1/23/24 | 1/24/24 | 2.20.0 |
+| 89 | 1/17/24 | 1/30/24 | 2/13/24 | 2/2/24 | 2/6/24 | 2/7/24 | 2.21.0 |
+| 90 | 1/31/24 | 2/13/24 | 2/27/24 | 2/16/24 | 2/20/24 | 2/21/24 | 2.22.0 |
+| 91 | 2/14/24 | 2/27/24 | 3/12/24 | 3/1/24 | 3/5/24 | 3/6/24 | 2.23.0 |
+| 92 | 2/28/24 | 3/12/24 | 3/26/24 | 3/15/24 | 3/19/24 | 3/20/24 | 2.24.0 |
+| 93 | 3/13/24 | 3/26/24 | 4/9/24 | 3/29/24 | 4/2/24 | 4/3/24 | 2.25.0 |
+| 94 | 3/27/24 | 4/9/24 | 4/23/24 | 4/12/24 | 4/16/24 | 4/17/24 | 2.26.0 |
+| 95 | 4/10/24 | 4/23/24 | 5/7/24 | 4/26/24 | 4/30/24 | 5/1/24 | 2.27.0 |
+| 96 | 4/24/24 | 5/7/24 | 5/21/24 | 5/10/24 | 5/14/24 | 5/15/24 | 2.28.0 |
+| 97 | 5/8/24 | 5/21/24 | 6/4/24 | 5/24/24 | 5/28/24 | 5/29/24 | 2.29.0 |
+| 98 | 5/22/24 | 6/4/24 | 6/18/24 | 6/7/24 | 6/11/24 | 6/12/24 | 2.30.0 |
+| 99 | 6/5/24 | 6/18/24 | 7/2/24 | 6/21/24 | 6/25/24 | 6/26/24 | 2.31.0 |
+| 100 | 6/19/24 | 7/2/24 | 7/16/24 | 7/5/24 | 7/9/24 | 7/10/24 | 2.32.0 |
+| 101 | 7/3/24 | 7/16/24 | 7/30/24 | 7/19/24 | 7/23/24 | 7/24/24 | 2.33.0 |
+| 102 | 7/17/24 | 7/30/24 | 8/13/24 | 8/2/24 | 8/6/24 | 8/7/24 | 2.34.0 |
+| 103 | 7/31/24 | 8/13/24 | 8/27/24 | 8/16/24 | 8/20/24 | 8/21/24 | 2.35.0 |
+| 104 | 8/14/24 | 8/27/24 | 9/10/24 | 8/30/24 | 9/3/24 | 9/4/24 | 2.36.0 |
+| 105 | 8/28/24 | 9/10/24 | 9/24/24 | 9/13/24 | 9/17/24 | 9/18/24 | 2.37.0 |
+| 106 | 9/11/24 | 9/24/24 | 10/8/24 | 9/27/24 | 10/1/24 | 10/2/24 | 2.38.0 |
+| 107 | 9/25/24 | 10/8/24 | 10/22/24 | 10/11/24 | 10/15/24 | 10/16/24 | 2.39.0 |
+| 108 | 10/9/24 | 10/22/24 | 11/5/24 | 10/25/24 | 10/29/24 | 10/30/24 | 2.40.0 |
+| 109 | 10/23/24 | 11/5/24 | 11/19/24 | 11/8/24 | 11/12/24 | 11/13/24 | 2.41.0 |
+| 110 | 11/6/24 | 11/19/24 | 12/3/24 | 11/22/24 | 11/26/24 | 11/27/24 | 2.42.0 |
+| 111 | 11/20/24 | 12/3/24 | 12/17/24 | 12/6/24 | 12/10/24 | 12/11/24 | 2.43.0 |
+| 112 | 12/4/24 | 12/17/24 | n/a | n/a | n/a | n/a | Freeze |
+
+### 2025
+
+| Sprint | Sprint Start | Sprint end (issue workflow run the following day) | Release Date | QA Sign Off Date | Release Sign Off Due Date (/approve command) | App Review Submission Date | Release Number |
+| ------ | ---------- | -------- | ------------ | -------------------- | ------------------------ | -------------------------- | -------------- |
+| 113 | 12/18/24 | 12/31/24 | n/a | n/a | n/a | n/a | Freeze |
+| 114 | 1/1/25 | 1/14/25 | 1/28/25 | 1/17/25 | 1/21/25 | 1/22/25 | 2.44.0 |
+| 115 | 1/15/25 | 1/28/25 | 2/11/25 | 1/31/25 | 2/4/25 | 2/5/25 | 2.45.0 |
+| 116 | 1/29/25 | 2/11/25 | 2/25/25 | 2/14/25 | 2/18/25 | 2/19/25 | 2.46.0 |
+| 117 | 2/12/25 | 2/25/25 | 3/11/25 | 2/28/25 | 3/4/25 | 3/5/25 | 2.47.0 |
+| 118 | 2/26/25 | 3/11/25 | 3/25/25 | 3/14/25 | 3/18/25 | 3/19/25 | 2.48.0 |
+| 119 | 3/12/25 | 3/25/25 | 4/8/25 | 3/28/25 | 4/1/25 | 4/2/25 | 2.49.0 |
+| 120 | 3/26/25 | 4/8/25 | 4/22/25 | 4/11/25 | 4/15/25 | 4/16/25 | 2.50.0 |
+| 121 | 4/9/25 | 4/22/25 | 5/6/25 | 4/25/25 | 4/29/25 | 4/30/25 | 2.51.0 |
+| 122 | 4/23/25 | 5/6/25 | 5/20/25 | 5/9/25 | 5/13/25 | 5/14/25 | 2.52.0 |
+| 123 | 5/7/25 | 5/20/25 | 6/3/25 | 5/23/25 | 5/27/25 | 5/28/25 | 2.53.0 |
+| 124 | 5/21/25 | 6/3/25 | 6/17/25 | 6/6/25 | 6/10/25 | 6/11/25 | 2.54.0 |
+| 125 | 6/4/25 | 6/17/25 | 7/1/25 | 6/20/25 | 6/24/25 | 6/25/25 | 2.55.0 |
+| 126 | 6/18/25 | 7/1/25 | 7/15/25 | 7/4/25 | 7/8/25 | 7/9/25 | 2.56.0 |
+| 127 | 7/2/25 | 7/15/25 | 7/29/25 | 7/18/25 | 7/22/25 | 7/23/25 | 2.57.0 |
+| 128 | 7/16/25 | 7/29/25 | 8/12/25 | 8/1/25 | 8/5/25 | 8/6/25 | 2.58.0 |
+| 129 | 7/30/25 | 8/12/25 | 8/26/25 | 8/15/25 | 8/19/25 | 8/20/25 | 2.59.0 |
+| 130 | 8/13/25 | 8/26/25 | 9/9/25 | 8/29/25 | 9/2/25 | 9/3/25 | 2.60.0 |
+| 131 | 8/27/25 | 9/9/25 | 9/23/25 | 9/12/25 | 9/16/25 | 9/17/25 | 2.61.0 |
+| 132 | 9/10/25 | 9/23/25 | 10/7/25 | 9/26/25 | 9/30/25 | 10/1/25 | 2.62.0 |
+| 133 | 9/24/25 | 10/7/25 | 10/21/25 | 10/10/25 | 10/14/25 | 10/15/25 | 2.63.0 |
+| 134 | 10/8/25 | 10/21/25 | 11/4/25 | 10/24/25 | 10/28/25 | 10/29/25 | 2.64.0 |
+| 135 | 10/22/25 | 11/4/25 | 11/18/25 | 11/7/25 | 11/11/25 | 11/12/25 | 2.65.0 |
+| 136 | 11/5/25 | 11/18/25 | 12/2/25 | 11/21/25 | 11/25/25 | 11/26/25 | 2.66.0 |
+| 137 | 11/19/25 | 12/2/25 | 12/16/25 | 12/5/25 | 12/9/25 | 12/10/25 | 2.67.0 |
+| 138 | 12/3/25 | 12/16/25 | 12/30/25 | 12/19/25 | 12/23/25 | 12/24/25 | 2.68.0 |
+| 139 | 12/17/25 | 12/30/25 | 1/13/26 | 1/2/26 | 1/6/25 | 1/7/26 | 2.69.0 |
+
+For information about the technical release process, please see the [release process](release-process/) documentation.
diff --git a/VAMobile/documentation/docs/Operations/_category_.json b/VAMobile/documentation/docs/Operations/_category_.json
index 16fb9d4ac89..05d3ec5b360 100644
--- a/VAMobile/documentation/docs/Operations/_category_.json
+++ b/VAMobile/documentation/docs/Operations/_category_.json
@@ -1,4 +1,4 @@
{
"label": "Operations",
- "position": 6
+ "position": 8
}
diff --git a/VAMobile/documentation/docs/Product/_category_.json b/VAMobile/documentation/docs/Product/_category_.json
index 6b2c3ee3e58..b1badb0e9b3 100644
--- a/VAMobile/documentation/docs/Product/_category_.json
+++ b/VAMobile/documentation/docs/Product/_category_.json
@@ -1,4 +1,4 @@
{
"label": "Product",
- "position": 3
+ "position": 4
}
diff --git a/VAMobile/documentation/docs/QA/HowWeWork/index.md b/VAMobile/documentation/docs/QA/HowWeWork/index.md
index d0e7100eb71..804f75b24a8 100644
--- a/VAMobile/documentation/docs/QA/HowWeWork/index.md
+++ b/VAMobile/documentation/docs/QA/HowWeWork/index.md
@@ -11,11 +11,11 @@ We typically provide that information by signing off that we've tested the softw
Good software testing happens with the keen awareness that it is impossible to "find all the bugs" (limitations in time, resources, tooling, and knowledge; not to mention inevitable changes in data, processes, software, and systems our software integrates with). Therefore, a highly-functional QA team knows when to stop vs continue working on a given task. On our team:
-We stop preparing for testing activities when:
+### We stop preparing for testing activities when:
* we are sufficiently aware of how our software and interacting systems can break and what kinds of problems are the most important to find, and
* we have what we need (tools, data prep, etc) to be able to look for those problems.
-We stop testing when:
+### We stop testing when:
* we've examined the product commensurate to the risk it contains,
* we've met our testing standards, and
* we've expressed our testing plan and results, along with quality assessments, clearly.
@@ -23,4 +23,4 @@ We stop testing when:
## Common misconception: QA makes the final decision
QA is one of the last roles, if not the last role, involved in a given ticket; on some teams they are given gatekeeping authority over what software is released.
-Within the VA mobile app space, PMs (in conjunction with stakeholders) make the final decision for what goes out the door. That is often explicit (such as new releases or new features) and, on a high-trust team, sometimes implicit (ex: QA stating a ticket meets the PM-set ACs does not need further review before merging into develop)
\ No newline at end of file
+Within the VA mobile app space, PMs (in conjunction with stakeholders) make the final decision for what goes out the door. That is often explicit (such as new releases or new features) and, on a high-trust team, sometimes implicit (ex: QA stating a ticket meets the PM-set ACs does not need further review before merging into develop)
diff --git a/VAMobile/documentation/docs/QA/QualityAssuranceProcess/Testing Summary.md b/VAMobile/documentation/docs/QA/QualityAssuranceProcess/Testing Summary.md
new file mode 100644
index 00000000000..66a1ce51167
--- /dev/null
+++ b/VAMobile/documentation/docs/QA/QualityAssuranceProcess/Testing Summary.md
@@ -0,0 +1,32 @@
+---
+title: Testing summary
+---
+# Why a testing summary?
+
+QA must [clearly communicate their test plan, results, and quality assessment](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/docs/QA/HowWeWork/index.md#we-stop-testing-when) to fulfill their role of providing stakeholders with enough information to decide whether to release software.
+
+For small, incremental, low-risk, simple changes, the documentation of the test plan itself (running a set of cases, which passed/failed, and any bug reports written) is often sufficient to meet decision-making needs. There's no grand narrative to communicate, for fixing a typo in a button label.
+
+For larger, 'big bang', higher-risk, complex changes, (which should be [avoided whenever possible](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/Engineering/FrontEnd/DevelopmentBestPractices#scoping-tickets)), just a test plan is typically insufficient to communicate your testing work and its results. A testing summary can also be important when working with multiple teams (who likely have differing expectations about what, how, and why QA tests what we test) to support the secondary goal of "avoiding surprising the implementation team about what's being released."
+
+# What's in a testing summary
+
+All testing summaries include:
+- Basic identifying information: QA Engineer's name, name of feature under test (and link(s) to key feature documentation, such as a feature epic), and the date when the testing summary was written
+- Link to full test plan(s) and result(s), manual and automated
+- List of bug(s) found and fixed, pre-release (and links to bug reports for those bugs)
+- List of bug(s) found and NOT fixed, pre-release (and links to bug reports for those bugs)
+- Testing narrative which includes:
+ - Whether all planned & desired testing was completed, and if not, an explanation why
+ - What risks QA assessed (in the code itself; in the composition or operations of the implementing team; in the upstream/downstream systems the code integrates with, and visibility/lack thereof into their operations; etc)
+ - How QA attempted to mitigate those risks
+ - Where, if anywhere, QA anticipates problems after release
+- Any other information QA deems relevant to communicate their quality assessment
+
+The VA H&B app flagship team, and the experience teams who work with the mobile app platform team for QA, have a lot of variety in documentation: where they document feature information, what they document, different repos in which they work through tickets, etc. QA should work with the PM responsible to establish where to write/save a testing summary.
+
+Because there is no standard place to publish these summaries, there's also no single template (ex: github ticket template) to create them. Here's an [example summary](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/products/va-mobile-app/features/design-personalization/qa/findings.md) in the flagship product repo that can be used as a helpful starting point.
+
+## When is a testing summary written
+
+A testing summary (implicit in the name) is written [when testing is completed, but before the release of the software under test.](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/QA/QualityAssuranceProcess/working-with-others#testing-qa)
diff --git a/VAMobile/documentation/docs/QA/QualityAssuranceProcess/working-with-others.md b/VAMobile/documentation/docs/QA/QualityAssuranceProcess/working-with-others.md
index 794af8d9c81..651aa8a32ab 100644
--- a/VAMobile/documentation/docs/QA/QualityAssuranceProcess/working-with-others.md
+++ b/VAMobile/documentation/docs/QA/QualityAssuranceProcess/working-with-others.md
@@ -25,7 +25,7 @@ While QA does a lot of our work towards the end of a ticket's lifecycle (testing
| **Involvement** | **How to pull us in** | **Artifacts QA delivers** |
| --- | --- | --- |
| High-level review or feature planning | Included on meeting requests, tagged in Slack/invited to relevant channels | n/a |
-| Manual testing | Engineering implentation tickets assigned to appropriate QA Engineer, after passing PR review | Per-ticket: Completed ticket will include planned & completed testing (comment, or TestRail link, as appropriate). Per-feature: QA Testing Summary. |
+| Manual testing | Engineering implentation tickets assigned to appropriate QA Engineer, after passing PR review | Per-ticket: Completed ticket will include planned & completed testing (comment, or TestRail link, as appropriate). Per-feature: [Testing Summary](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/QA/QualityAssuranceProcess/Testing%20Summary). |
| Automated testing | Engineering detox script addition/updates assigned to appropriate QA Engineer, after passing PR review | PRs or tickets will include QA review |
-NB: During testing, towards the end of QA review, the UX team does UX review (visual, interaction, and content review). For details, reference [the UX team documentation on the UX QA process](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/UX/How-We-Work/designing-ui#qa).
\ No newline at end of file
+NB: During testing, towards the end of QA review, the UX team does UX review (visual, interaction, and content review). For details, reference [the UX team documentation on the UX QA process](https://department-of-veterans-affairs.github.io/va-mobile-app/docs/UX/How-We-Work/designing-ui#qa).
diff --git a/VAMobile/documentation/docs/QA/_category_.json b/VAMobile/documentation/docs/QA/_category_.json
index d80b1470fb7..96adc258eb6 100644
--- a/VAMobile/documentation/docs/QA/_category_.json
+++ b/VAMobile/documentation/docs/QA/_category_.json
@@ -1,4 +1,4 @@
{
"label": "QA",
- "position": 5
-}
\ No newline at end of file
+ "position": 7
+}
diff --git a/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md b/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md
index e17c3667d41..ff717f20798 100644
--- a/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md
+++ b/VAMobile/documentation/docs/UX/Foundations/Information-Architecture.md
@@ -31,7 +31,6 @@ References:
* Removing a feature and/or screen
* Changing the UX of global navigational elements (i.e. tab bar/bottom navigation, top bar, including treatments for back buttons, contextual actions and screen titles)
-
## IA documentation
Understanding what’s guiding the app’s current information architecture and make future decisions that are in line with the existing organization, navigation, labeling, and indexing systems.
@@ -51,16 +50,16 @@ The VA Health and Benefits app’s IA contains four top level categories: Home,
* **Home:** The app’s default screen—displays a combined, personalized view of the information (and tasks) most relevant to the individual Veteran from across the VA, plus persistent access to general VA info (ex: contact and location finder) and lesser used features like Profile and Settings.
* **Profile (Subcategory):** Infrequently updated items like personal information (such as contact information, military information, DOB) that isn’t specific to a single category and app settings.
* **Health:** All health-related features and statuses.
- * Features: Appointments, Pharmacy, Medical records, Messaging.
+ * Features: Appointments, Prescriptions, VA vaccine records, Messaging (future: Medical records).
* **Benefits:** All benefit-related features and statuses that are not health-related.
- * Features: Disability rating, Claims, Education, VA Letters
-* **[Payments]:** A unified section for managing financial information from across the VA.
- * Features: Benefit payments, medical copays, bills, travel reimbursements, direct deposit information.
+ * Features: Disability rating, Claims, VA Letters (future: Education)
+* **Payments:** A unified section for managing financial information from across the VA.
+ * Features: VA payment history, direct deposit information (future: Medical copays, Bills, Travel reimbursements).
### Adding new items to the app’s Information Architecture
-1. **A feature’s placement within the app’s navigation and taxonomy should take user mental models, business goals, and the feature type into account.** [Determining Navigation and Information Architecture Placement for New VA Mobile App Features](https://docs.google.com/document/d/1XQcYxnCifloaBFNKL2C9JNS7KIj6wEhb4VokPGxBZU8/edit#) is a guide intended to help teams decide where a new feature belongs in this app’s sitemap and navigation model.
+1. **A feature’s placement within the app’s navigation and taxonomy should take user mental models, business goals, and the feature type into account.** [Determining Navigation and Information Architecture Placement for New VA Mobile App Features](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/products/va-mobile-app/ux-design/information-architecture/adding-new-features.md) is a guide intended to help teams decide where a new feature belongs in this app’s sitemap and navigation model.
1. **Always try to find a placement in an existing category first** before proposing a new top-level category for a feature. Confirm new category names and contents with card sort research before adding to the app.
1. **Within a category, keep the hierarchy as flat as possible** in terms of screens (limit the levels it’s possible to drill down through in order to get to child screens), but without inlcuding too many options on a single screen.
1. **If there are many features within a category, group the features and label the groups** at category level before introducing additional levels into the screen hierarchy—this helps avoid cognitive overload.
@@ -71,6 +70,4 @@ The VA Health and Benefits app’s IA contains four top level categories: Home,
The VA Health and Benefits app’s Information Architecture and navigation model are based on the findings and output from a multi-stage, collaborative and cross-functional design and research process: [Information Architecture and Navigation - High Level Project Summary](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/products/va-mobile-app/ux-design/information-architecture-navigation/High%20Level%20Project%20Summary.md)
* [**Phase I:** Two rounds of card sorting](https://github.com/department-of-veterans-affairs/va.gov-team/tree/master/products/va-mobile-app/ux-research/information-architecture) (open and closed) with Veterans
* [**Phase II:** Navigation model design exploration](https://github.com/department-of-veterans-affairs/va.gov-team/tree/master/products/va-mobile-app/ux-design/information-architecture-navigation#phase-ii---navigation-model-exploration--implementation), audit and comparative analysis
-* [**Phase III:** Evaluative testing](https://github.com/department-of-veterans-affairs/va.gov-team/tree/master/products/va-mobile-app/ux-research/usability-testing/new%20navigation%20usability) with Veterans, including a usability study of the proposed navigation model and sitemap reflected through a low-fidelity prototype
-
-
+* [**Phase III:** Evaluative testing](https://github.com/department-of-veterans-affairs/va.gov-team/tree/master/products/va-mobile-app/ux-research/usability-testing/new%20navigation%20usability) with Veterans, including a usability study of the proposed navigation model and sitemap reflected through a low-fidelity prototype
\ No newline at end of file
diff --git a/VAMobile/documentation/docs/UX/How-We-Work/figma-permissions.md b/VAMobile/documentation/docs/UX/How-We-Work/figma-permissions.md
index 158174a5511..a6aa01e8ad8 100644
--- a/VAMobile/documentation/docs/UX/How-We-Work/figma-permissions.md
+++ b/VAMobile/documentation/docs/UX/How-We-Work/figma-permissions.md
@@ -12,13 +12,13 @@ All of our Figma files are set so “**anyone with the link can view**.” If yo
### Adding members or guests to the team
1. Admin, Owner, or Editor [invites new Member or Guest to VA Mobile App team](https://help.figma.com/hc/en-us/articles/360040453113-Add-members-or-guests-to-an-organization) as an Editor or Viewer.
- 1. **Members** must have an Ad Hoc email address and can be set as an Editor or Viewer.
- 2. **Guests** will not have an Ad Hoc email address and will automatically be set as a Viewer-restricted.
+ 1. **Members** must have an Ad Hoc email address and can be set as an Editor or Viewer. Typically, only designers on the VA Mobile App team should be Editors. All other team members should be Viewers.
+ 2. **Guests** will not have an Ad Hoc email address and will automatically be set as a Viewer.
2. **Member** or **Guest** accepts the invitation to join the VA Mobile App team.
3. In Figma, a **Member** or **Guest** will need to switch to the Ad Hoc organization in the top left corner, click on All Teams, and open the VA Mobile App team’s space.
4. **Member** or **Guest** can now see all of our Figma files.
3. **Members** will be able to Edit or View files depending on their permissions.
- 4. **Guests** will be able to view files and use the library in their private drafts.
+ 4. **Guests** will be able to view files and use the library in their private drafts. If a guest needs edit access to a particular file, they can be added as an Editor in that file.
#### Team permissions by role
diff --git a/VAMobile/documentation/docs/UX/_category_.json b/VAMobile/documentation/docs/UX/_category_.json
index 6a6d7e815af..036822b2bde 100644
--- a/VAMobile/documentation/docs/UX/_category_.json
+++ b/VAMobile/documentation/docs/UX/_category_.json
@@ -1,4 +1,4 @@
{
"label": "UX",
- "position": 4
+ "position": 6
}
diff --git a/VAMobile/documentation/docs/contributing.md b/VAMobile/documentation/docs/contributing.md
new file mode 100644
index 00000000000..3b26a9a724a
--- /dev/null
+++ b/VAMobile/documentation/docs/contributing.md
@@ -0,0 +1,47 @@
+---
+title: Contributing
+sidebar_position: 2
+---
+
+## VA Health & Benefits: Mobile & Web Collaboration
+
+### Collaboration Phases
+
+This model shows how collaboration between web and mobile teams evolves as web teams develop more experience working in the mobile app and add mobile specific resources to their teams.
+
+**The outcome is such that an Experience team owns one or multiple Veteran-facing experiences across modalities – mobile app(s), va.gov, and future modalities.**
+
+Any support with Experience teams will be dependent on prioritization.
+
+### Definitions
+
+Web team: An OCTO-led team that owns Veteran-facing va.gov experience(s).
+
+Mobile team: An OCTO-led team that owns all experiences in VA: Health and Benefits mobile app.
+
+Experience team: A yet-to-exist team that owns Veteran-facing experiences across all modalities: native mobile apps, va.gov, and current/future technologies.
+
+| Phase A: Mobile works independently | Phase B: Web experience advises mobile | Phase C: Mobile and Web split responsibilities | Phase D: Mobile advises web experience team** | Phase E: Web team works independently and become an Experience team. |
+| --- | --- | --- | --- | --- |
+| VAHB Mobile App team does all of the implementation and maintenance work | VAHB Mobile App team does all of the implementation and maintenance work | Web experience team works to identify, strategize, and design initiatives
VAHB builds/ships, measures and maintains. | Web experience team does all of the implementation and maintenance work
VAHB may lend resources as needed | **Experience** team does **all** the implementation and maintenance work |
+| | Web experience team advises mobile team as experience subject matter experts | VAHB team advises the experience team | VAHB team advises the experience team, runs QA, and reviews code. | VAHB runs QA and reviews code prior to submission and release |
+| Mobile OCTO team POs manage initiatives | Mobile OCTO team POs manage initiatives | Experience OCTO POs manage initiatives | Experience OCTO POs manage initiatives | Experience OCTO POs manage initiatives |
+
+### **_How an initiative will work in detail_**
+
+Transition Phase C (Mobile and Web split responsibilities) represents the next available stage of collaboration that web and mobile teams can move to while most mobile expertise is still within the mobile team.
+
+#### Success measures for Phase C
+
+1. Web teams move through the strategy and design phases with minimal support from the mobile team.
+2. The mobile team implement requirements and designs that the web experience team created with minimal rework.
+
+**What needs to be done to move on to the next step:**
+
+| Initiative Steps | Web Application Team | VAHB Mobile Team |
+|--------------------|----------------------|------------------|
+| Step 0: Identify | Create a [project brief](https://github.com/department-of-veterans-affairs/va-mobile-app/issues/new?template=feature-request.yml) that roughly lays out abstract requirements, risks, and major players. | - Mobile reviews the brief and gives feedback on mobile specific elements. - This is the review gate to consider if this feature or update is appropriate for VAHB. |
+| Step 1: Strategize | - Web team drafts product strategy and decides on requirements. - A formal kickoff could be scheduled at this stage to lay out how these teams will collaborate with each other, timelines, and points of contact. - Web team creates tickets on their own board for research and design. | - Mobile reviews and gives feedback on mobile specific considerations. - Mobile will prioritize resources to consult on Step 2 |
+| Step 2: Design | - Evaluative research, design and product ideation is done in order to define the first version of a feature. Finalize what is in and what isn’t. What does it look like? - Web creates an implementation plan and submits a [testplan request](https://github.com/department-of-veterans-affairs/va-mobile-app/issues/new?template=QA_Test_Plan.md) to the mobile QA team. | - Mobile will consult on research, design, data, content, accessibility, etc - Mobile reviews implementation plan - Mobile prioritizes implementation |
+| Step 3: Build/Ship | - Web shares test accounts and assists with testing - Web assists with providing app store and what’s new content | - Mobile copies over engineering tickets and test plans - Mobile points engineering and QA tickets - Mobile implements - Mobile leads all necessary steps to include in whole app release process, including phased release, app store info, and what’s new content |
+| Step 4: Measure | - Web assists with comparing web and mobile analytics | - Mobile monitors initial launch success |
diff --git a/VAMobile/documentation/docs/intro.md b/VAMobile/documentation/docs/intro.md
index 237a9e84692..d6bc80eef7f 100644
--- a/VAMobile/documentation/docs/intro.md
+++ b/VAMobile/documentation/docs/intro.md
@@ -3,18 +3,20 @@ title: Intro to the VA Mobile App
sidebar_position: 1
---
-# Intro to the VA Mobile App
+:::info Release Freeze Information
+The VA: Health and Benefits mobile app will be participating in a release freeze from December 17, 2024 until January 28, 2025, to accommodate the availability of team members around the winter holiday. This freeze effectively skips two normal release cycles, as the app is published on a bi-weekly basis. While releases will be frozen, code is not. Normal work and merging into the `develop` branch can continue as planned, but the code will be held back from the app stores until the freeze is lifted.
+:::
-
-
+
## Background
+
Nearly 40% of all traffic to VA.gov comes from users on their mobile devices. This traffic is typically driven by users that want to complete quick transactions, such as viewing Claims Status or Facility Locator.
The VA: Health and Benefits App team has a hypothesis, validated by user research, that native functionality in a mobile app will allow Veterans to more easily complete key transactions across VA Health and Benefits services.
-
## Download the app
+
diff --git a/VAMobile/documentation/static/img/home/vamobile-home-zones.png b/VAMobile/documentation/static/img/home/vamobile-home-zones.png
new file mode 100644
index 00000000000..be1e7646e78
Binary files /dev/null and b/VAMobile/documentation/static/img/home/vamobile-home-zones.png differ
diff --git a/VAMobile/e2e/tests/Appeals.e2e.ts b/VAMobile/e2e/tests/Appeals.e2e.ts
index e28247e64d0..047591a25f1 100644
--- a/VAMobile/e2e/tests/Appeals.e2e.ts
+++ b/VAMobile/e2e/tests/Appeals.e2e.ts
@@ -95,6 +95,7 @@ describe('Appeals', () => {
await device.launchApp({ newInstance: false })
await device.disableSynchronization()
await element(by.id(CommonE2eIdConstants.GO_TO_VA_GOV_LINK_ID)).tap()
+ await setTimeout(2000)
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('AppealsNeedHelpGoToVAScreen')
diff --git a/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts b/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts
index 46f53fa90cc..4c512d82c3b 100644
--- a/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts
+++ b/VAMobile/e2e/tests/AppointmentsExpanded.e2e.ts
@@ -6,6 +6,37 @@ export const Appointmentse2eConstants = {
GET_DIRECTIONS_ID: 'directionsTestID',
}
+const checkMedicationWording = async ({
+ appointmentType,
+ appointmentStatus,
+ pastAppointment,
+}: {
+ appointmentType: string
+ appointmentStatus: string
+ pastAppointment: boolean
+}) => {
+ if (
+ appointmentType === 'Phone' ||
+ appointmentType === 'CC' ||
+ appointmentType === 'Onsite' ||
+ appointmentType === 'VA'
+ ) {
+ if (
+ appointmentStatus === 'Canceled' ||
+ (!pastAppointment && (appointmentStatus === 'Upcoming' || appointmentStatus === 'Confirmed'))
+ ) {
+ await expect(element(by.text('Prepare for your appointment'))).toExist()
+ await expect(element(by.text('Find a full list of things to bring to your appointment'))).toExist()
+ } else {
+ await expect(element(by.text('Prepare for your appointment'))).not.toExist()
+ await expect(element(by.text('Find a full list of things to bring to your appointment'))).not.toExist()
+ }
+ } else {
+ await expect(element(by.text('Prepare for your appointment'))).not.toExist()
+ await expect(element(by.text('Find a full list of things to bring to your appointment'))).not.toExist()
+ }
+}
+
const checkUpcomingApptDetails = async (
appointmentType: string,
appointmentStatus: string,
@@ -255,6 +286,7 @@ const checkUpcomingApptDetails = async (
await expect(element(by.id('CallTTYTestID')).atIndex(1)).toExist()
}
}
+ await checkMedicationWording({ appointmentType, appointmentStatus, pastAppointment })
await element(by.text('Appointments')).tap()
}
diff --git a/VAMobile/e2e/tests/Claims.e2e.ts b/VAMobile/e2e/tests/Claims.e2e.ts
index 6a0c51bc088..c5ff4d13984 100644
--- a/VAMobile/e2e/tests/Claims.e2e.ts
+++ b/VAMobile/e2e/tests/Claims.e2e.ts
@@ -368,7 +368,7 @@ describe('Claims Screen', () => {
})
it('should tap on the closed tab', async () => {
- await element(by.id('claimsHistoryClosedID')).tap()
+ await element(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_CLOSED_TAB_ID)).tap()
})
it('verify the status details page of closed claim with decision letter', async () => {
diff --git a/VAMobile/e2e/tests/DecisionLetters.e2e.ts b/VAMobile/e2e/tests/DecisionLetters.e2e.ts
index 1bc76c311ee..0d348afbf13 100644
--- a/VAMobile/e2e/tests/DecisionLetters.e2e.ts
+++ b/VAMobile/e2e/tests/DecisionLetters.e2e.ts
@@ -17,6 +17,8 @@ export const DecisionLettersE2eIDConstants = {
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',
}
beforeAll(async () => {
@@ -29,7 +31,7 @@ beforeAll(async () => {
describe('Decision Letters Screen', () => {
it('should tap on the closed tab', async () => {
- await element(by.text('Closed')).tap()
+ await element(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_CLOSED_TAB_ID)).tap()
})
it('verify the status details page of closed claim with decision letter', async () => {
@@ -39,19 +41,18 @@ describe('Decision Letters Screen', () => {
it('verify that the claims letters sceen is displayed', async () => {
await element(by.id(DecisionLettersE2eIDConstants.GET_CLAIMS_LETTER_BUTTON_ID)).tap()
- await expect(element(by.text('Claim letters'))).toExist()
await expect(element(by.id(DecisionLettersE2eIDConstants.DECISION_CLAIM_LETTER_1_ID))).toExist()
await expect(element(by.id(DecisionLettersE2eIDConstants.DECISION_CLAIM_LETTER_2_ID))).toExist()
})
it('should go back to the claims details page', async () => {
- await element(by.text('Claim details')).tap()
+ await element(by.id(DecisionLettersE2eIDConstants.CLAIM_LETTERS_BACK_ID)).tap()
})
it('tap on claims letters', async () => {
- await element(by.text(DecisionLettersE2eIDConstants.CLAIMS_HISTORY_TEXT)).tap()
- await element(by.text('Claims')).tap()
- await element(by.text('Claim letters')).tap()
+ await element(by.id(CommonE2eIdConstants.CLAIMS_DETAILS_BACK_ID)).tap()
+ await element(by.id(CommonE2eIdConstants.CLAIMS_HISTORY_BACK_ID)).tap()
+ await element(by.id(DecisionLettersE2eIDConstants.TO_DECISION_LETTERS_ID)).tap()
})
it('should tap on a claim letter and verify a pdf is displayed', async () => {
diff --git a/VAMobile/e2e/tests/HomeScreen.e2e.ts b/VAMobile/e2e/tests/HomeScreen.e2e.ts
index 5ebda7ba269..49ae00ed6cb 100644
--- a/VAMobile/e2e/tests/HomeScreen.e2e.ts
+++ b/VAMobile/e2e/tests/HomeScreen.e2e.ts
@@ -33,6 +33,7 @@ export const HomeE2eIdConstants = {
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 () => {
@@ -52,7 +53,7 @@ describe('Home Screen', () => {
})
it('should show primary home page header content', async () => {
- await expect(element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT))).toExist()
+ await expect(element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID))).toExist()
await expect(element(by.text(CommonE2eIdConstants.PROFILE_TAB_BUTTON_TEXT))).toExist()
})
@@ -119,6 +120,10 @@ describe('Home Screen', () => {
it('taps home then jumps to appointments from appointments button', async () => {
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))
+ .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()
})
@@ -127,7 +132,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('homeScreenID'))
+ .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID))
.scroll(200, 'down')
await element(by.text(HomeE2eIdConstants.CLAIMS_BUTTON_SUBTEXT_TEXT)).tap()
await expect(element(by.text(CommonE2eIdConstants.CLAIMS_HISTORY_BUTTON_TEXT))).toExist()
@@ -137,7 +142,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('homeScreenID'))
+ .whileElement(by.id(HomeE2eIdConstants.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()
@@ -147,10 +152,10 @@ 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('homeScreenID'))
+ .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID))
.scroll(200, 'down')
await element(by.text(HomeE2eIdConstants.PRESCRIPTIONS_BUTTON_SUBTEXT_TEXT)).tap()
- await expect(element(by.text(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_TEXT))).toExist()
+ await expect(element(by.id(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_ID))).toExist()
})
it('should tap home then show home page about you section content', async () => {
@@ -160,7 +165,7 @@ describe('Home Screen', () => {
} catch (e) {}
await waitFor(element(by.text(HomeE2eIdConstants.MONTHLY_PAYMENT_AMOUNT_TEXT)))
.toBeVisible()
- .whileElement(by.id('homeScreenID'))
+ .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID))
.scroll(200, 'down')
await expect(element(by.text(HomeE2eIdConstants.HOME_PAGE_MILITARY_BRANCH))).toExist()
await expect(element(by.text(HomeE2eIdConstants.VETERAN_STATUS_TEXT))).toExist()
@@ -178,7 +183,7 @@ describe('Home Screen', () => {
it('should show home page VA Resources content', async () => {
await waitFor(element(by.text(HomeE2eIdConstants.LOCATION_FINDER_ROW_TEXT)))
.toBeVisible()
- .whileElement(by.id('homeScreenID'))
+ .whileElement(by.id(HomeE2eIdConstants.HOME_SCREEN_SCROLL_ID))
.scroll(200, 'down')
await expect(element(by.text(HomeE2eIdConstants.LOCATION_FINDER_ROW_TEXT))).toExist()
await expect(element(by.text(HomeE2eIdConstants.CONTACT_VA_ROW_TEXT))).toExist()
@@ -194,11 +199,11 @@ describe('Home Screen', () => {
).toExist()
if (device.getPlatform() === 'android') {
await device.disableSynchronization()
- await element(by.text('800-698-2411')).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).tap()
await setTimeout(5000)
await device.takeScreenshot('ContactVAAndroidCallingScreen')
await device.launchApp({ newInstance: false })
- await element(by.text('TTY: 711')).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).tap()
await setTimeout(5000)
await device.takeScreenshot('ContactVATTYAndroidCallingScreen')
await device.launchApp({ newInstance: false })
@@ -220,7 +225,7 @@ describe('Home Screen', () => {
await element(by.text('Done')).tap()
await waitFor(element(by.text(HomeE2eIdConstants.ANNOUNCEMENT_BANNER_TEXT)))
.toBeVisible()
- .whileElement(by.id('homeScreenID'))
+ .whileElement(by.id(HomeE2eIdConstants.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 529a378e345..1be4a16dddf 100644
--- a/VAMobile/e2e/tests/LoginScreen.e2e.ts
+++ b/VAMobile/e2e/tests/LoginScreen.e2e.ts
@@ -10,11 +10,20 @@ export const LoginE2eIdConstants = {
describe('Login Screen', () => {
it('should show login page content', async () => {
- await waitFor(element(by.id(LoginE2eIdConstants.LOGIN_PAGE_ID)))
- .toExist()
- .withTimeout(60000)
+ try {
+ await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
+ .toExist()
+ .withTimeout(120000)
+ } catch (ex) {
+ await device.uninstallApp()
+ await device.installApp()
+ await device.launchApp({ newInstance: true, permissions: { notifications: 'YES' } })
+ await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
+ .toExist()
+ .withTimeout(60000)
+ }
- await expect(element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT))).toExist()
+ await expect(element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID))).toExist()
await expect(element(by.id(CommonE2eIdConstants.SIGN_IN_BTN_ID))).toExist()
await expect(element(by.id(LoginE2eIdConstants.LOGIN_FIND_VA_BUTTON_ID))).toExist()
const VALogoScreenshot = await element(by.id('VALogo')).takeScreenshot('VALogoLoginScreen')
diff --git a/VAMobile/e2e/tests/Messages.e2e.ts b/VAMobile/e2e/tests/Messages.e2e.ts
index 4c5969e24ae..ea5110971ad 100644
--- a/VAMobile/e2e/tests/Messages.e2e.ts
+++ b/VAMobile/e2e/tests/Messages.e2e.ts
@@ -1,9 +1,6 @@
import { by, device, element, expect, waitFor } from 'detox'
-import { DateTime } from 'luxon'
import { setTimeout } from 'timers/promises'
-import { isIOS } from 'utils/platform'
-
import {
CommonE2eIdConstants,
checkImages,
@@ -13,16 +10,6 @@ import {
toggleRemoteConfigFlag,
} from './utils'
-export async function getDateWithTimeZone(dateString: string) {
- const date = DateTime.fromFormat(dateString, 'LLLL d, yyyy h:m a', { zone: 'America/Chicago' })
- const dateUTC = date.toLocal()
- let dateTime = dateUTC.toLocaleString(Object.assign(DateTime.DATETIME_FULL))
- if (device.getPlatform() === 'android') {
- dateTime = dateTime.replace(' at ', ', ')
- }
- return dateTime
-}
-
export const MessagesE2eIdConstants = {
MESSAGE_1_ID: 'Unread: Martha Kaplan, Md October 26, 2021 Medication: Naproxen side effects',
MESSAGE_1_READ_ID: 'Martha Kaplan, Md October 26, 2021 Medication: Naproxen side effects',
@@ -34,17 +21,17 @@ export const MessagesE2eIdConstants = {
MESSAGE_6_ID: 'Ratana, Narin October 21, 2021 Test: Preparing for your visit',
MESSAGE_7_ID: 'Ratana, Narin September 17, 2021 Education: Good morning to you',
MESSAGE_10_ID: 'Ratana, Narin September 17, 2021 COVID: Test',
- FOLDERS_TEXT: 'Folders',
+ FOLDERS_ID: 'foldersID',
MESSAGES_ID: 'messagesTestID',
REVIEW_MESSAGE_REPLY_ID: 'replyTestID',
ONLY_USE_MESSAGES_TEXT: 'Only use messages for non-urgent needs',
- ATTACHMENTS_BUTTON_TEXT: 'Add Files',
+ 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: 'Select a file',
+ SELECT_A_FILE_ID: 'messagesSelectAFileID',
REPLY_PAGE_TEST_ID: 'replyPageTestID',
START_NEW_MESSAGE_TO_ID: 'to field',
START_NEW_MESSAGE_CATEGORY_ID: 'picker',
@@ -64,12 +51,26 @@ export const MessagesE2eIdConstants = {
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',
+ MOVE_PICKER_ID: 'pickerMoveMessageID',
+ MOVE_PICKER_CANCEL_ID: 'pickerMoveMessageCancelID',
+ MOVE_PICKER_CONFIRM_ID: 'pickerMoveMessageConfirmID',
+ ATTACHMENTS_PAGE_CANCEL_ID: 'attachmentsCancelID',
+ MESSAGES_HELP_CLOSE_ID: 'messagesHelpCloseTestID',
+ MESSAGE_PICKER_CONFIRM_ID: 'messagePickerConfirmID',
+ FOLDERS_BACK_ID: 'foldersBackToMessagesID',
}
const tapItems = async (items: string, type: string) => {
- if (type === 'url' || type === 'map' || type === 'email') {
- await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom')
- }
+ // if (type === 'url' || type === 'map' || type === 'email') {
+ // if (items != 'https://www.va.gov/') {
+ // await element(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID)).scrollTo('bottom')
+ // }
+ // }
+ await waitFor(element(by.text(items)))
+ .toBeVisible()
+ .whileElement(by.id(MessagesE2eIdConstants.VIEW_MESSAGE_ID))
+ .scroll(50, 'down')
await device.disableSynchronization()
await element(by.text(items)).tap()
if (type === 'url' || type === 'map') {
@@ -84,7 +85,6 @@ const tapItems = async (items: string, type: string) => {
await setTimeout(3000)
}
-let dateWithTimeZone
let messageCollapsed
let messageExpanded
@@ -99,7 +99,7 @@ describe('Messages Screen', () => {
it('should match the messages page design', async () => {
await expect(element(by.id(CommonE2eIdConstants.START_NEW_MESSAGE_BUTTON_ID))).toExist()
await expect(element(by.text('Inbox (3)'))).toExist()
- await expect(element(by.text(MessagesE2eIdConstants.FOLDERS_TEXT))).toExist()
+ await expect(element(by.id(MessagesE2eIdConstants.FOLDERS_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.MESSAGE_1_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.MESSAGE_2_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.MESSAGE_3_ID))).toExist()
@@ -117,24 +117,18 @@ describe('Messages Screen', () => {
it('verify message OLDER than 45 days information', async () => {
await element(by.id(MessagesE2eIdConstants.MESSAGES_ID)).scrollTo('top')
await element(by.id(MessagesE2eIdConstants.MESSAGE_2_ID)).tap()
- await expect(element(by.text('This conversation is too old for new replies'))).toExist()
- await expect(
- element(
- by.text(
- 'The last message in this conversation is more than 45 days old. To continue this conversation, start a new message.',
- ),
- ),
- ).toExist()
+ await expect(element(by.id('secureMessagingOlderThan45DaysAlertID'))).toExist()
await expect(element(by.text(MessagesE2eIdConstants.ONLY_USE_MESSAGES_TEXT))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.REVIEW_MESSAGE_REPLY_ID))).not.toExist()
await expect(element(by.id(CommonE2eIdConstants.START_NEW_MESSAGE_BUTTON_ID)))
})
it('verify the message just opened is displayed as read', async () => {
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
await expect(
element(by.id('Diana Persson, Md October 26, 2021 Has attachment COVID: Prepping for your visit')),
).toExist()
+ await expect(element(by.text('Inbox (2)'))).toExist()
})
it('verify message NEWER than 45 days information', async () => {
@@ -143,7 +137,6 @@ describe('Messages Screen', () => {
await expect(element(by.id(MessagesE2eIdConstants.REVIEW_MESSAGE_REPLY_ID))).toExist()
await expect(element(by.text('Medication: Naproxen side effects'))).toExist()
await expect(element(by.text('RATANA, NARIN '))).toExist()
- await expect(element(by.text('Only use messages for non-urgent needs'))).toExist()
})
it(':android: verify phone links open', async () => {
@@ -156,6 +149,7 @@ describe('Messages Screen', () => {
await tapItems('+18006982411', 'phone')
await tapItems('1-800-698-2411.', 'phone')
})
+
//Currently broken on iOS. Will be fixed with ticket 7679
it(':android: verify url links open', async () => {
await tapItems('https://www.va.gov/', 'url')
@@ -183,22 +177,22 @@ describe('Messages Screen', () => {
})
it('verify medication message details', async () => {
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
await element(by.id('Martha Kaplan, Md October 26, 2021 Medication: Naproxen side effects')).tap()
await expect(element(by.text('Medication: Naproxen side effects'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('verify COVID message details', async () => {
await element(by.id('Diana Persson, Md October 26, 2021 Has attachment COVID: Prepping for your visit')).tap()
await expect(element(by.text('COVID: Your requested info'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('verify general message details', async () => {
await element(by.id(MessagesE2eIdConstants.MESSAGE_3_ID)).tap()
await expect(element(by.text('General: Vaccine Booster'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('verify appointment message details', async () => {
@@ -208,7 +202,7 @@ describe('Messages Screen', () => {
.scroll(100, 'down')
await element(by.id(MessagesE2eIdConstants.MESSAGE_4_ID)).tap()
await expect(element(by.text('Appointment: Preparing for your visit'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('verify other message details', async () => {
@@ -218,7 +212,7 @@ describe('Messages Screen', () => {
.scroll(100, 'down')
await element(by.id(MessagesE2eIdConstants.MESSAGE_5_ID)).tap()
await expect(element(by.text('General: COVID vaccine booster?'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('verify test_results message details', async () => {
@@ -228,7 +222,7 @@ describe('Messages Screen', () => {
.scroll(100, 'down')
await element(by.id(MessagesE2eIdConstants.MESSAGE_6_ID)).tap()
await expect(element(by.text('Test: Preparing for your visit'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('verify education message details', async () => {
@@ -238,7 +232,7 @@ describe('Messages Screen', () => {
.scroll(100, 'down')
await element(by.id(MessagesE2eIdConstants.MESSAGE_7_ID)).tap()
await expect(element(by.text('Education: Good morning to you'))).toExist()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
it('should tap on and then cancel the move option', async () => {
@@ -247,8 +241,8 @@ describe('Messages Screen', () => {
.whileElement(by.id(MessagesE2eIdConstants.MESSAGES_ID))
.scroll(400, 'up')
await element(by.id(MessagesE2eIdConstants.MESSAGE_1_READ_ID)).tap()
- await element(by.text('Move')).tap()
- await element(by.text('Cancel')).tap()
+ await element(by.id(MessagesE2eIdConstants.MOVE_PICKER_ID)).tap()
+ await element(by.id(MessagesE2eIdConstants.MOVE_PICKER_CANCEL_ID)).tap()
})
it('should tap reply and verify the correct information is displayed', async () => {
@@ -256,19 +250,19 @@ describe('Messages Screen', () => {
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()
- await expect(element(by.text(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_TEXT))).toExist()
+ await expect(element(by.id(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.MESSAGE_INPUT_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.SEND_BUTTON_ID))).toExist()
})
it('reply: verify talk to the veterans crisis line now is displayed', async () => {
- await element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT)).tap()
+ await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID)).tap()
await expect(element(by.text('Veterans Crisis Line'))).toExist()
- await element(by.text('Done')).tap()
+ await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BACK_ID)).tap()
})
it('should tap add files and verify the correct info is displayed', async () => {
- await element(by.text(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_TEXT)).tap()
+ await element(by.id(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_ID)).tap()
await expect(element(by.text('What to know about attaching files'))).toExist()
await expect(element(by.text('You can attach up to 4 files to each message.'))).toExist()
await expect(
@@ -277,21 +271,21 @@ describe('Messages Screen', () => {
await expect(element(by.text('The maximum size for each file is 6 MB.'))).toExist()
await expect(element(by.text('The maximum total size for all files attached to 1 message is 10 MB.'))).toExist()
await expect(element(by.text("We can't save attachments in a draft."))).toExist()
- await expect(element(by.text(MessagesE2eIdConstants.SELECT_A_FILE_ID))).toExist()
+ await expect(element(by.id(MessagesE2eIdConstants.SELECT_A_FILE_ID))).toExist()
})
it('should tap cancel and verify that the reply page is displayed', async () => {
- await element(by.text('Cancel')).atIndex(0).tap()
+ await element(by.id(MessagesE2eIdConstants.ATTACHMENTS_PAGE_CANCEL_ID)).tap()
await expect(element(by.id('To RATANA, NARIN '))).toExist()
await expect(element(by.id('Subject Medication: Naproxen side effects'))).toExist()
- await expect(element(by.text(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_TEXT))).toExist()
+ await expect(element(by.id(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.MESSAGE_INPUT_ID))).toExist()
await expect(element(by.id(MessagesE2eIdConstants.SEND_BUTTON_ID))).toExist()
})
it('verify tap select a file action sheet options are correct', async () => {
- await element(by.text(MessagesE2eIdConstants.ATTACHMENTS_BUTTON_TEXT)).tap()
- await element(by.text(MessagesE2eIdConstants.SELECT_A_FILE_ID)).tap()
+ 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()
@@ -300,10 +294,10 @@ describe('Messages Screen', () => {
it('should close the action sheet and tap cancel', async () => {
if (device.getPlatform() === 'android') {
await element(by.text('Cancel ')).tap()
- await element(by.text('Cancel')).atIndex(1).tap()
+ await element(by.id(MessagesE2eIdConstants.ATTACHMENTS_PAGE_CANCEL_ID)).tap()
} else {
await element(by.text('Cancel')).atIndex(2).tap()
- await element(by.text('Cancel')).atIndex(0).tap()
+ await element(by.id(MessagesE2eIdConstants.ATTACHMENTS_PAGE_CANCEL_ID)).tap()
}
})
@@ -330,16 +324,12 @@ describe('Messages Screen', () => {
it('should tap and move a message', async () => {
await element(by.id(MessagesE2eIdConstants.MESSAGE_2_READ_ID)).tap()
- await element(by.text('Move')).tap()
+ await element(by.id(MessagesE2eIdConstants.MOVE_PICKER_ID)).tap()
await element(by.text('Custom Folder 2')).tap()
- if (device.getPlatform() === 'android') {
- await element(by.text('Move')).tap()
- } else {
- await element(by.text('Move')).atIndex(1).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('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.BACK_TO_MESSAGES_ID)).tap()
})
//running on iOS only for the next few tests due to android wonkiness due to detox
@@ -354,9 +344,9 @@ describe('Messages Screen', () => {
})
it(':ios: new message: verify talk to the veterans crisis line now', async () => {
- await element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT)).tap()
+ await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID)).tap()
await expect(element(by.text('Veterans Crisis Line'))).toExist()
- await element(by.text('Done')).tap()
+ await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BACK_ID)).tap()
})
it(':ios: verify only use messages for non-urgent needs information', async () => {
@@ -367,14 +357,14 @@ describe('Messages Screen', () => {
await expect(element(by.text('If you need help sooner, use one of these urgent communication options:'))).toExist()
await device.disableSynchronization()
if (device.getPlatform() === 'android') {
- await element(by.text('Call 988 and select 1')).tap()
+ await element(by.id(CommonE2eIdConstants.VETERANS_CRISIS_LINE_CALL_ID)).tap()
await setTimeout(5000)
await device.takeScreenshot('messagesHelpCrisisLinePhone')
await device.launchApp({ newInstance: false })
await element(by.id('messageHelpTestID')).scrollTo('bottom')
- await element(by.text('TTY: 800-799-4889')).tap()
+ await element(by.id(CommonE2eIdConstants.VETERANS_CRISIS_LINE_TTY_ID)).tap()
await setTimeout(5000)
await device.takeScreenshot('messagesHelpCrisisLineTTY')
await device.launchApp({ newInstance: false })
@@ -387,12 +377,12 @@ describe('Messages Screen', () => {
await element(by.id('messageHelpTestID')).scrollTo('top')
}
- await element(by.text('Text 838255')).tap()
+ await element(by.id(CommonE2eIdConstants.VETERANS_CRISIS_LINE_TEXT_ID)).tap()
await setTimeout(5000)
await device.takeScreenshot('messagesHelpText')
await device.launchApp({ newInstance: false })
- await element(by.text('Start a confidential chat')).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('messagesHelpChat')
@@ -401,7 +391,7 @@ describe('Messages Screen', () => {
})
it(':ios: should close the messages help panel', async () => {
- await element(by.id('messagesHelpCloseTestID')).tap()
+ await element(by.id(MessagesE2eIdConstants.MESSAGES_HELP_CLOSE_ID)).tap()
})
it(':ios: verify the correct errors displayed on save', async () => {
@@ -415,7 +405,7 @@ describe('Messages Screen', () => {
it(':ios: should tap the to field and select a name', async () => {
await element(by.id(MessagesE2eIdConstants.START_NEW_MESSAGE_TO_ID)).tap()
await element(by.text('VA Flagship mobile applications interface_DAYT29')).tap()
- await element(by.text('Done')).tap()
+ await element(by.id(MessagesE2eIdConstants.MESSAGE_PICKER_CONFIRM_ID)).tap()
})
it(':ios: should tap the category field and select a category', async () => {
@@ -425,7 +415,7 @@ describe('Messages Screen', () => {
.scroll(50, 'down')
await element(by.id(MessagesE2eIdConstants.START_NEW_MESSAGE_CATEGORY_ID)).tap()
await element(by.text('Medication')).tap()
- await element(by.text('Done')).tap()
+ await element(by.id(MessagesE2eIdConstants.MESSAGE_PICKER_CONFIRM_ID)).tap()
})
it(':ios: should add and delete text in the subject field', async () => {
@@ -456,7 +446,7 @@ describe('Messages Screen', () => {
await element(by.id(MessagesE2eIdConstants.START_NEW_MESSAGE_CANCEL_ID)).tap()
await element(by.text(MessagesE2eIdConstants.MESSAGE_CANCEL_DELETE_TEXT)).tap()
await expect(element(by.id(CommonE2eIdConstants.START_NEW_MESSAGE_BUTTON_ID))).toExist()
- await expect(element(by.text(MessagesE2eIdConstants.FOLDERS_TEXT))).toExist()
+ await expect(element(by.id(MessagesE2eIdConstants.FOLDERS_ID))).toExist()
await expect(
element(by.id('Diana Persson, Md October 26, 2021 Has attachment COVID: Prepping for your visit')),
).toExist()
@@ -470,7 +460,7 @@ describe('Messages Screen', () => {
it('navigate to the sent folder and select the first message', async () => {
await openHealth()
await openMessages()
- await element(by.text(MessagesE2eIdConstants.FOLDERS_TEXT)).tap()
+ await element(by.id(MessagesE2eIdConstants.FOLDERS_ID)).tap()
await element(by.text('Sent')).tap()
})
@@ -570,8 +560,8 @@ describe('Messages Screen', () => {
})
it('verify that the sent folder opens and is displayed', async () => {
- await element(by.text('Messages')).tap()
- await element(by.text('Sent')).tap()
+ await element(by.id(MessagesE2eIdConstants.FOLDERS_BACK_ID)).tap()
+ await element(by.id('Sent')).tap()
await expect(element(by.id(CommonE2eIdConstants.START_NEW_MESSAGE_BUTTON_ID))).toExist()
await expect(
element(
@@ -593,7 +583,7 @@ describe('Messages Screen', () => {
it('verify that custom folders exist with messages', async () => {
await element(by.text('Sent')).tap()
- await element(by.text('Messages')).tap()
+ await element(by.id(MessagesE2eIdConstants.FOLDERS_BACK_ID)).tap()
await expect(element(by.text('Custom Folder 2'))).toExist()
})
})
diff --git a/VAMobile/e2e/tests/MilitaryInformation.e2e.ts b/VAMobile/e2e/tests/MilitaryInformation.e2e.ts
index 7153056d20c..d3c1b1129cb 100644
--- a/VAMobile/e2e/tests/MilitaryInformation.e2e.ts
+++ b/VAMobile/e2e/tests/MilitaryInformation.e2e.ts
@@ -1,11 +1,19 @@
import { by, device, element, expect } from 'detox'
import { setTimeout } from 'timers/promises'
-import { changeMockData, checkImages, loginToDemoMode, openMilitaryInformation, openProfile } from './utils'
+import {
+ CommonE2eIdConstants,
+ changeMockData,
+ checkImages,
+ loginToDemoMode,
+ openMilitaryInformation,
+ openProfile,
+} from './utils'
export const MilitaryInformationE2eIdConstants = {
MILITARY_DATE_TEXT: 'July 13, 1970 – August 31, 1998',
- SERVICE_INFORMATION_INCORRECT_TITLE_TEXT: "What if my military service information doesn't look right?",
+ SERVICE_INFORMATION_INCORRECT_ID: 'militaryServiceIncorrectLinkID',
+ SERVICE_INFORMATION_INCORRECT_SWIPE: 'IncorrectServiceTestID',
SERVICE_INFORMATION_INCORRECT_BODY_LABEL_1:
'Some Veterans have reported seeing military service information in their V-A .gov profiles that doesn’t seem right. When this happens, it’s because there’s an error in the information we’re pulling into V-A .gov from the Defense Enrollment Eligibility Reporting System (D-E-E-R-S).',
SERVICE_INFORMATION_INCORRECT_BODY_LABEL_2:
@@ -52,10 +60,7 @@ describe('Military Info Screen', () => {
it('should open new screen if military service information is incorrect', async () => {
await openProfile()
await openMilitaryInformation()
- await element(by.text(MilitaryInformationE2eIdConstants.SERVICE_INFORMATION_INCORRECT_TITLE_TEXT)).tap()
- await expect(
- element(by.text(MilitaryInformationE2eIdConstants.SERVICE_INFORMATION_INCORRECT_TITLE_TEXT)).atIndex(1),
- ).toExist()
+ await element(by.id(MilitaryInformationE2eIdConstants.SERVICE_INFORMATION_INCORRECT_ID)).tap()
await expect(
element(by.label(MilitaryInformationE2eIdConstants.SERVICE_INFORMATION_INCORRECT_BODY_LABEL_1)),
).toExist()
@@ -65,11 +70,11 @@ describe('Military Info Screen', () => {
await expect(
element(by.label(MilitaryInformationE2eIdConstants.SERVICE_INFORMATION_INCORRECT_BODY_LABEL_3)),
).toExist()
- await expect(element(by.id('CallVATestID'))).toExist()
- await element(by.id('IncorrectServiceTestID')).swipe('up')
+ await expect(element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID))).toExist()
+ await element(by.id(MilitaryInformationE2eIdConstants.SERVICE_INFORMATION_INCORRECT_SWIPE)).swipe('up')
if (device.getPlatform() === 'android') {
await device.disableSynchronization()
- await element(by.id('CallVATestID')).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).tap()
await setTimeout(5000)
await device.enableSynchronization()
await device.launchApp({ newInstance: false })
diff --git a/VAMobile/e2e/tests/Onboarding.e2e.ts b/VAMobile/e2e/tests/Onboarding.e2e.ts
index 9339a38b768..e0bada940ec 100644
--- a/VAMobile/e2e/tests/Onboarding.e2e.ts
+++ b/VAMobile/e2e/tests/Onboarding.e2e.ts
@@ -4,6 +4,8 @@ import { CommonE2eIdConstants, checkImages, loginToDemoMode } from './utils'
export const OnboardingE2eIdConstants = {
VA_ICON_ID: 'VAIconOnboardingLogo',
+ DONE_NEXT_BUTTON_ID: 'onboardingDoneNextButtonID',
+ SKIP_BACK_BUTTON_ID: 'onboardingSkipBackButtonID',
}
beforeAll(async () => {
@@ -24,56 +26,56 @@ describe('Onboarding Screen', () => {
),
),
).toExist()
- await expect(element(by.text('Skip'))).toExist()
- await expect(element(by.text('Next'))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID))).toExist()
})
it('should tap next and show the manage your health care content', async () => {
- await element(by.text('Next')).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
await expect(element(by.text('Manage your health care')))
await expect(element(by.text('Use our health care tools to manage tasks like these:'))).toExist()
await expect(element(by.text('Refill your prescriptions'))).toExist()
await expect(element(by.text('Communicate with your health care team'))).toExist()
await expect(element(by.text('Review your appointments'))).toExist()
- await expect(element(by.text('Back'))).toExist()
- await expect(element(by.text('Next'))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID))).toExist()
})
it('should tap next and show the manage your benefits content', async () => {
- await element(by.text('Next')).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
await expect(element(by.text('Manage your benefits'))).toExist()
await expect(element(by.text('Use our benefits tools to manage tasks like these:'))).toExist()
await expect(element(by.text('Review your disability rating'))).toExist()
await expect(element(by.text('Check the status of your claims and appeals'))).toExist()
await expect(element(by.label('Download common V-A letters'))).toExist()
- await expect(element(by.text('Back'))).toExist()
- await expect(element(by.text('Next'))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID))).toExist()
})
it('should tap next and show the manage your payments content', async () => {
- await element(by.text('Next')).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
await expect(element(by.text('Manage your payments'))).toExist()
await expect(element(by.text('Use our payments tools to manage tasks like these:'))).toExist()
await expect(element(by.text('Update your direct deposit information'))).toExist()
await expect(element(by.text('Review the history of payments we’ve sent to you'))).toExist()
- await expect(element(by.text('Back'))).toExist()
- await expect(element(by.text('Done'))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID))).toExist()
+ await expect(element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID))).toExist()
})
it('should tap back and verify the previous page is displayed', async () => {
- await element(by.text('Back')).tap()
+ await element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID)).tap()
await expect(element(by.text('Manage your benefits'))).toExist()
- await element(by.text('Back')).tap()
+ await element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID)).tap()
await expect(element(by.text('Manage your health care'))).toExist()
- await element(by.text('Back')).tap()
+ await element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID)).tap()
await expect(element(by.text('Welcome, Kimberly'))).toExist()
})
it('verify the home page is displayed after tapping done', async () => {
- await element(by.text('Next')).tap()
- await element(by.text('Next')).tap()
- await element(by.text('Next')).tap()
- await element(by.text('Done')).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
+ await element(by.id(OnboardingE2eIdConstants.DONE_NEXT_BUTTON_ID)).tap()
await expect(element(by.text(CommonE2eIdConstants.HOME_ACTIVITY_HEADER_TEXT))).toExist()
})
@@ -82,7 +84,7 @@ describe('Onboarding Screen', () => {
await device.installApp()
await device.launchApp({ newInstance: true, permissions: { notifications: 'YES' } })
await loginToDemoMode(false)
- await element(by.text('Skip')).tap()
+ await element(by.id(OnboardingE2eIdConstants.SKIP_BACK_BUTTON_ID)).tap()
await expect(element(by.text(CommonE2eIdConstants.HOME_ACTIVITY_HEADER_TEXT))).toExist()
})
})
diff --git a/VAMobile/e2e/tests/Payments.e2e.ts b/VAMobile/e2e/tests/Payments.e2e.ts
index c32079a8b6a..8d36aba215a 100644
--- a/VAMobile/e2e/tests/Payments.e2e.ts
+++ b/VAMobile/e2e/tests/Payments.e2e.ts
@@ -1,6 +1,6 @@
import { by, device, element, expect, waitFor } from 'detox'
-import { loginToDemoMode, openPayments, openVAPaymentHistory } from './utils'
+import { CommonE2eIdConstants, loginToDemoMode, openPayments, openVAPaymentHistory } from './utils'
export const PaymentsE2eIDConstants = {
PAYMENTS_YEAR_PICKER_ID: 'selectAYearTestID',
@@ -8,6 +8,14 @@ export const PaymentsE2eIDConstants = {
PAYMENT_HISTORY_1_ID: 'Regular Chapter 31 $603.33',
PAYMENT_HISTORY_2_ID: 'Post-9/11 GI Bill $1,172.60',
PAYMENT_INFO_INCORRECT_ID: 'paymentInfoIncorrectTestID',
+ PAYMENT_MISSING_ID: 'paymentsMissingPanelID',
+ PAYMENT_MISSING_CLOSE_ID: 'paymentsMissingCloseID',
+ PAYMENT_ISSUE_ID: 'paymentsIssuesPanelID',
+ PAYMENT_ISSUE_CLOSE_ID: 'paymentIssuesCloseID',
+ PAYMENT_DETAILS_BACK_ID: 'paymentDetailsBackID',
+ PAYMENT_HISTORY_SCROLL_ID: 'paymentHistoryTestID',
+ SELECT_A_YEAR_CANCEL_ID: 'selectAYearCancelTestID',
+ SELECT_A_YEAR_CONFIRM_ID: 'selectAYearConfirmTestID',
}
beforeAll(async () => {
@@ -26,18 +34,18 @@ describe('Payments Screen', () => {
it("verify what if I'm missing a payment information", async () => {
await element(by.id(PaymentsE2eIDConstants.MISSING_PAYMENTS_LINK_ID)).tap()
- await expect(element(by.text("What if I'm missing a payment?")).atIndex(1)).toExist()
+ await expect(element(by.id(PaymentsE2eIDConstants.PAYMENT_MISSING_ID))).toExist()
if (device.getPlatform() === 'android') {
await device.disableSynchronization()
- await element(by.text('800-827-1000')).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).tap()
await device.takeScreenshot('PaymentsMissingAndroidCallingScreen')
await device.launchApp({ newInstance: false })
- await element(by.text('TTY: 711')).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).tap()
await device.takeScreenshot('PaymentsMissingAndroidCallingScreenTTY')
await device.launchApp({ newInstance: false })
await device.enableSynchronization()
}
- await element(by.text('Close')).tap()
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_MISSING_CLOSE_ID)).tap()
})
it('payment details: verify the payment details for paper check', async () => {
@@ -51,51 +59,51 @@ describe('Payments Screen', () => {
it("verify what if my payment information doesn't look right info", async () => {
await element(by.id(PaymentsE2eIDConstants.PAYMENT_INFO_INCORRECT_ID)).tap()
- await expect(element(by.text("What if my payment information doesn't look right?")).atIndex(1)).toExist()
+ await expect(element(by.id(PaymentsE2eIDConstants.PAYMENT_ISSUE_ID))).toExist()
if (device.getPlatform() === 'android') {
await device.disableSynchronization()
- await element(by.text('800-827-1000')).tap()
- await device.takeScreenshot('PaymentIncorrectAndroidCallingScreen')
+ await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).tap()
+ await device.takeScreenshot('PaymentsMissingAndroidCallingScreen')
await device.launchApp({ newInstance: false })
- await element(by.text('TTY: 711')).tap()
- await device.takeScreenshot('PaymentIncorrectAndroidCallingScreenTTY')
+ await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).tap()
+ await device.takeScreenshot('PaymentsMissingAndroidCallingScreenTTY')
await device.launchApp({ newInstance: false })
await device.enableSynchronization()
}
- await element(by.text('Close')).tap()
- await element(by.text('History')).tap()
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_ISSUE_CLOSE_ID)).tap()
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_DETAILS_BACK_ID)).tap()
})
it('verify the payment details for direct deposit', async () => {
await waitFor(element(by.id(PaymentsE2eIDConstants.PAYMENT_HISTORY_2_ID)))
.toBeVisible()
- .whileElement(by.id('paymentHistoryTestID'))
+ .whileElement(by.id(PaymentsE2eIDConstants.PAYMENT_HISTORY_SCROLL_ID))
.scroll(200, 'down')
await element(by.id(PaymentsE2eIDConstants.PAYMENT_HISTORY_2_ID)).tap()
await expect(element(by.text('BANK OF AMERICA, N.A.'))).toExist()
await expect(element(by.text('********0567'))).toExist()
- await element(by.text('History')).tap()
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_DETAILS_BACK_ID)).tap()
})
it('should tap on and cancel the select a year picker', async () => {
- await element(by.id('paymentHistoryTestID')).scrollTo('top')
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_HISTORY_SCROLL_ID)).scrollTo('top')
await element(by.id(PaymentsE2eIDConstants.PAYMENTS_YEAR_PICKER_ID)).tap()
await expect(element(by.text('Select a year'))).toExist()
- await element(by.text('Cancel')).tap()
+ await element(by.id(PaymentsE2eIDConstants.SELECT_A_YEAR_CANCEL_ID)).tap()
await expect(element(by.text('2017')).atIndex(0)).toExist()
})
it('should tap on and select 2016 from the select a year picker', async () => {
await element(by.id(PaymentsE2eIDConstants.PAYMENTS_YEAR_PICKER_ID)).tap()
await element(by.text('2016')).tap()
- await element(by.text('Done')).tap()
+ await element(by.id(PaymentsE2eIDConstants.SELECT_A_YEAR_CONFIRM_ID)).tap()
await expect(element(by.text('2016')).atIndex(0)).toExist()
})
it('should verify the next and back page arrows work', async () => {
- await element(by.id('paymentHistoryTestID')).scrollTo('bottom')
- await element(by.id('next-page')).tap()
- await element(by.id('paymentHistoryTestID')).scrollTo('bottom')
- await element(by.id('previous-page')).tap()
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_HISTORY_SCROLL_ID)).scrollTo('bottom')
+ await element(by.id(CommonE2eIdConstants.NEXT_PAGE_ID)).tap()
+ await element(by.id(PaymentsE2eIDConstants.PAYMENT_HISTORY_SCROLL_ID)).scrollTo('bottom')
+ await element(by.id(CommonE2eIdConstants.PREVIOUS_PAGE_ID)).tap()
})
})
diff --git a/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts b/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts
index 1b7b37077a7..7e527f70531 100644
--- a/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts
+++ b/VAMobile/e2e/tests/PersonalInformationScreen.e2e.ts
@@ -11,39 +11,56 @@ import {
export const PersonalInfoConstants = {
PERSONAL_INFORMATION_TEXT: 'Personal information',
- HOW_TO_UPDATE_LINK_TEXT: 'How to update or fix an error in your legal name',
- HOW_TO_FIX_LINK_TEXT: 'How to fix an error in your date of birth',
- LEARN_HOW_LINK_TEXT: 'Learn how to change your legal name on file with the VA',
- NEAREST_CENTER_LINK_TEXT: 'Find nearest VA medical center',
- PHONE_LINK_TEXT: '800-827-1000',
- TTY_LINK_TEXT: 'TTY: 711',
- PREFERRED_NAME_ROW_TEXT: 'Preferred name',
+ HOW_TO_UPDATE_ID: 'howDoIUpdateTestID',
+ HOW_TO_UPDATE_LINK_ID: 'howToFixLegalNameID',
+ HOW_TO_UPDATE_CLOSE_ID: 'howDoIUpdateCloseTestID',
+ WHAT_TO_KNOW_ID: 'whatToKnowID',
+ WHAT_TO_KNOW_CLOSE_ID: 'whatToKnowBackID',
+ HOW_TO_FIX_LINK_ID: 'howToFixDOBID',
+ LEARN_HOW_LINK_ID: 'learnToChangeLegalNameID',
+ NEAREST_CENTER_LINK_ID: 'findNearestVAMedicalCenterID',
+ PREFERRED_NAME_HEADER_TEXT: 'Preferred name',
+ PREFERRED_NAME_ROW_ID: 'preferredNameRowID',
PREFERRED_NAME_ID: 'preferredNameTestID',
- GENDER_IDENTITY_ROW_TEXT: 'Gender identity',
- GENDER_IDENTITY_WHAT_TO_KNOW_TEXT: 'What to know before you decide to share your gender identity',
+ PREFERRED_NAME_BACK_ID: 'preferredNameBackID',
+ GENDER_IDENTITY_HEADER_TEXT: 'Gender identity',
+ GENDER_IDENTITY_ROW_ID: 'genderIdentityRowID',
+ GENDER_IDENTITY_WHAT_TO_KNOW_ID: 'whatToKnowTestID',
+ GENDER_IDENTITY_SCROLL: 'genderIdentityID',
+ GENDER_IDENTITY_BACK_ID: 'genderIdentityBackID',
PREFER_NOT_TEXT: 'Prefer not to answer',
+ PERSONAL_INFO_SCROLL_ID: 'PersonalInformationTestID',
}
-const scrollToThenTap = async (text: string) => {
- await element(by.id('PersonalInformationTestID')).atIndex(0).scrollTo('bottom')
- await waitFor(element(by.text(text))).toBeVisible()
- await element(by.text(text)).tap()
+const scrollToThenTap = async (text: string, scrollID?: string, id?: boolean) => {
+ if (scrollID != undefined) {
+ await element(by.id(scrollID)).atIndex(0).scrollTo('bottom')
+ } else {
+ await element(by.id(PersonalInfoConstants.PERSONAL_INFO_SCROLL_ID)).atIndex(0).scrollTo('bottom')
+ }
+ if (id) {
+ await waitFor(element(by.id(text))).toBeVisible()
+ await element(by.id(text)).tap()
+ } else {
+ await waitFor(element(by.text(text))).toBeVisible()
+ await element(by.text(text)).tap()
+ }
}
-const checkLocatorAndContactLinks = async () => {
+const checkLocatorAndContactLinks = async (scrollID?: string) => {
await device.disableSynchronization()
- await scrollToThenTap(PersonalInfoConstants.NEAREST_CENTER_LINK_TEXT)
+ await scrollToThenTap(PersonalInfoConstants.NEAREST_CENTER_LINK_ID, scrollID, true)
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('PersonalInformationFindVALocations')
await device.launchApp({ newInstance: false })
- await scrollToThenTap(PersonalInfoConstants.PHONE_LINK_TEXT)
+ await scrollToThenTap(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID, undefined, true)
await setTimeout(1000)
await device.takeScreenshot('PersonalInformationPhoneNumber')
await device.launchApp({ newInstance: false })
- await scrollToThenTap(PersonalInfoConstants.TTY_LINK_TEXT)
+ await scrollToThenTap(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID, undefined, true)
await setTimeout(1000)
await device.takeScreenshot('PersonalInformationTTY')
await device.launchApp({ newInstance: false })
@@ -52,12 +69,12 @@ const checkLocatorAndContactLinks = async () => {
export async function updateGenderIdentify(genderIdentityOption) {
it('should update gender identity for ' + genderIdentityOption, async () => {
- await element(by.id('PersonalInformationTestID')).scrollTo('bottom')
- await element(by.text(PersonalInfoConstants.GENDER_IDENTITY_ROW_TEXT)).tap()
- await expect(element(by.text(PersonalInfoConstants.GENDER_IDENTITY_ROW_TEXT)).atIndex(0)).toExist()
- await scrollToThenTap(genderIdentityOption)
+ await element(by.id(PersonalInfoConstants.PERSONAL_INFO_SCROLL_ID)).scrollTo('bottom')
+ await element(by.id(PersonalInfoConstants.GENDER_IDENTITY_ROW_ID)).tap()
+ await expect(element(by.text(PersonalInfoConstants.GENDER_IDENTITY_HEADER_TEXT)).atIndex(0)).toExist()
+ await scrollToThenTap(genderIdentityOption, PersonalInfoConstants.GENDER_IDENTITY_SCROLL)
await element(by.text(genderIdentityOption)).tap()
- await element(by.text('Save')).tap()
+ await element(by.id('genderIdentitySaveID')).tap()
await expect(element(by.text(genderIdentityOption))).toExist()
await expect(element(by.text(PersonalInfoConstants.PERSONAL_INFORMATION_TEXT))).toExist()
@@ -65,11 +82,11 @@ export async function updateGenderIdentify(genderIdentityOption) {
await expect(element(by.text(genderIdentityOption))).toExist()
await element(by.text('Dismiss')).tap()
- await element(by.id('PersonalInformationTestID')).scrollTo('bottom')
- await element(by.text(PersonalInfoConstants.GENDER_IDENTITY_ROW_TEXT)).tap()
+ await element(by.id(PersonalInfoConstants.PERSONAL_INFO_SCROLL_ID)).scrollTo('bottom')
+ await element(by.id(PersonalInfoConstants.GENDER_IDENTITY_ROW_ID)).tap()
await expect(element(by.text('Gender identity saved'))).not.toExist()
await expect(element(by.label(genderIdentityOption + ' ').withDescendant(by.id('RadioFilled')))).toExist()
- await element(by.text('Cancel')).tap()
+ await element(by.id(PersonalInfoConstants.GENDER_IDENTITY_BACK_ID)).tap()
})
}
@@ -93,36 +110,37 @@ describe('Personal Info Screen', () => {
})
it('should tap links in "How to update" large panel', async () => {
- await element(by.text(PersonalInfoConstants.HOW_TO_UPDATE_LINK_TEXT)).tap()
- await expect(element(by.text('Profile help'))).toExist()
+ await element(by.id(PersonalInfoConstants.HOW_TO_UPDATE_LINK_ID)).tap()
+ await expect(element(by.id(PersonalInfoConstants.HOW_TO_UPDATE_ID))).toExist()
- await element(by.text(PersonalInfoConstants.LEARN_HOW_LINK_TEXT)).tap()
+ await element(by.id(PersonalInfoConstants.LEARN_HOW_LINK_ID)).tap()
+ await setTimeout(2000)
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('personalInfoLearnHowToWebPage')
await device.launchApp({ newInstance: false })
if (device.getPlatform() === 'android') {
- await checkLocatorAndContactLinks()
+ await checkLocatorAndContactLinks(PersonalInfoConstants.HOW_TO_UPDATE_ID)
}
- await element(by.text('Close')).tap()
+ await element(by.id(PersonalInfoConstants.HOW_TO_UPDATE_CLOSE_ID)).tap()
})
it('should tap links in "How to fix an error" large panel', async () => {
- await element(by.text(PersonalInfoConstants.HOW_TO_FIX_LINK_TEXT)).tap()
- await expect(element(by.text('Profile help'))).toExist()
+ await element(by.id(PersonalInfoConstants.HOW_TO_FIX_LINK_ID)).tap()
+ await expect(element(by.id(PersonalInfoConstants.HOW_TO_UPDATE_ID))).toExist()
if (device.getPlatform() === 'android') {
- await checkLocatorAndContactLinks()
+ await checkLocatorAndContactLinks(PersonalInfoConstants.HOW_TO_UPDATE_ID)
}
- await element(by.text('Close')).tap()
+ await element(by.id(PersonalInfoConstants.HOW_TO_UPDATE_CLOSE_ID)).tap()
})
it('should update preferred name', async () => {
- await element(by.text(PersonalInfoConstants.PREFERRED_NAME_ROW_TEXT)).tap()
- await expect(element(by.text(PersonalInfoConstants.PREFERRED_NAME_ROW_TEXT)).atIndex(0)).toExist()
+ await element(by.id(PersonalInfoConstants.PREFERRED_NAME_ROW_ID)).tap()
+ 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()
@@ -131,10 +149,10 @@ describe('Personal Info Screen', () => {
await expect(element(by.text('Preferred name saved'))).toExist()
await expect(element(by.text('Kimberlee'))).toExist()
- await element(by.text(PersonalInfoConstants.PREFERRED_NAME_ROW_TEXT)).tap()
+ await element(by.id(PersonalInfoConstants.PREFERRED_NAME_ROW_ID)).tap()
await expect(element(by.text('Preferred name saved'))).not.toExist()
await expect(element(by.text('Kimberlee')).atIndex(0)).toExist()
- await element(by.text('Cancel')).tap()
+ await element(by.id(PersonalInfoConstants.PREFERRED_NAME_BACK_ID)).tap()
})
updateGenderIdentify(PersonalInfoConstants.PREFER_NOT_TEXT)
@@ -145,11 +163,15 @@ describe('Personal Info Screen', () => {
updateGenderIdentify('A gender not listed here')
it('should show "What to know" large panel in gender identity section', async () => {
- await element(by.id('PersonalInformationTestID')).scrollTo('bottom')
- await element(by.text(PersonalInfoConstants.GENDER_IDENTITY_ROW_TEXT)).tap()
- await scrollToThenTap(PersonalInfoConstants.GENDER_IDENTITY_WHAT_TO_KNOW_TEXT)
- await expect(element(by.text('Profile help'))).toExist()
- await element(by.text('Close')).tap()
- await element(by.text('Cancel')).tap()
+ await element(by.id(PersonalInfoConstants.PERSONAL_INFO_SCROLL_ID)).scrollTo('bottom')
+ await element(by.id(PersonalInfoConstants.GENDER_IDENTITY_ROW_ID)).tap()
+ await scrollToThenTap(
+ PersonalInfoConstants.GENDER_IDENTITY_WHAT_TO_KNOW_ID,
+ PersonalInfoConstants.GENDER_IDENTITY_SCROLL,
+ true,
+ )
+ await expect(element(by.id(PersonalInfoConstants.WHAT_TO_KNOW_ID))).toExist()
+ await element(by.id(PersonalInfoConstants.WHAT_TO_KNOW_CLOSE_ID)).tap()
+ await element(by.id(PersonalInfoConstants.GENDER_IDENTITY_BACK_ID)).tap()
})
})
diff --git a/VAMobile/e2e/tests/Prescriptions.e2e.ts b/VAMobile/e2e/tests/Prescriptions.e2e.ts
index 329b9cf1fd6..ba1cf923952 100644
--- a/VAMobile/e2e/tests/Prescriptions.e2e.ts
+++ b/VAMobile/e2e/tests/Prescriptions.e2e.ts
@@ -14,8 +14,8 @@ import {
export const PrescriptionsE2eIdConstants = {
PRESCRIPTION_FILTER_BUTTON_ID: 'openFilterAndSortTestID',
PRESCRIPTION_FILTER_MODAL_ID: 'ModalTestID',
- PRESCRIPTION_FILTER_APPLY_TEXT: 'Apply',
- PRESCRIPTION_REFILL_WARNING_TEXT: "We can't refill some of your prescriptions in the app",
+ PRESCRIPTION_FILTER_APPLY_ID: 'radioButtonApplyTestID',
+ PRESCRIPTION_REFILL_WARNING_ID: 'prescriptionRefillWarningTestID',
PRESCRIPTION_ALL_DESCRIPTION_LABEL:
'This list only shows prescriptions filled by V-A pharmacies and may not include all your medications.',
PRESCRIPTION_ALL_NUMBER_OF_PRESCRIPTIONS_TEXT: 'All prescriptions (31), sorted by status (A to Z)',
@@ -31,7 +31,7 @@ export const PrescriptionsE2eIdConstants = {
PRESCRIPTION_DETAILS_LABEL: 'Get prescription details',
PRESCRIPTION_PENDING_DESCRIPTION_LABEL:
"This list shows refill requests you've submitted. It also shows refills the V-A pharmacy is processing.",
- PRESCRIPTION_TRACKING_GET_TRACKING_TEXT: 'Get prescription tracking',
+ 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',
@@ -42,6 +42,14 @@ export const PrescriptionsE2eIdConstants = {
PRESCRIPTION_REFILL_REQUEST_SUMMARY_DESCRIPTION_2_LABEL:
'If you have questions about the status of your refill, contact your provider or local V-A pharmacy.',
PRESCRIPTION_REFILL_REQUEST_SUMMARY_PENDING_BUTTON_TEXT: 'Go to all pending refills',
+ PRESCRIPTION_BACK_ID: 'prescriptionsBackTestID',
+ PRESCRIPTION_HISTORY_SCROLL_ID: 'PrescriptionHistory',
+ FILTER_PRESCRIPTIONS_TEST_ID: 'filterSortWrapperBoxTestID',
+ PRESCRIPTION_GO_TO_MY_VA_HEALTH_LINK_ID: 'goToMyVAHealthPrescriptionHistoryID',
+ PRESCRIPTION_DETAILS_BACK_ID: 'prescriptionsDetailsBackTestID',
+ PRESCRIPTION_FILTER_CANCEL_ID: 'radioButtonCancelTestID',
+ PRESCRIPTION_HELP_BUTTON_ID: 'prescriptionsHelpID',
+ PRESCRIPTION_REQUEST_REFILL_ID: 'requestRefillsButtonID',
}
let tempPath
@@ -63,23 +71,23 @@ export async function validateSort(
) {
it('should sort prescription data by ' + name, async () => {
if (firstInstance) {
- await element(by.id('PrescriptionHistory')).scrollTo('top')
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).scrollTo('top')
await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_BUTTON_ID)).tap()
await element(by.text('All (31)')).atIndex(0).tap()
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_TEXT)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_ID)).tap()
} else {
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('previous-page')).tap()
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('previous-page')).tap()
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('previous-page')).tap()
- await element(by.id('PrescriptionHistory')).scrollTo('top')
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(CommonE2eIdConstants.PREVIOUS_PAGE_ID)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(CommonE2eIdConstants.PREVIOUS_PAGE_ID)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(CommonE2eIdConstants.PREVIOUS_PAGE_ID)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).scrollTo('top')
}
await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_BUTTON_ID)).tap()
await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_MODAL_ID)).scrollTo('bottom')
@@ -91,20 +99,20 @@ export async function validateSort(
checkImages(tempPath)
}
await element(by.text(name)).tap()
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_TEXT)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_ID)).tap()
await expect(element(by.text(firstPrescription)).atIndex(0)).toBeVisible()
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('next-page')).tap()
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('next-page')).tap()
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('PrescriptionHistory')).swipe('up', 'fast', 1.0)
- await element(by.id('next-page')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(CommonE2eIdConstants.NEXT_PAGE_ID)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(CommonE2eIdConstants.NEXT_PAGE_ID)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).swipe('up', 'fast', 1.0)
+ await element(by.id(CommonE2eIdConstants.NEXT_PAGE_ID)).tap()
await expect(element(by.text(lastPrescription))).toBeVisible()
})
}
@@ -117,23 +125,25 @@ export async function validateFilter(name: string, quantity: number, helperText?
await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_BUTTON_ID)).tap()
helperText && (await expect(element(by.text(helperText))).toExist())
await element(by.text(`${name} (${quantity})`)).tap()
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_TEXT)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_ID)).tap()
await expect(element(by.text(`${filterDescription} (${quantity}), sorted by status (A to Z)`))).toExist()
})
}
describe('Prescriptions Screen', () => {
it('should match the prescription page design', async () => {
- tempPath = await element(by.id('filterSortWrapperBoxTestID')).takeScreenshot('filterSortWrapperBox')
+ tempPath = await element(by.id(PrescriptionsE2eIdConstants.FILTER_PRESCRIPTIONS_TEST_ID)).takeScreenshot(
+ 'filterSortWrapperBox',
+ )
checkImages(tempPath)
- await expect(element(by.text(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_TEXT))).toExist()
+ await expect(element(by.id(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_ID))).toExist()
await expect(element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_BUTTON_ID))).toExist()
- await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_WARNING_TEXT))).toExist()
+ await expect(element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_WARNING_ID))).toExist()
await expect(element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_ALL_DESCRIPTION_LABEL))).toExist()
await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_ALL_NUMBER_OF_PRESCRIPTIONS_TEXT))).toExist()
await waitFor(element(by.label('CAPECITABINE 500MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(100, 'down')
await expect(
element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_STATUS_LABEL_HEADER_TEXT)).atIndex(0),
@@ -146,8 +156,8 @@ describe('Prescriptions Screen', () => {
})
it('verify prescription refill warning label information', async () => {
- await element(by.id('PrescriptionHistory')).scrollTo('top')
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_WARNING_TEXT)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).scrollTo('top')
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_WARNING_ID)).tap()
await expect(element(by.text("We can't refill some of your prescriptions in the app"))).toExist()
await expect(element(by.label('Some V-A health facilities use a new electronic health record system.'))).toExist()
await expect(
@@ -157,8 +167,8 @@ describe('Prescriptions Screen', () => {
),
),
).toExist()
- await expect(element(by.label('Go to My V-A Health')).atIndex(trackingIndex)).toExist()
- await element(by.label('Go to My V-A Health')).atIndex(trackingIndex).tap()
+ await expect(element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_GO_TO_MY_VA_HEALTH_LINK_ID))).toExist()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_GO_TO_MY_VA_HEALTH_LINK_ID)).tap()
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('PrescriptionVAHealthLink')
@@ -172,13 +182,13 @@ describe('Prescriptions Screen', () => {
element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_STATUS_LABEL_HEADER_TEXT)).atIndex(0),
).toExist()
await expect(element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_STATUS_LABEL_BODY_LABEL))).toExist()
- await element(by.text('Close')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
})
it('verify prescription details information', async () => {
await waitFor(element(by.label('CAPECITABINE 500MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(50, 'down')
await element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_DETAILS_LABEL)).atIndex(0).tap()
await expect(element(by.text('AMLODIPINE BESYLATE 10MG TAB'))).toExist()
@@ -205,8 +215,8 @@ describe('Prescriptions Screen', () => {
element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_STATUS_LABEL_HEADER_TEXT)).atIndex(0),
).toExist()
await expect(element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_STATUS_LABEL_BODY_LABEL))).toExist()
- await element(by.text('Close')).tap()
- await element(by.label('Prescriptions')).atIndex(0).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_DETAILS_BACK_ID)).tap()
})
validateFilter('Active', 24, 'Includes these statuses: On hold, Parked, Refill in process, and Submitted')
@@ -220,7 +230,7 @@ describe('Prescriptions Screen', () => {
it('verify prescriptions screen after filters cancel', async () => {
await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_BUTTON_ID)).tap()
- await element(by.text('Cancel')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_CANCEL_ID)).tap()
await expect(element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_ALL_DESCRIPTION_LABEL))).toExist()
await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_ALL_NUMBER_OF_PRESCRIPTIONS_TEXT))).toExist()
await expect(
@@ -243,15 +253,15 @@ describe('Prescriptions Screen', () => {
await expect(element(by.text('Tracking (3)'))).toExist()
await expect(element(by.text('Transferred (1)'))).toExist()
await expect(element(by.text('Unknown (1)'))).toExist()
- await element(by.text('Cancel')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_CANCEL_ID)).tap()
})
it('verify prescription tracking item specific info', async () => {
await waitFor(element(by.label('CITALOPRAM HYDROBROMIDE 20MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(500, 'down')
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_TEXT)).atIndex(0).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_ID)).atIndex(0).tap()
await expect(element(by.label('Prescription number 3 6 3 6 8 5 6'))).toExist()
await expect(
element(
@@ -282,30 +292,30 @@ describe('Prescriptions Screen', () => {
await setTimeout(5000)
await device.takeScreenshot('PrescriptionTrackingWebsiteDHL')
await device.launchApp({ newInstance: false })
- await element(by.text('Close')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
})
it('verify tracking link for FEDEX works', async () => {
await waitFor(element(by.label('LAMIVUDINE 100MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(500, 'down')
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_TEXT)).atIndex(1).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_ID)).atIndex(1).tap()
await expect(element(by.text('Delivery service: FEDEX'))).toExist()
await element(by.label('7 5 3 4 5 3 3 6 3 6 8 5 6')).atIndex(trackingIndex).tap()
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('PrescriptionTrackingWebsiteFedex')
await device.launchApp({ newInstance: false })
- await element(by.text('Close')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
})
it('verify tracking info for multiple packages', async () => {
await waitFor(element(by.label('LAMIVUDINE 150MG/ZIDOVUDINE 300MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(500, 'down')
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_TEXT)).atIndex(2).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_ID)).atIndex(2).tap()
await expect(element(by.text('Package 1 of 2'))).toExist()
await expect(element(by.text('Delivery service: UPS'))).toExist()
await expect(element(by.text('Package 2 of 2'))).toExist()
@@ -323,9 +333,9 @@ describe('Prescriptions Screen', () => {
await openPrescriptions()
await waitFor(element(by.label('LAMIVUDINE 150MG/ZIDOVUDINE 300MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(500, 'down')
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_TEXT)).atIndex(2).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_TRACKING_GET_TRACKING_ID)).atIndex(2).tap()
})
it('verify tracking link for USPS works', async () => {
@@ -335,11 +345,11 @@ describe('Prescriptions Screen', () => {
await setTimeout(5000)
await device.takeScreenshot('PrescriptionTrackingWebsiteUSPS')
await device.launchApp({ newInstance: false })
- await element(by.text('Close')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
})
it('verify prescriptions help model information', async () => {
- await element(by.text('Help')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HELP_BUTTON_ID)).tap()
tempPath = await element(by.id('PrescriptionsHelpTestID')).takeScreenshot('PrescriptionHealth')
checkImages(tempPath)
await expect(element(by.text('This list may not include all your medications '))).toExist()
@@ -356,12 +366,12 @@ describe('Prescriptions Screen', () => {
),
),
).toExist()
- await element(by.text('Close')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
})
it('verify refill request screen information', async () => {
- await element(by.id('PrescriptionHistory')).scrollTo('top')
- await element(by.text(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_TEXT)).atIndex(0).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID)).scrollTo('top')
+ await element(by.id(CommonE2eIdConstants.PRESCRIPTION_REFILL_BUTTON_ID)).tap()
await expect(element(by.text('Refill request'))).toExist()
await expect(element(by.text('Request refills at least 15 days before you need more medication.'))).toExist()
await expect(
@@ -378,13 +388,13 @@ describe('Prescriptions Screen', () => {
})
it('verify error when nothing is selected for request refills', async () => {
- await element(by.text('Request refills')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REQUEST_REFILL_ID)).tap()
await expect(element(by.text('Please select a prescription'))).toExist()
})
it('verify action sheet for request refill', async () => {
await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_NAME_TEXT)).atIndex(0).tap()
- await element(by.text('Request refill')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REQUEST_REFILL_ID)).tap()
await expect(element(by.text('Request prescription refill?'))).toExist()
if (device.getPlatform() === 'android') {
await element(by.text('Cancel ')).tap()
@@ -394,7 +404,7 @@ describe('Prescriptions Screen', () => {
})
it('verify refill request summary screen information', async () => {
- await element(by.text('Request refill')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REQUEST_REFILL_ID)).tap()
await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap()
await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_REQUEST_SUMMARY_TEXT))).toExist()
await expect(
@@ -425,13 +435,13 @@ describe('Prescriptions Screen', () => {
it('verify user can request refill from get prescriptions details', async () => {
await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_BUTTON_ID)).tap()
await element(by.text('Active (24)')).atIndex(0).tap()
- await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_TEXT)).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_FILTER_APPLY_ID)).tap()
await waitFor(element(by.label('CAPECITABINE 500MG TAB.')))
.toBeVisible()
- .whileElement(by.id('PrescriptionHistory'))
+ .whileElement(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_HISTORY_SCROLL_ID))
.scroll(500, 'down')
await element(by.label(PrescriptionsE2eIdConstants.PRESCRIPTION_DETAILS_LABEL)).atIndex(0).tap()
- await element(by.text('Request refill')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_REQUEST_REFILL_ID)).tap()
await element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_DIALOG_YES_TEXT)).tap()
await expect(element(by.text(PrescriptionsE2eIdConstants.PRESCRIPTION_REFILL_REQUEST_SUMMARY_TEXT))).toExist()
await expect(
@@ -452,7 +462,7 @@ describe('Prescriptions Screen', () => {
})
it('verify tapping close from refill request summary', async () => {
- await element(by.text('Close')).tap()
+ await element(by.id(PrescriptionsE2eIdConstants.PRESCRIPTION_BACK_ID)).tap()
await expect(element(by.text('AMLODIPINE BESYLATE 10MG TAB'))).toExist()
})
@@ -460,16 +470,4 @@ describe('Prescriptions Screen', () => {
validateSort('Medication name (A to Z)', 'ACETAMINOPHEN 325MG TAB', 'ZIPRASIDONE HCL 40MG CAP')
validateSort('Refills left (least to most)', 'ATORVASTATIN CALCIUM 10MG TAB', 'BERNA VACCINE CAP B/P')
validateSort('Status (A to Z)', 'AMLODIPINE BESYLATE 10MG TAB', 'LAMIVUDINE 10MG TAB')
-
- it('should reset mock data', async () => {
- await changeMockData(
- 'prescriptions.json',
- ['/v0/health/rx/prescriptions', { data: 1 }, 'attributes', 'refillStatus'],
- 'refillinprocess',
- )
- await device.launchApp({ newInstance: true })
- await loginToDemoMode()
- await openHealth()
- await openPrescriptions()
- })
})
diff --git a/VAMobile/e2e/tests/PushNotifications.e2e.ts b/VAMobile/e2e/tests/PushNotifications.e2e.ts
index 59b3d3ea733..ec3984364f6 100644
--- a/VAMobile/e2e/tests/PushNotifications.e2e.ts
+++ b/VAMobile/e2e/tests/PushNotifications.e2e.ts
@@ -27,7 +27,7 @@ describe(':ios: Push Notifications', () => {
newInstance: true,
userNotification: mockNotification,
})
- await loginToDemoMode()
+ await loginToDemoMode(true, true)
await waitFor(element(by.text(PushNotificationsConstants.REVIEW_MESSAGE_SCREEN_TITLE)))
.toExist()
.withTimeout(8000)
diff --git a/VAMobile/e2e/tests/SettingsScreen.e2e.ts b/VAMobile/e2e/tests/SettingsScreen.e2e.ts
index 571e0e06737..bfd8fef0703 100644
--- a/VAMobile/e2e/tests/SettingsScreen.e2e.ts
+++ b/VAMobile/e2e/tests/SettingsScreen.e2e.ts
@@ -5,22 +5,26 @@ import { CommonE2eIdConstants, loginToDemoMode, openDismissLeavingAppPopup, open
export const SettingsE2eIdConstants = {
SETTINGS_SCREEN_TEXT: 'Settings',
- MANAGE_ACCT_ROW_TEXT: 'Account security',
+ MANAGE_ACCT_ROW_ID: 'accountSecurityID',
MANAGE_ACCT_SCREEN_TEXT:
'To access or update your sign-in information, go to the website where you manage your account information. Any updates you make there will automatically update on the mobile app.',
- NOTIFICATIONS_ROW_TEXT: 'Notifications',
+ NOTIFICATIONS_ROW_ID: 'notificationsID',
NOTIFICATIONS_SCREEN_TEXT: "We'll send these notifications to your device.",
NOTIFICATIONS_APPOINTMENT_TEXT: 'Appointment reminders',
NOTIFICATIONS_MESSAGING_TEXT: 'New secure messages',
NOTIFICATIONS_SCREEN_SUBTEXT:
"Your privacy is important to us. We won't show any personal information in your notifications.",
- NOTIFICATIONS_LINK_TEXT: 'Manage email and text notifications on VA.gov',
- SHARE_APP_ROW_TEXT: 'Share the app',
+ NOTIFICATIONS_LINK_ID: 'noficationSettingsLinkID',
+ SHARE_APP_ROW_ID: 'shareAppID',
SHARE_APP_SCREEN_TEXT:
'Download the VA: Health and Benefits on the App Store: https://apps.apple.com/us/app/va-health-and-benefits/id1559609596 or on Google Play: https://play.google.com/store/apps/details?id=gov.va.mobileapp',
- PRIVACY_ROW_TEXT: 'Privacy policy',
- SIGN_OUT_BTN_ID: 'Sign out',
+ PRIVACY_ROW_ID: 'privacyPolicyID',
+ SIGN_OUT_BTN_ID: 'signOutButtonID',
SIGN_OUT_CONFIRM_TEXT: device.getPlatform() === 'ios' ? 'Sign Out' : 'Sign Out ',
+ BACK_TO_SETTINGS_SCREEN_ID: 'backToSettingsScreenID',
+ ACCOUNT_SETTINGS_SCREEN_ID: 'accountSecurityScreenID',
+ IN_APP_RECRUITMENT_ID: 'inAppRecruitmentID',
+ IN_APP_RECRUITMENT_QUESTIONNARE_ID: 'goToQuestionnaireID',
}
beforeAll(async () => {
@@ -35,33 +39,32 @@ describe('Settings Screen', () => {
.toExist()
.withTimeout(2000)
- await expect(element(by.text(SettingsE2eIdConstants.MANAGE_ACCT_ROW_TEXT))).toExist()
- await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_ROW_TEXT))).toExist()
- await expect(element(by.text(SettingsE2eIdConstants.SHARE_APP_ROW_TEXT))).toExist()
- await expect(element(by.text(SettingsE2eIdConstants.PRIVACY_ROW_TEXT))).toExist()
+ await expect(element(by.id(SettingsE2eIdConstants.MANAGE_ACCT_ROW_ID))).toExist()
+ await expect(element(by.id(SettingsE2eIdConstants.NOTIFICATIONS_ROW_ID))).toExist()
+ await expect(element(by.id(SettingsE2eIdConstants.SHARE_APP_ROW_ID))).toExist()
+ await expect(element(by.id(SettingsE2eIdConstants.PRIVACY_ROW_ID))).toExist()
})
it('should show "Manage account" screen', async () => {
- await element(by.text(SettingsE2eIdConstants.MANAGE_ACCT_ROW_TEXT)).tap()
- await expect(element(by.text(SettingsE2eIdConstants.MANAGE_ACCT_ROW_TEXT)).atIndex(0)).toExist()
+ await element(by.id(SettingsE2eIdConstants.MANAGE_ACCT_ROW_ID)).tap()
+ await expect(element(by.id(SettingsE2eIdConstants.ACCOUNT_SETTINGS_SCREEN_ID))).toExist()
await expect(element(by.text(SettingsE2eIdConstants.MANAGE_ACCT_SCREEN_TEXT))).toExist()
- await element(by.text(SettingsE2eIdConstants.SETTINGS_SCREEN_TEXT)).tap()
+ await element(by.id(SettingsE2eIdConstants.BACK_TO_SETTINGS_SCREEN_ID)).tap()
})
it('should show "Notifications" screen', async () => {
- await element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_ROW_TEXT)).atIndex(0).tap()
- await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_ROW_TEXT)).atIndex(0)).toExist()
+ await element(by.id(SettingsE2eIdConstants.NOTIFICATIONS_ROW_ID)).tap()
await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_SCREEN_TEXT))).toExist()
await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_APPOINTMENT_TEXT))).toExist()
await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_MESSAGING_TEXT))).toExist()
await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_SCREEN_SUBTEXT))).toExist()
- await expect(element(by.text(SettingsE2eIdConstants.NOTIFICATIONS_LINK_TEXT))).toExist()
- await element(by.text(SettingsE2eIdConstants.SETTINGS_SCREEN_TEXT)).tap()
+ await expect(element(by.id(SettingsE2eIdConstants.NOTIFICATIONS_LINK_ID))).toExist()
+ await element(by.id(SettingsE2eIdConstants.BACK_TO_SETTINGS_SCREEN_ID)).tap()
})
it('should show "Share the app" screen', async () => {
if (device.getPlatform() === 'ios') {
- await element(by.text(SettingsE2eIdConstants.SHARE_APP_ROW_TEXT)).tap()
+ await element(by.id(SettingsE2eIdConstants.SHARE_APP_ROW_ID)).tap()
await device.takeScreenshot('ShareTheAppScreenshot')
await device.launchApp({ newInstance: true })
await loginToDemoMode()
@@ -71,44 +74,21 @@ describe('Settings Screen', () => {
})
it('should show Give feedback screen', async () => {
- try {
- await expect(element(by.text('Give feedback'))).toExist()
- } catch (ex) {
- await element(by.text('Developer Screen')).tap()
- await element(by.text('Remote Config')).tap()
- await waitFor(element(by.text('Override Toggles')))
- .toBeVisible()
- .whileElement(by.id('remoteConfigTestID'))
- .scroll(400, 'down')
- await waitFor(element(by.text('inAppRecruitment')))
- .toBeVisible()
- .whileElement(by.id('remoteConfigTestID'))
- .scroll(100, 'down')
- await element(by.text('inAppRecruitment')).tap()
- await waitFor(element(by.text('Apply Overrides')))
- .toBeVisible()
- .whileElement(by.id('remoteConfigTestID'))
- .scroll(100, 'down')
- await element(by.text('Apply Overrides')).tap()
- await loginToDemoMode()
- await openProfile()
- await openSettings()
- }
- await element(by.text('Give feedback')).tap()
+ await element(by.id(SettingsE2eIdConstants.IN_APP_RECRUITMENT_ID)).tap()
await expect(element(by.text('Make this app better for all Veterans'))).toExist()
await expect(element(by.text('Go to questionnaire'))).toExist()
await expect(element(by.text('Learn more about the Veteran Usability Project'))).toExist()
})
it('should tap on "go to questionnaire" in in app recruitment', async () => {
- await element(by.text('Go to questionnaire')).tap()
+ await element(by.id(SettingsE2eIdConstants.IN_APP_RECRUITMENT_QUESTIONNARE_ID)).tap()
await device.takeScreenshot('inAppRecruitmentQuestionnaire')
await element(by.text('Done')).tap()
- await element(by.text('Close')).tap()
+ await element(by.id(SettingsE2eIdConstants.BACK_TO_SETTINGS_SCREEN_ID)).tap()
})
it('should show Privacy Policy page', async () => {
- await element(by.text(SettingsE2eIdConstants.PRIVACY_ROW_TEXT)).tap()
+ await element(by.id(SettingsE2eIdConstants.PRIVACY_ROW_ID)).tap()
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('SettingsPrivacyPolicy')
@@ -116,17 +96,17 @@ describe('Settings Screen', () => {
})
it('should show and dismiss leaving app popup for privacy', async () => {
- await openDismissLeavingAppPopup(SettingsE2eIdConstants.PRIVACY_ROW_TEXT, true)
+ await openDismissLeavingAppPopup(SettingsE2eIdConstants.PRIVACY_ROW_ID, false)
})
it('should show and dismiss signout popup', async () => {
- await element(by.text(SettingsE2eIdConstants.SIGN_OUT_BTN_ID)).atIndex(0).tap()
+ await element(by.id(SettingsE2eIdConstants.SIGN_OUT_BTN_ID)).atIndex(0).tap()
await expect(element(by.text(SettingsE2eIdConstants.SIGN_OUT_CONFIRM_TEXT))).toExist()
await element(by.text(CommonE2eIdConstants.CANCEL_PLATFORM_SPECIFIC_TEXT)).tap()
})
it('should sign out', async () => {
- await element(by.text(SettingsE2eIdConstants.SIGN_OUT_BTN_ID)).atIndex(0).tap()
+ await element(by.id(SettingsE2eIdConstants.SIGN_OUT_BTN_ID)).atIndex(0).tap()
await element(by.text(SettingsE2eIdConstants.SIGN_OUT_CONFIRM_TEXT)).tap()
await expect(element(by.text(CommonE2eIdConstants.SIGN_IN_BTN_ID))).toExist()
})
diff --git a/VAMobile/e2e/tests/SignIn.e2e.ts b/VAMobile/e2e/tests/SignIn.e2e.ts
index 38249fda11a..30743d6eaee 100644
--- a/VAMobile/e2e/tests/SignIn.e2e.ts
+++ b/VAMobile/e2e/tests/SignIn.e2e.ts
@@ -8,7 +8,7 @@ export const SignE2eIdConstants = {
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_TEXT: "Read more if you haven't yet verified",
+ 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:',
@@ -17,27 +17,36 @@ export const SignE2eIdConstants = {
describe('Sign In', () => {
it('should show sign in page content', async () => {
- await waitFor(element(by.id(SignE2eIdConstants.LOGIN_PAGE_ID)))
- .toExist()
- .withTimeout(20000)
+ try {
+ await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
+ .toExist()
+ .withTimeout(120000)
+ } catch (ex) {
+ await device.uninstallApp()
+ await device.installApp()
+ await device.launchApp({ newInstance: true, permissions: { notifications: 'YES' } })
+ await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
+ .toExist()
+ .withTimeout(60000)
+ }
await element(by.id(CommonE2eIdConstants.SIGN_IN_BTN_ID)).tap()
- await expect(element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT))).toExist()
+ 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.text(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_TEXT))).toExist()
+ await expect(element(by.id(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_ID))).toExist()
await expect(element(by.id(SignE2eIdConstants.CONTINUE_SIGN_IN_BTN_ID))).toExist()
})
it(':ios: should show webview with log in options', async () => {
await element(by.text('Close')).tap()
await element(by.id(CommonE2eIdConstants.SIGN_IN_BTN_ID)).tap()
- await element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT)).tap()
- await element(by.text('Done')).tap()
- await element(by.text(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_TEXT)).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.text(SignE2eIdConstants.LOA_GATE_EXPAND_MSG_TEXT)).tap()
+ 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()
diff --git a/VAMobile/e2e/tests/VALetters.e2e.ts b/VAMobile/e2e/tests/VALetters.e2e.ts
index 679c883c257..75b5f59b35d 100644
--- a/VAMobile/e2e/tests/VALetters.e2e.ts
+++ b/VAMobile/e2e/tests/VALetters.e2e.ts
@@ -16,6 +16,11 @@ export const LettersConstants = {
MAILING_ADDRESS: '3101 N Fort Valley Rd',
DOWNLOAD_DOCUMENTS_TEXT: 'Downloaded documents will list your address as:',
LETTER_FILE_NAME: 'demo_mode_benefit_summary',
+ LETTER_REVIEW_LETTERS_BUTTON_ID: 'lettersOverviewViewLettersButtonID',
+ LETTER_BENEFIT_SUMMARY_ROW_ID: 'BenefitSummaryServiceVerificationTestID',
+ LETTER_BENEFIT_SUMMARY_ASK_VA_LINK_ID: 'lettersBenefitServiceGoToAskVAID',
+ LETTER_BENEFIT_SUMMARY_BACK_ID: 'BenefitSummaryServiceVerificationBackID',
+ LETTER_BENEFIT_SUMMARY_VIEW_LETTER_ID: 'lettersBenefitServiceViewLetterID',
LETTER_TYPES: [
{
name: 'Benefit summary and service verification letter',
@@ -75,18 +80,18 @@ describe('VA Letters', () => {
it('should tap address and open edit screen', async () => {
await element(by.text(LettersConstants.MAILING_ADDRESS)).tap()
- await element(by.id('streetAddressLine2TestID')).typeText('2')
- await element(by.id('streetAddressLine2TestID')).tapReturnKey()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_STREET_ADDRESS_LINE_2_ID)).typeText('2')
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_STREET_ADDRESS_LINE_2_ID)).tapReturnKey()
- await element(by.text('Save')).tap()
- await element(by.id('suggestedAddressTestID')).tap()
- await element(by.id('Use this address')).tap()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SAVE_ID)).tap()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SUGGESTED_ADDRESS_ID)).tap()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_USE_THIS_ADDRESS_ID)).tap()
await expect(element(by.text(LettersConstants.DOWNLOAD_DOCUMENTS_TEXT))).toExist()
})
it('should verify address change is reflected in contact info', async () => {
- await element(by.text('Home')).tap()
+ await element(by.id('Home')).tap()
await openProfile()
await openContactInfo()
await expect(element(by.text('3101 N Fort Valley Rd, 2'))).toExist()
@@ -96,15 +101,15 @@ describe('VA Letters', () => {
await openBenefits()
await element(by.text('3101 N Fort Valley Rd, 2')).tap()
- await element(by.id('streetAddressLine2TestID')).clearText()
- await element(by.text('Save')).tap()
- await element(by.id('suggestedAddressTestID')).tap()
- await element(by.id('Use this address')).tap()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_STREET_ADDRESS_LINE_2_ID)).clearText()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SAVE_ID)).tap()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_SUGGESTED_ADDRESS_ID)).tap()
+ await element(by.id(CommonE2eIdConstants.CONTACT_INFO_USE_THIS_ADDRESS_ID)).tap()
await expect(element(by.text(LettersConstants.MAILING_ADDRESS))).toExist()
})
it('should view letter types', async () => {
- await element(by.text('Review letters')).tap()
+ await element(by.id(LettersConstants.LETTER_REVIEW_LETTERS_BUTTON_ID)).tap()
for (const letterType of LettersConstants.LETTER_TYPES) {
await expect(element(by.text(letterType.name))).toExist()
@@ -113,35 +118,28 @@ describe('VA Letters', () => {
for (const letterType of LettersConstants.LETTER_TYPES) {
it(`should view ${letterType.name}`, async () => {
- // need in-app reset in iOS before checking proof of service card to avoid false fail
- if (device.getPlatform() === 'ios' && letterType.name === 'Proof of minimum essential coverage letter') {
- await openBenefits()
- await openLetters()
- await element(by.text('Review letters')).tap()
- }
-
await element(by.text(letterType.name)).tap()
await expect(element(by.text(letterType.name))).toExist()
await expect(element(by.text(letterType.description))).toExist()
if (device.getPlatform() === 'ios') {
- const isBenefitSummaryLetter = await checkIfElementIsPresent('BenefitSummaryServiceVerificationTestID')
+ const isBenefitSummaryLetter = await checkIfElementIsPresent(LettersConstants.LETTER_BENEFIT_SUMMARY_ROW_ID)
if (isBenefitSummaryLetter) {
- await element(by.id('BenefitSummaryServiceVerificationTestID')).scrollTo('bottom')
- await element(by.text('Go to Ask VA')).tap()
+ await element(by.id(LettersConstants.LETTER_BENEFIT_SUMMARY_ROW_ID)).scrollTo('bottom')
+ await element(by.id(LettersConstants.LETTER_BENEFIT_SUMMARY_ASK_VA_LINK_ID)).tap()
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(2000)
await device.takeScreenshot('benefitSummaryLetterAskVAWebpage')
await device.launchApp({ newInstance: false })
}
- await element(by.text('Review letter')).tap()
+ await element(by.id(LettersConstants.LETTER_BENEFIT_SUMMARY_VIEW_LETTER_ID)).tap()
await expect(element(by.text(LettersConstants.LETTER_FILE_NAME))).toExist()
await element(by.text('Done')).tap()
}
- await element(by.text('Review letters')).tap()
+ await element(by.id(LettersConstants.LETTER_BENEFIT_SUMMARY_BACK_ID)).tap()
})
}
})
diff --git a/VAMobile/e2e/tests/VaccineRecords.e2e.ts b/VAMobile/e2e/tests/VaccineRecords.e2e.ts
index 6b3eddf7234..e967e48f331 100644
--- a/VAMobile/e2e/tests/VaccineRecords.e2e.ts
+++ b/VAMobile/e2e/tests/VaccineRecords.e2e.ts
@@ -8,6 +8,7 @@ export const VaccinesE2eIdConstants = {
VACCINE_3_ID: 'FLU vaccine May 10, 2018',
VACCINE_5_ID: 'PneumoPPV vaccine April 28, 2016',
VACCINE_6_ID: 'FLU vaccine April 28, 2016',
+ VACCINE_DETAILS_BACK_ID: 'vaccinesDetailsBackID',
}
beforeAll(async () => {
@@ -54,7 +55,7 @@ describe('Vaccine Records Screen', () => {
})
it('should tap on VA vaccines and navigate back to the vaccines list', async () => {
- await element(by.text('VA vaccines')).tap()
+ await element(by.id(VaccinesE2eIdConstants.VACCINE_DETAILS_BACK_ID)).tap()
})
it('verify no disclaimer is displayed when all fields are populated', async () => {
@@ -67,12 +68,12 @@ describe('Vaccine Records Screen', () => {
),
),
).not.toExist()
- await element(by.text('VA vaccines')).tap()
+ await element(by.id(VaccinesE2eIdConstants.VACCINE_DETAILS_BACK_ID)).tap()
})
it('verify no manufacturer for non COVID-19 record', async () => {
await element(by.id(VaccinesE2eIdConstants.VACCINE_3_ID)).tap()
await expect(element(by.text('Manufacturer'))).not.toExist()
- await element(by.text('VA vaccines')).tap()
+ await element(by.id(VaccinesE2eIdConstants.VACCINE_DETAILS_BACK_ID)).tap()
})
})
diff --git a/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts b/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts
index 0c97fd959de..a3ed4bcb3b0 100644
--- a/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts
+++ b/VAMobile/e2e/tests/VeteranStatusCard.e2e.ts
@@ -2,6 +2,7 @@ import { by, device, element, expect, waitFor } from 'detox'
import { setTimeout } from 'timers/promises'
import {
+ CommonE2eIdConstants,
changeMockData,
checkImages,
loginToDemoMode,
@@ -13,7 +14,7 @@ import {
} from './utils'
export const VeteranStatusCardConstants = {
- VETERAN_STATUS_TEXT: 'Proof of Veteran status',
+ 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',
@@ -24,8 +25,9 @@ export const VeteranStatusCardConstants = {
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.",
VETERAN_STATUS_DOB_DISABILITY_ERROR_PHONE_TEXT: '800-827-1000',
- VETERAN_STATUS_DOB_DISABILITY_ERROR_TTY_TEXT: 'TTY: 711',
VETERAN_STATUS_PERIOD_OF_SERVICE_ERROR_PHONE_TEXT: '800-538-9552',
+ VETERAN_STATUS_CLOSE_ID: 'veteranStatusCloseID',
+ BACK_TO_PROFILE_ID: 'backToProfileID',
}
beforeAll(async () => {
@@ -45,9 +47,7 @@ export async function validateVeteranStatusDesign() {
await expect(element(by.id('veteranStatusDOBTestID'))).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.text(VeteranStatusCardConstants.VETERAN_STATUS_DOB_DISABILITY_ERROR_TTY_TEXT)).atIndex(0),
- ).toExist()
+ await expect(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0)).toExist()
await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_ERROR_PHONE_TEXT))).toExist()
const veteranStatusCardBranchIcon = await element(by.id('veteranStatusCardBranchEmblem')).takeScreenshot(
'veteranStatusCardBranchIcon',
@@ -62,19 +62,19 @@ export async function tapPhoneAndTTYLinks() {
.toBeVisible()
.whileElement(by.id('veteranStatusTestID'))
.scroll(200, 'down')
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DOB_DISABILITY_ERROR_PHONE_TEXT)).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(0).tap()
await setTimeout(1000)
await device.takeScreenshot('VeteranStatusDOBorDisabilityErrorPhoneNumber')
await device.launchApp({ newInstance: false })
- await waitFor(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DOB_DISABILITY_ERROR_TTY_TEXT)).atIndex(0))
+ await waitFor(element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0))
.toBeVisible()
.whileElement(by.id('veteranStatusTestID'))
.scroll(200, 'down')
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DOB_DISABILITY_ERROR_TTY_TEXT)).atIndex(0).tap()
+ 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(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_ERROR_PHONE_TEXT)).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_TTY_PHONE_NUMBER_ID)).atIndex(0).tap()
} catch (e) {}
await setTimeout(2000)
await device.takeScreenshot('VeteranStatusDOBorDisabilityErrorTTY')
@@ -84,7 +84,7 @@ export async function tapPhoneAndTTYLinks() {
.toBeVisible()
.whileElement(by.id('veteranStatusTestID'))
.scroll(200, 'down')
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_ERROR_PHONE_TEXT)).tap()
+ await element(by.id(CommonE2eIdConstants.CALL_VA_PHONE_NUMBER_ID)).atIndex(1).tap()
await setTimeout(2000)
await device.takeScreenshot('VeteranStatusPeriodOfServiceErrorPhoneNumber')
await device.launchApp({ newInstance: false })
@@ -100,39 +100,39 @@ export async function verifyMilitaryInfo(militaryBranch) {
militaryBranch,
)
await element(by.text('Home')).tap()
- await waitFor(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)))
+ await waitFor(element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)))
.toBeVisible()
.whileElement(by.id('homeScreenID'))
.scroll(200, 'down')
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap()
await expect(element(by.text(militaryBranch)).atIndex(1)).toExist()
- await element(by.text('Close')).tap()
- await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT))).toExist()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap()
+ await expect(element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID))).toExist()
await expect(element(by.text(militaryBranch))).toExist()
await openProfile()
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap()
await expect(element(by.text(militaryBranch)).atIndex(1)).toExist()
- await element(by.text('Close')).tap()
- await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT))).toExist()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap()
+ await expect(element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID))).toExist()
await expect(element(by.text(militaryBranch))).toExist()
})
}
describe('Veteran Status Card', () => {
it('should match design in the home screen', async () => {
- await waitFor(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)))
+ await waitFor(element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)))
.toBeVisible()
.whileElement(by.id('homeScreenID'))
.scroll(200, 'down')
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap()
await validateVeteranStatusDesign()
})
tapPhoneAndTTYLinks()
it('should match design in the profile screen', async () => {
- await element(by.text('Close')).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap()
await openProfile()
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap()
await validateVeteranStatusDesign()
})
@@ -143,28 +143,28 @@ describe('Veteran Status Card', () => {
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(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_2_TEXT))).toExist()
- await element(by.text('Close')).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap()
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(VeteranStatusCardConstants.VETERAN_STATUS_PERIOD_OF_SERVICE_PERIOD_2_TEXT))).toExist()
- await element(by.text('Profile')).tap()
+ await element(by.id(VeteranStatusCardConstants.BACK_TO_PROFILE_ID)).tap()
})
it('verify the date of birth matches the dob in the app', async () => {
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap()
await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DATE_OF_BIRTH_TEXT))).toExist()
- await element(by.text('Close')).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap()
await openPersonalInformation()
await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DATE_OF_BIRTH_TEXT))).toExist()
- await element(by.text('Profile')).tap()
+ await element(by.id(VeteranStatusCardConstants.BACK_TO_PROFILE_ID)).tap()
})
it('verify the disability rating matches the app', async () => {
- await element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_TEXT)).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_ID)).tap()
await expect(element(by.text(VeteranStatusCardConstants.VETERAN_STATUS_DISABILITY_RATING_TEXT))).toExist()
- await element(by.text('Close')).tap()
+ await element(by.id(VeteranStatusCardConstants.VETERAN_STATUS_CLOSE_ID)).tap()
await openBenefits()
await openDisabilityRating()
await expect(element(by.text('100%')).atIndex(1)).toExist()
diff --git a/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts b/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts
index 6a39ea673c7..56240e7715e 100644
--- a/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts
+++ b/VAMobile/e2e/tests/VeteransCrisisLine.e2e.ts
@@ -10,17 +10,18 @@ export const VCLConstants = {
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_TEXT: 'Call 988 and select 1',
- TEXT_MESSAGE_LINK_TEXT: 'Text 838255',
- CHAT_LINK_TEXT: 'Start a confidential chat',
- TTY_LINK_TEXT: 'TTY: 800-799-4889',
+ 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_TEXT: 'VeteransCrisisLine.net',
+ VCL_SITE_LINK_ID: 'veteransCrisisLineGetMoreResourcesTestID',
+ BACK_ID: 'veteranCrisisLineBackID',
}
const tapAndTakeScreenshot = async (text: string, screenshotName: string) => {
await device.disableSynchronization()
- await element(by.text(text)).tap()
+ await element(by.id(text)).tap()
await setTimeout(5000)
await device.takeScreenshot(screenshotName)
await device.launchApp({ newInstance: false })
@@ -42,19 +43,19 @@ describe('Veterans Crisis Line', () => {
if (device.getPlatform() === 'android') {
it('should open phone link', async () => {
- await tapAndTakeScreenshot(VCLConstants.PHONE_LINK_TEXT, 'CrisisLinePhone')
+ await tapAndTakeScreenshot(VCLConstants.PHONE_LINK_ID, 'CrisisLinePhone')
})
it('should open TTY link', async () => {
- await tapAndTakeScreenshot(VCLConstants.TTY_LINK_TEXT, 'CrisisLineTTY')
+ await tapAndTakeScreenshot(VCLConstants.TTY_LINK_ID, 'CrisisLineTTY')
})
}
it('should open text message link', async () => {
- await tapAndTakeScreenshot(VCLConstants.TEXT_MESSAGE_LINK_TEXT, 'CrisisLineTextMessage')
+ await tapAndTakeScreenshot(VCLConstants.TEXT_MESSAGE_LINK_ID, 'CrisisLineTextMessage')
})
it('should open chat link', async () => {
- await element(by.text(VCLConstants.CHAT_LINK_TEXT)).tap()
+ await element(by.id(VCLConstants.CHAT_LINK_ID)).tap()
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('CrisisLineChat')
@@ -62,7 +63,7 @@ describe('Veterans Crisis Line', () => {
})
it('should open website link', async () => {
- await element(by.text(VCLConstants.VCL_SITE_LINK_TEXT)).tap()
+ await element(by.id(VCLConstants.VCL_SITE_LINK_ID)).tap()
await element(by.text(CommonE2eIdConstants.LEAVING_APP_LEAVE_TEXT)).tap()
await setTimeout(5000)
await device.takeScreenshot('VCLWebsite')
@@ -70,7 +71,7 @@ describe('Veterans Crisis Line', () => {
})
it('should close panel', async () => {
- await element(by.text('Done')).tap()
+ await element(by.id(VCLConstants.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 760e58ec147..2b0baf4b7d5 100644
--- a/VAMobile/e2e/tests/utils.ts
+++ b/VAMobile/e2e/tests/utils.ts
@@ -11,6 +11,16 @@ const fs = require('fs')
jestExpect.extend({ toMatchImageSnapshot })
const { DEMO_PASSWORD } = getEnv()
+const mockNotification = {
+ trigger: {
+ type: 'push',
+ },
+ title: 'New Secure Message',
+ body: 'Review your messages in the health care section of the VA app',
+ payload: {
+ url: 'vamobile://messages/2092809',
+ },
+}
export const CommonE2eIdConstants = {
VA_LOGO_ICON_ID: 'va-icon',
@@ -19,6 +29,8 @@ export const CommonE2eIdConstants = {
SIGN_IN_BTN_ID: 'Sign in',
SKIP_BTN_TEXT: 'Skip',
VETERAN_CRISIS_LINE_BTN_TEXT: 'Talk to the Veterans Crisis Line now',
+ VETERAN_CRISIS_LINE_BTN_ID: 'veteransCrisisLineID',
+ VETERAN_CRISIS_LINE_BACK_ID: 'veteranCrisisLineBackID',
PROFILE_TAB_BUTTON_TEXT: 'Profile',
HEALTH_TAB_BUTTON_TEXT: 'Health',
APPOINTMENTS_TAB_BUTTON_TEXT: 'Appointments',
@@ -54,6 +66,7 @@ export const CommonE2eIdConstants = {
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',
@@ -66,22 +79,40 @@ export const CommonE2eIdConstants = {
GO_TO_VA_GOV_LINK_ID: 'goToVAGovID',
CLAIMS_HISTORY_SCROLL_ID: 'claimsHistoryID',
NEXT_PAGE_ID: 'next-page',
+ 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',
}
/** Log the automation into demo mode
* */
-export async function loginToDemoMode(skipOnboarding = true) {
- await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
- .toExist()
- .withTimeout(60000)
+export async function loginToDemoMode(skipOnboarding = true, pushNotifications?: boolean) {
try {
- await element(
- by.text(
- "[react-native-gesture-handler] Seems like you're using an old API with gesture components, check out new Gestures system!",
- ),
- ).tap()
- await element(by.text('Dismiss')).tap()
- } catch (e) {}
+ await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
+ .toExist()
+ .withTimeout(120000)
+ } catch (ex) {
+ await device.uninstallApp()
+ await device.installApp()
+ if (pushNotifications) {
+ await device.launchApp({
+ delete: true,
+ permissions: { notifications: 'YES' },
+ newInstance: true,
+ userNotification: mockNotification,
+ })
+ } else {
+ await device.launchApp({ newInstance: true, permissions: { notifications: 'YES' } })
+ }
+ await waitFor(element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)))
+ .toExist()
+ .withTimeout(60000)
+ }
await element(by.id(CommonE2eIdConstants.VA_LOGO_ICON_ID)).multiTap(7)
if (DEMO_PASSWORD !== undefined) {
@@ -261,7 +292,7 @@ export async function checkImages(screenshotPath) {
* And can have a more specific & readable name for each function
*/
export async function openVeteransCrisisLine() {
- await element(by.text(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_TEXT)).tap()
+ await element(by.id(CommonE2eIdConstants.VETERAN_CRISIS_LINE_BTN_ID)).tap()
}
export async function openProfile() {
diff --git a/VAMobile/env/constant.env b/VAMobile/env/constant.env
index c441478098b..d912e23ce81 100644
--- a/VAMobile/env/constant.env
+++ b/VAMobile/env/constant.env
@@ -1,13 +1,13 @@
WEBVIEW_URL_CHANGE_LEGAL_NAME=https://www.va.gov/resources/how-to-change-your-legal-name-on-file-with-va/
WEBVIEW_URL_CORONA_FAQ=https://www.va.gov/coronavirus-veteran-frequently-asked-questions
WEBVIEW_URL_FACILITY_LOCATOR=https://www.va.gov/find-locations/
+WEBVIEW_URL_WHAT_TO_BRING_TO_APPOINTMENTS=https://www.va.gov/resources/what-should-i-bring-to-my-health-care-appointments/
LINK_URL_VA_NOTIFICATIONS=https://www.va.gov/profile/notifications/
LINK_URL_VA_SCHEDULING=https://www.va.gov/health-care/schedule-view-va-appointments/
LINK_URL_IN_APP_RECRUITMENT=https://docs.google.com/forms/d/e/1FAIpQLSfRb0OtW34qKm8tGoQwwwDFs8IqwOMCLTde3DeM-ukKOEZBnA/viewform
LINK_URL_VETERAN_USABILITY_PROJECT=https://veteranusability.us/
LINK_URL_VETERANS_CRISIS_LINE=https://www.veteranscrisisline.net/
LINK_URL_VETERANS_CRISIS_LINE_GET_HELP=https://www.veteranscrisisline.net/get-help/chat
-LINK_URL_SCHEDULE_APPOINTMENTS=https://www.va.gov/health-care/schedule-view-va-appointments/
LINK_URL_PRIVACY_POLICY=https://www.va.gov/privacy-policy/
LINK_URL_DECISION_REVIEWS=https://www.va.gov/decision-reviews/
LINK_URL_ABOUT_DISABILITY_RATINGS=https://www.va.gov/disability/about-disability-ratings/
diff --git a/VAMobile/env/env.sh b/VAMobile/env/env.sh
index a535026880f..53878600a7e 100755
--- a/VAMobile/env/env.sh
+++ b/VAMobile/env/env.sh
@@ -15,7 +15,7 @@ echo "" > .env
if [[ $environment == 'staging' ]]
then
echo "Setting up Staging environment"
- AUTH_SIS_PREFIX="staging."
+ WEBSITE_PREFIX="staging."
API_PREFIX="staging-api."
else
echo "Setting up Production environment"
@@ -27,7 +27,7 @@ echo "ENVIRONMENT=$environment" >> .env
echo "API_ROOT=https://${API_PREFIX}va.gov/mobile" >> .env
# set SIS vars
-AUTH_SIS_ROOT="https://${AUTH_SIS_PREFIX}va.gov"
+AUTH_SIS_ROOT="https://${WEBSITE_PREFIX}va.gov"
echo "AUTH_SIS_ENDPOINT=${AUTH_SIS_ROOT}/sign-in" >> .env
echo "AUTH_SIS_TOKEN_EXCHANGE_URL=https://${API_PREFIX}va.gov/v0/sign_in/token" >> .env
echo "AUTH_SIS_TOKEN_REFRESH_URL=https://${API_PREFIX}va.gov/v0/sign_in/refresh" >> .env
@@ -50,6 +50,10 @@ else
fi
# set demo mode password
echo "DEMO_PASSWORD=${DEMO_PASSWORD}" >> .env
+
+# set website URLs
+echo "LINK_URL_SCHEDULE_APPOINTMENTS=https://${WEBSITE_PREFIX}va.gov/health-care/schedule-view-va-appointments" >> .env
+
# Get all vars that are the same across environments
while read p; do
echo "$p" >> .env
diff --git a/VAMobile/ios/Gemfile.lock b/VAMobile/ios/Gemfile.lock
index a669ef38020..50e26862d8d 100644
--- a/VAMobile/ios/Gemfile.lock
+++ b/VAMobile/ios/Gemfile.lock
@@ -5,7 +5,7 @@ GEM
base64
nkf
rexml
- activesupport (7.2.1)
+ activesupport (7.2.1.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
@@ -24,7 +24,7 @@ GEM
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.0)
- aws-partitions (1.982.0)
+ aws-partitions (1.991.0)
aws-sdk-core (3.209.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
@@ -33,7 +33,7 @@ GEM
aws-sdk-kms (1.94.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.166.0)
+ aws-sdk-s3 (1.167.0)
aws-sdk-core (~> 3, >= 3.207.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
@@ -126,7 +126,7 @@ GEM
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.3.1)
- fastlane (2.223.1)
+ fastlane (2.224.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -217,7 +217,7 @@ GEM
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.7.2)
- jwt (2.9.1)
+ jwt (2.9.3)
base64
logger (1.6.1)
mini_magick (4.13.2)
@@ -274,13 +274,13 @@ GEM
xcode-install (2.8.1)
claide (>= 0.9.1)
fastlane (>= 2.1.0, < 3.0.0)
- xcodeproj (1.25.0)
+ xcodeproj (1.25.1)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
- rexml (>= 3.3.2, < 4.0)
+ rexml (>= 3.3.6, < 4.0)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
diff --git a/VAMobile/ios/Podfile.lock b/VAMobile/ios/Podfile.lock
index 85ebac1bbd7..6fc01d9a335 100644
--- a/VAMobile/ios/Podfile.lock
+++ b/VAMobile/ios/Podfile.lock
@@ -1396,6 +1396,8 @@ PODS:
- Yoga
- react-native-blob-util (0.19.11):
- React-Core
+ - react-native-cookies (6.2.1):
+ - React-Core
- react-native-document-picker (8.2.2):
- React-Core
- react-native-image-picker (7.1.2):
@@ -1845,6 +1847,7 @@ DEPENDENCIES:
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-blob-util (from `../node_modules/react-native-blob-util`)
+ - "react-native-cookies (from `../node_modules/@react-native-cookies/cookies`)"
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
- react-native-notifications (from `../node_modules/react-native-notifications`)
@@ -1998,6 +2001,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
react-native-blob-util:
:path: "../node_modules/react-native-blob-util"
+ react-native-cookies:
+ :path: "../node_modules/@react-native-cookies/cookies"
react-native-document-picker:
:path: "../node_modules/react-native-document-picker"
react-native-image-picker:
@@ -2097,7 +2102,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: 4cb898d0bf20404aab1850c656dcea009429d6c1
- DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
+ DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
FBLazyVector: 7b438dceb9f904bd85ca3c31d64cce32a035472b
Firebase: 10c8cb12fb7ad2ae0c09ffc86cd9c1ab392a0031
FirebaseABTesting: d87f56707159bae64e269757a6e963d490f2eebe
@@ -2113,7 +2118,7 @@ SPEC CHECKSUMS:
FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc
FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
- glog: 69ef571f3de08433d766d614c73a9838a06bf7eb
+ glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
GoogleAppMeasurement: bb3c564c3efb933136af0e94899e0a46167466a8
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
@@ -2155,6 +2160,7 @@ SPEC CHECKSUMS:
React-Mapbuffer: 714f2fae68edcabfc332b754e9fbaa8cfc68fdd4
React-microtasksnativemodule: 4943ad8f99be8ccf5a63329fa7d269816609df9e
react-native-blob-util: 39a20f2ef11556d958dc4beb0aa07d1ef2690745
+ react-native-cookies: f54fcded06bb0cda05c11d86788020b43528a26c
react-native-document-picker: cd4d6b36a5207ad7a9e599ebb9eb0c2e84fa0b87
react-native-image-picker: 2fbbafdae7a7c6db9d25df2f2b1db4442d2ca2ad
react-native-notifications: 4601a5a8db4ced6ae7cfc43b44d35fe437ac50c4
@@ -2205,7 +2211,7 @@ SPEC CHECKSUMS:
SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
- Yoga: 4ef80d96a5534f0e01b3055f17d1e19a9fc61b63
+ Yoga: 1354c027ab07c7736f99a3bef16172d6f1b12b47
PODFILE CHECKSUM: 528e5ac3a06c35c8645d8271610e36fdcca33735
diff --git a/VAMobile/ios/RNAuthSession.swift b/VAMobile/ios/RNAuthSession.swift
index efc30a76718..9c38c303c45 100644
--- a/VAMobile/ios/RNAuthSession.swift
+++ b/VAMobile/ios/RNAuthSession.swift
@@ -36,6 +36,7 @@ class RNAuthSession: NSObject, RCTBridgeModule, ASWebAuthenticationPresentationC
URLQueryItem(name: "code_challenge", value: codeChallenge),
URLQueryItem(name: "application", value: "vamobile"),
URLQueryItem(name: "oauth", value: "true"),
+ URLQueryItem(name: "scope", value: "device_sso"),
]
guard var comps = URLComponents(string: authUrl) else {
diff --git a/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj b/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj
index 3c3265b20ed..f2407c8c94f 100644
--- a/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj
+++ b/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj
@@ -495,7 +495,6 @@
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
- "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/react-native-blob-util/ReactNativeBlobUtilPrivacyInfo.bundle",
);
name = "[CP] Copy Pods Resources";
@@ -513,7 +512,6 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
- "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReactNativeBlobUtilPrivacyInfo.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
@@ -554,7 +552,6 @@
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
- "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/react-native-blob-util/ReactNativeBlobUtilPrivacyInfo.bundle",
);
name = "[CP] Copy Pods Resources";
@@ -572,7 +569,6 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
- "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReactNativeBlobUtilPrivacyInfo.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
diff --git a/VAMobile/jest/testSetup.ts b/VAMobile/jest/testSetup.ts
index 8b601fee7e3..89fa935594f 100644
--- a/VAMobile/jest/testSetup.ts
+++ b/VAMobile/jest/testSetup.ts
@@ -200,6 +200,14 @@ jest.mock('react-native-file-viewer', () => {
}
})
+jest.mock('@react-native-cookies/cookies', () => {
+ return {
+ clearAll: jest.fn(),
+ get: jest.fn(),
+ setFromResponse: jest.fn(),
+ }
+})
+
jest.mock('@react-native-firebase/analytics', () => {
return jest.fn(() => {
return {
diff --git a/VAMobile/package.json b/VAMobile/package.json
index 4911886f38b..fef0af36993 100644
--- a/VAMobile/package.json
+++ b/VAMobile/package.json
@@ -39,9 +39,10 @@
"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.16.0",
+ "@department-of-veterans-affairs/mobile-tokens": "0.17.1",
"@expo/react-native-action-sheet": "^4.1.0",
- "@react-native-async-storage/async-storage": "^1.23.1",
+ "@react-native-async-storage/async-storage": "^1.24.0",
+ "@react-native-cookies/cookies": "^6.2.1",
"@react-native-firebase/analytics": "^18.9.0",
"@react-native-firebase/app": "^18.9.0",
"@react-native-firebase/crashlytics": "^18.9.0",
@@ -51,7 +52,7 @@
"@react-navigation/bottom-tabs": "^6.6.1",
"@react-navigation/native": "^6.1.18",
"@react-navigation/stack": "^6.4.1",
- "@reduxjs/toolkit": "^2.2.7",
+ "@reduxjs/toolkit": "^2.2.8",
"@tanstack/react-query": "^5.56.2",
"eslint-plugin-tsdoc": "^0.3.0",
"i18next": "^23.7.18",
@@ -73,7 +74,7 @@
"react-native-image-picker": "^7.1.2",
"react-native-keyboard-manager": "^6.5.11-2",
"react-native-keychain": "^8.2.0",
- "react-native-localize": "^3.1.0",
+ "react-native-localize": "^3.2.1",
"react-native-notifications": "^5.1.0",
"react-native-safe-area-context": "^4.10.9",
"react-native-screens": "^3.34.0",
@@ -92,10 +93,10 @@
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-env": "^7.24.8",
- "@babel/preset-typescript": "^7.24.7",
+ "@babel/preset-typescript": "^7.25.7",
"@babel/runtime": "^7.24.8",
"@department-of-veterans-affairs/eslint-config-mobile": "0.15.0",
- "@react-native/babel-preset": "0.75.3",
+ "@react-native/babel-preset": "0.75.4",
"@react-native/eslint-config": "^0.75.3",
"@react-native/metro-config": "^0.75.3",
"@react-native/typescript-config": "0.75.3",
@@ -123,7 +124,7 @@
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-prettier": "^5.2.1",
- "eslint-plugin-react": "^7.37.0",
+ "eslint-plugin-react": "^7.37.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-native": "^4.1.0",
"husky": "^9.1.6",
@@ -134,7 +135,7 @@
"jest-when": "^3.6.0",
"lint-staged": "^15.2.9",
"metro-react-native-babel-preset": "^0.77.0",
- "prettier": "^3.3.2",
+ "prettier": "^3.3.3",
"react-devtools": "^5.3.1",
"react-test-renderer": "^18.3.1",
"redux-mock-store": "^1.5.4",
diff --git a/VAMobile/release_branch.sh b/VAMobile/release_branch.sh
index 8ebb547ee04..3b21ec27a47 100755
--- a/VAMobile/release_branch.sh
+++ b/VAMobile/release_branch.sh
@@ -14,16 +14,16 @@ Help() {
echo "Release branch automation script"
echo
echo "This script does the following:"
- echo "1. Checks the date to see if it occurs at a 2 week interval from August 4, 2021. (If this is true, then we should cut a release branch from develop"
+ echo "1. Checks the date to see if it occurs at a 2 week interval from August 4, 2021. (If this is true, then we should cut a release branch from develop). unless the --bypass-date-check flag is passed"
echo "2. Checks out the main branch, then pulls the latest tag."
echo "3. Increments the latest tag by the minor version to get the next release version number"
echo "4. Checks out and pulls latest develop branch"
echo "5. Creates a new release branch with the correct name and pushes it up to the origin"
echo
- echo "Syntax: ./release_branch.sh [-h]"
+ echo "Syntax: ./release_branch.sh [-h] [--bypass-date-check]"
+ echo "--bypass-date-check Bypass the date check."
}
-
### Increments the part of the string
## $1: version itself
## $2: number of part: 0 – major, 1 – minor, 2 – patch
@@ -37,18 +37,32 @@ increment_version() {
echo $(local IFS=$delimiter ; echo "${array[*]}")
}
-
#### Process the options
-
-while getopts h option
- do case "${option}" in
- h) Help; exit ;;
- *) echo "Invalid option -${option}"; exit ;;
+bypass_date_check=false # Initialize variable
+
+while [[ $# -gt 0 ]]
+do
+ key="$1"
+
+ case $key in
+ -h|--help)
+ Help
+ exit 0
+ ;;
+ --bypass-date-check)
+ bypass_date_check=true
+ shift # past argument
+ ;;
+ *)
+ echo "Invalid option: $1"
+ exit 1
+ ;;
esac
done
-# First release branch was 08-04-2021. check and see that we are at TWO WEEK interval (14 days)
-if [[ $[$((($(date +%s)-$(date +%s --date "2021-08-04"))/(3600*24)))%14] == 0 ]]
+# First release branch was 08-04-2021. check and see that we are at TWO WEEK interval (14 days) unless the --bypass-date-check flag is passed
+#if [[ "$bypass_date_check" == true ]] || [[ $[$((($(gdate +%s)-$(gdate +%s --date "2021-08-04"))/(3600*24)))%14] == 0 ]] #Used to test locally on mac
+if [[ "$bypass_date_check" == true ]] || [[ $[$((($(date +%s)-$(date +%s --date "2021-08-04"))/(3600*24)))%14] == 0 ]]
then
echo "Checking out and pulling latest from main branch"
@@ -84,4 +98,4 @@ then
else
echo "Not scheduled for new release branch this week. Exiting."
exit 0
-fi
+fi
\ No newline at end of file
diff --git a/VAMobile/src/components/AccordionCollapsible.test.tsx b/VAMobile/src/components/AccordionCollapsible.test.tsx
index 61666ade009..f14d31bf5d7 100644
--- a/VAMobile/src/components/AccordionCollapsible.test.tsx
+++ b/VAMobile/src/components/AccordionCollapsible.test.tsx
@@ -9,11 +9,10 @@ import Mock = jest.Mock
context('AccordionCollapsible', () => {
let onPressSpy: Mock
- const initializeTestInstance = (hideArrow = false, expandedInitialValue = false) => {
+ const initializeTestInstance = (expandedInitialValue = false) => {
onPressSpy = jest.fn(() => {})
render(
HEADER}
expandedContent={EXPANDED}
collapsedContent={COLLAPSED}
@@ -43,13 +42,8 @@ context('AccordionCollapsible', () => {
expect(onPressSpy).toBeCalled()
})
- it('when hideArrow set to true, cannot find tab to press', () => {
+ it('when expandedInitialValue is true it should show Expanded and not Collapsed content on load', () => {
initializeTestInstance(true)
- expect(screen.queryByRole('tab')).toBeFalsy()
- })
-
- it('when expandedIntiailValue is true it should show Expanded and not Collapsed content on load', () => {
- initializeTestInstance(false, true)
expect(screen.getByRole('tab', { name: 'HEADER' })).toBeTruthy()
expect(screen.queryByText('COLLAPSED')).toBeFalsy()
expect(screen.getByText('EXPANDED')).toBeTruthy()
diff --git a/VAMobile/src/components/AccordionCollapsible.tsx b/VAMobile/src/components/AccordionCollapsible.tsx
index 5cbdcf9d1a2..f815fc516fc 100644
--- a/VAMobile/src/components/AccordionCollapsible.tsx
+++ b/VAMobile/src/components/AccordionCollapsible.tsx
@@ -22,8 +22,6 @@ export type AccordionCollapsibleProps = {
a11yHint?: string
/** component to display on when the accordion is collapsed */
collapsedContent?: ReactNode
- /** if true hides the accordion arrow and only displays header & collapsed content */
- hideArrow?: boolean
/** custom on press call if more action is needed when expanding/collapsing the accordion */
customOnPress?: (expandedValue?: boolean) => void
/** sets the initial value of expanded if an accordion should already be expanded on render */
@@ -41,7 +39,6 @@ const AccordionCollapsible: FC = ({
header,
expandedContent,
collapsedContent,
- hideArrow,
testID,
customOnPress,
expandedInitialValue,
@@ -78,11 +75,9 @@ const AccordionCollapsible: FC = ({
const data = (
{header}
- {!hideArrow && (
-
-
-
- )}
+
+
+
)
@@ -92,14 +87,6 @@ const AccordionCollapsible: FC = ({
}
: {}
- if (hideArrow) {
- return (
-
- {data}
-
- )
- }
-
return (
{data}
diff --git a/VAMobile/src/components/CrisisLineButton.tsx b/VAMobile/src/components/CrisisLineButton.tsx
index dffebf73954..740d98a01b6 100644
--- a/VAMobile/src/components/CrisisLineButton.tsx
+++ b/VAMobile/src/components/CrisisLineButton.tsx
@@ -29,6 +29,7 @@ const CrisisLineButton: FC = () => {
borderRadius: 40,
},
],
+ testID: 'veteransCrisisLineID',
}
return (
diff --git a/VAMobile/src/components/FormWrapper/FormFields/FormAttachments.tsx b/VAMobile/src/components/FormWrapper/FormFields/FormAttachments.tsx
index 9d6b980bbaa..8c5b11652d4 100644
--- a/VAMobile/src/components/FormWrapper/FormFields/FormAttachments.tsx
+++ b/VAMobile/src/components/FormWrapper/FormFields/FormAttachments.tsx
@@ -18,13 +18,21 @@ export type FormAttachmentsProps = {
buttonLabel?: string
/**button onPress */
buttonPress?: () => void
+ /** optional TestID */
+ testID?: string
/** list of current attachments */
attachmentsList?: Array
}
/** A common component for form attachments, displays Attachments heading with helper link,
* already attached items with remove option, and an optional large button. */
-const FormAttachments: FC = ({ removeOnPress, buttonLabel, buttonPress, attachmentsList }) => {
+const FormAttachments: FC = ({
+ removeOnPress,
+ buttonLabel,
+ buttonPress,
+ testID,
+ attachmentsList,
+}) => {
const theme = useTheme()
const { t } = useTranslation(NAMESPACE.COMMON)
const { t: tFunction } = useTranslation()
@@ -58,6 +66,7 @@ const FormAttachments: FC = ({ removeOnPress, buttonLabel,
label={t('remove')}
a11yHint={t('remove.a11yHint', { content: fileName })}
buttonType={ButtonVariants.Destructive}
+ testID={testID}
/>
)
@@ -80,6 +89,7 @@ const FormAttachments: FC = ({ removeOnPress, buttonLabel,
onPress={buttonPress}
buttonType={ButtonVariants.Secondary}
a11yLabel={buttonLabel}
+ testID={testID}
/>
)}
diff --git a/VAMobile/src/components/Templates/FeatureLandingAndChildTemplate.tsx b/VAMobile/src/components/Templates/FeatureLandingAndChildTemplate.tsx
index 9a3a0e6ac6a..7c554e21c0f 100644
--- a/VAMobile/src/components/Templates/FeatureLandingAndChildTemplate.tsx
+++ b/VAMobile/src/components/Templates/FeatureLandingAndChildTemplate.tsx
@@ -83,6 +83,7 @@ export const ChildTemplate: FC = ({
a11yLabel: headerButton.labelA11y,
onPress: headerButton.onPress,
icon: headerButton.icon,
+ testID: headerButton.testID,
}
: undefined,
}
diff --git a/VAMobile/src/components/VABulletList.tsx b/VAMobile/src/components/VABulletList.tsx
index 3f9f618a4a5..3f7487ff025 100644
--- a/VAMobile/src/components/VABulletList.tsx
+++ b/VAMobile/src/components/VABulletList.tsx
@@ -94,7 +94,7 @@ const VABulletList: FC = ({ listOfText, paragraphSpacing }) =
-
+
{!!boldedTextPrefix && {boldedTextPrefix}}
{text.trim()}
{!!boldedText && {boldedText}}
diff --git a/VAMobile/src/constants/analytics.ts b/VAMobile/src/constants/analytics.ts
index 9d6b76bfd86..0c92adbee69 100644
--- a/VAMobile/src/constants/analytics.ts
+++ b/VAMobile/src/constants/analytics.ts
@@ -1142,6 +1142,14 @@ export const Events = {
},
}
},
+ vama_sso_cookie_received: (received: boolean): Event => {
+ return {
+ name: 'vama_sso_cookie_received',
+ params: {
+ received,
+ },
+ }
+ },
vama_toggle: (toggle_name: string, status: boolean, screen_name: string): Event => {
return {
name: 'vama_toggle',
@@ -1199,6 +1207,14 @@ export const Events = {
},
}
},
+ vama_webview_fail: (error: string): Event => {
+ return {
+ name: 'vama_webview_fail',
+ params: {
+ error,
+ },
+ }
+ },
vama_whatsnew_alert: (): Event => {
return {
name: 'vama_whatsnew_alert',
diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealDetailsScreen.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealDetailsScreen.tsx
index 721b8de600c..ff7e6e4efa4 100644
--- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealDetailsScreen.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealDetailsScreen.tsx
@@ -59,7 +59,7 @@ function AppealDetailsScreen({ navigation, route }: AppealDetailsScreenProps) {
useEffect(() => {
if (appeal && !loadingAppeal && !appealError) {
- registerReviewEvent()
+ registerReviewEvent(true)
}
}, [appeal, loadingAppeal, appealError])
diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealStatus/AppealCurrentStatus/AppealCurrentStatus.test.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealStatus/AppealCurrentStatus/AppealCurrentStatus.test.tsx
index c4fcd994b2b..da9d6d66214 100644
--- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealStatus/AppealCurrentStatus/AppealCurrentStatus.test.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/AppealDetailsScreen/AppealStatus/AppealCurrentStatus/AppealCurrentStatus.test.tsx
@@ -181,9 +181,8 @@ context('AppealStatus', () => {
),
).toBeTruthy()
expect(
- screen.getByLabelText("Submit VA Form 9 to continue your appeal to the Board of Veterans' Appeals,"),
+ screen.getByText("Submit VA Form 9 to continue your appeal to the Board of Veterans' Appeals, or"),
).toBeTruthy()
- expect(screen.getByText('or')).toBeTruthy()
expect(screen.getByText('Opt in to the new decision review process')).toBeTruthy()
})
})
diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx
index 7240ba458cc..b474df6172b 100644
--- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimDetailsScreen.tsx
@@ -99,7 +99,7 @@ function ClaimDetailsScreen({ navigation, route }: ClaimDetailsScreenProps) {
useEffect(() => {
if (claim && !loadingClaim && !claimError) {
- registerReviewEvent()
+ registerReviewEvent(true)
logAnalyticsEvent(
Events.vama_claim_details_open(
claimID,
diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClosedClaimInfo/ClosedClaimStatusDetails.test.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClosedClaimInfo/ClosedClaimStatusDetails.test.tsx
index 885b434c6d9..15d970484fb 100644
--- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClosedClaimInfo/ClosedClaimStatusDetails.test.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClosedClaimInfo/ClosedClaimStatusDetails.test.tsx
@@ -39,8 +39,8 @@ context('ClosedClaimStatusDetails', () => {
it('renders list of claimed items', () => {
renderWithProps()
- expect(screen.getByLabelText('Hearing Loss (Increase)')).toBeTruthy()
- expect(screen.getByLabelText('Ankle strain (related to: PTSD - Combat POW) (New)')).toBeTruthy()
- expect(screen.getByLabelText('Diabetes mellitus2 (Secondary)')).toBeTruthy()
+ expect(screen.getByText('Hearing Loss (Increase)')).toBeTruthy()
+ expect(screen.getByText('Ankle strain (related to: PTSD - Combat POW) (New)')).toBeTruthy()
+ expect(screen.getByText('Diabetes mellitus2 (Secondary)')).toBeTruthy()
})
})
diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx
index dcab3606c4c..f97a6583a39 100644
--- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx
@@ -94,7 +94,11 @@ const ClaimLettersScreen = ({ navigation }: ClaimLettersScreenProps) => {
})
return (
-
+
{loading || downloading ? (
) : letterInfoError || claimsInDowntime ? (
diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimsScreen.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimsScreen.tsx
index f0fd8d30a16..bc2754505b9 100644
--- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimsScreen.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimsScreen.tsx
@@ -34,7 +34,7 @@ const ClaimsScreen = ({ navigation }: ClaimsScreenProps) => {
title={t('claims.title')}>
-
+
)
diff --git a/VAMobile/src/screens/BenefitsScreen/DisabilityRatingsScreen/DisabilityRatingsScreen.tsx b/VAMobile/src/screens/BenefitsScreen/DisabilityRatingsScreen/DisabilityRatingsScreen.tsx
index 58cd10365c1..7a7c053b73e 100644
--- a/VAMobile/src/screens/BenefitsScreen/DisabilityRatingsScreen/DisabilityRatingsScreen.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/DisabilityRatingsScreen/DisabilityRatingsScreen.tsx
@@ -57,7 +57,7 @@ function DisabilityRatingsScreen() {
useFocusEffect(
React.useCallback(() => {
- registerReviewEvent()
+ registerReviewEvent(true)
}, []),
)
diff --git a/VAMobile/src/screens/BenefitsScreen/Letters/BenefitSummaryServiceVerification/BenefitSummaryServiceVerification.tsx b/VAMobile/src/screens/BenefitsScreen/Letters/BenefitSummaryServiceVerification/BenefitSummaryServiceVerification.tsx
index a10196748b9..73356aa6d38 100644
--- a/VAMobile/src/screens/BenefitsScreen/Letters/BenefitSummaryServiceVerification/BenefitSummaryServiceVerification.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/Letters/BenefitSummaryServiceVerification/BenefitSummaryServiceVerification.tsx
@@ -231,7 +231,8 @@ function BenefitSummaryServiceVerification({ navigation }: BenefitSummaryService
backLabel={t('letters.overview.viewLetters')}
backLabelOnPress={navigation.goBack}
title={t('letters.details.title')}
- testID="BenefitSummaryServiceVerificationTestID">
+ testID="BenefitSummaryServiceVerificationTestID"
+ backLabelTestID="BenefitSummaryServiceVerificationBackID">
{loadingCheck ? (
) : letterDownloadError ? (
@@ -285,6 +286,7 @@ function BenefitSummaryServiceVerification({ navigation }: BenefitSummaryService
text={t('letters.benefitService.sendMessage')}
a11yLabel={a11yLabelVA(t('letters.benefitService.sendMessage'))}
a11yHint={t('letters.benefitService.sendMessageA11yHint')}
+ testID="lettersBenefitServiceGoToAskVAID"
/>
@@ -292,7 +294,7 @@ function BenefitSummaryServiceVerification({ navigation }: BenefitSummaryService
diff --git a/VAMobile/src/screens/BenefitsScreen/Letters/GenericLetter/GenericLetter.tsx b/VAMobile/src/screens/BenefitsScreen/Letters/GenericLetter/GenericLetter.tsx
index a1086a52169..9d0b351d6c8 100644
--- a/VAMobile/src/screens/BenefitsScreen/Letters/GenericLetter/GenericLetter.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/Letters/GenericLetter/GenericLetter.tsx
@@ -74,7 +74,7 @@ function GenericLetter({ navigation, route }: GenericLetterProps) {
@@ -84,7 +84,8 @@ function GenericLetter({ navigation, route }: GenericLetterProps) {
+ title={t('letters.details.title')}
+ backLabelTestID="BenefitSummaryServiceVerificationBackID">
{downloading ? (
) : letterDownloadError ? (
diff --git a/VAMobile/src/screens/BenefitsScreen/Letters/LettersOverviewScreen.tsx b/VAMobile/src/screens/BenefitsScreen/Letters/LettersOverviewScreen.tsx
index d1b35f47684..e9065011f2b 100644
--- a/VAMobile/src/screens/BenefitsScreen/Letters/LettersOverviewScreen.tsx
+++ b/VAMobile/src/screens/BenefitsScreen/Letters/LettersOverviewScreen.tsx
@@ -61,6 +61,7 @@ function LettersOverviewScreen({ navigation }: LettersOverviewProps) {
onPress={() => navigateTo('LettersList')}
label={t('letters.overview.viewLetters')}
a11yHint={t('letters.overview.viewLetters.hint')}
+ testID="lettersOverviewViewLettersButtonID"
/>
>
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.test.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.test.tsx
index 68c4a4b6120..257491e069c 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.test.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.test.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { screen } from '@testing-library/react-native'
+import { t } from 'i18next'
import {
AppointmentAttributes,
@@ -109,6 +110,9 @@ context('CommunityCareAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(screen.getByText('If you need to reschedule or cancel this appointment, call your provider.')).toBeTruthy()
})
@@ -165,6 +169,9 @@ context('CommunityCareAppointment', () => {
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(screen.getByText('If you need to reschedule or cancel this appointment, call your provider.')).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('link', { name: 'Find your VA location' })).toBeTruthy()
expect(screen.getByLabelText('Find your V-A location')).toBeTruthy()
expect(
@@ -319,6 +326,9 @@ context('CommunityCareAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
@@ -394,6 +404,9 @@ context('CommunityCareAppointment', () => {
),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('link', { name: 'Go to VA.gov to schedule' })).toBeTruthy()
expect(screen.getByLabelText('Go to V-A .gov to schedule')).toBeTruthy()
})
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.tsx
index cb4b90a3f25..c4760cf9011 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/CommunityCareAppointment.tsx
@@ -17,6 +17,7 @@ import {
AppointmentDateAndTime,
AppointmentDetailsModality,
AppointmentLocation,
+ AppointmentMedicationWording,
AppointmentPersonalContactInfo,
AppointmentProvider,
AppointmentReasonAndComment,
@@ -75,6 +76,7 @@ function CommunityCareAppointment({
)}
+ {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(
screen.getByText('You can cancel this appointment in the app. But if you need to reschedule, call us.'),
@@ -176,6 +180,9 @@ context('InPersonVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(screen.getByText('If you need to reschedule or cancel this appointment, call us.')).toBeTruthy()
@@ -348,6 +355,9 @@ context('InPersonVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
@@ -414,6 +424,9 @@ context('InPersonVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/InPersonVAAppointment.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/InPersonVAAppointment.tsx
index 3ce360e193a..ee356998769 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/InPersonVAAppointment.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/InPersonVAAppointment.tsx
@@ -13,6 +13,7 @@ import {
AppointmentDateAndTime,
AppointmentDetailsModality,
AppointmentLocation,
+ AppointmentMedicationWording,
AppointmentPersonalContactInfo,
AppointmentPreferredModality,
AppointmentProvider,
@@ -62,6 +63,7 @@ function InPersonVAAppointment({
+ {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(
screen.getByText('You can cancel this appointment in the app. But if you need to reschedule, call us.'),
@@ -139,6 +143,9 @@ context('PhoneAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(screen.getByText('If you need to reschedule or cancel this appointment, call us.')).toBeTruthy()
@@ -260,6 +267,9 @@ context('PhoneAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
@@ -307,6 +317,9 @@ context('PhoneAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/PhoneAppointment.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/PhoneAppointment.tsx
index aa9f94b0f84..cb3c0762f29 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/PhoneAppointment.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/PhoneAppointment.tsx
@@ -13,6 +13,7 @@ import {
AppointmentDateAndTime,
AppointmentDetailsModality,
AppointmentLocation,
+ AppointmentMedicationWording,
AppointmentPersonalContactInfo,
AppointmentPreferredModality,
AppointmentProvider,
@@ -56,6 +57,7 @@ function PhoneAppointment({ appointmentID, attributes, subType, goBack, cancelAp
+
+
+ {t('appointmentsTab.medicationWording.title')}
+
+ {body}
+ {
+ navigateTo('Webview', {
+ url: WEBVIEW_URL_WHAT_TO_BRING_TO_APPOINTMENTS,
+ displayTitle: t('webview.vagov'),
+ loadingMessage: t('loading'),
+ })
+ }}
+ text={t('appointmentsTab.medicationWording.whatToBringLink')}
+ />
+
+ )
+ default:
+ return <>>
+ }
+ default:
+ return <>>
+ }
+}
+
+export default AppointmentMedicationWording
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/index.ts b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/index.ts
index e093d40ee65..afab848232c 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/index.ts
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/index.ts
@@ -10,6 +10,8 @@ export { default as AppointmentDetailsModality } from './AppointmentDetailsModal
export * from './AppointmentDetailsModality'
export { default as AppointmentJoinSessionPrepareForVideo } from './AppointmentJoinSessionPrepareForVideo'
export * from './AppointmentJoinSessionPrepareForVideo'
+export { default as AppointmentMedicationWording } from './AppointmentMedicationWording'
+export * from './AppointmentMedicationWording'
export { default as AppointmentLocation } from './AppointmentLocation'
export * from './AppointmentLocation'
export { default as AppointmentPersonalContactInfo } from './AppointmentPersonalContactInfo'
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.test.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.test.tsx
index be7d8f4f967..c4628597f76 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.test.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.test.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { screen } from '@testing-library/react-native'
+import { t } from 'i18next'
import {
AppointmentAttributes,
@@ -116,6 +117,9 @@ context('VideoVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(screen.getByText('If you need to reschedule or cancel this appointment, call us.')).toBeTruthy()
})
@@ -173,6 +177,9 @@ context('VideoVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule or cancel?' })).toBeTruthy()
expect(screen.getByText('If you need to reschedule or cancel this appointment, call us.')).toBeTruthy()
@@ -345,6 +352,9 @@ context('VideoVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
@@ -411,6 +421,9 @@ context('VideoVAAppointment', () => {
screen.getByText('Other details: Please arrive 20 minutes before the start of your appointment'),
).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('appointmentsTab.medicationWording.title') })).toBeTruthy()
+ expect(screen.getByRole('link', { name: t('appointmentsTab.medicationWording.whatToBringLink') })).toBeTruthy()
+
expect(screen.getByRole('header', { name: 'Need to reschedule?' })).toBeTruthy()
expect(
screen.getByText(
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.tsx
index 270249de655..6bca9e3300f 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/VideoVAAppointment.tsx
@@ -13,6 +13,7 @@ import {
AppointmentDateAndTime,
AppointmentDetailsModality,
AppointmentLocation,
+ AppointmentMedicationWording,
AppointmentPersonalContactInfo,
AppointmentPreferredModality,
AppointmentProvider,
@@ -62,6 +63,7 @@ function VideoVAAppointment({
+
{subText}
- {showVAGovLink && (
-
- )}
+ {showVAGovLink &&
+ (featureEnabled('sso') ? (
+
+ navigateTo('Webview', {
+ url: LINK_URL_SCHEDULE_APPOINTMENTS,
+ displayTitle: t('webview.vagov'),
+ loadingMessage: t('webview.appointments.loading'),
+ useSSO: true,
+ })
+ }
+ text={t('noAppointments.visitVA')}
+ a11yLabel={a11yLabelVA(t('noAppointments.visitVA'))}
+ a11yHint={t('mobileBodyLink.a11yHint')}
+ />
+ ) : (
+
+ ))}
)
}
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/PastAppointments/PastAppointmentDetails.tsx b/VAMobile/src/screens/HealthScreen/Appointments/PastAppointments/PastAppointmentDetails.tsx
index d228dca329d..3d463e56bcd 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/PastAppointments/PastAppointmentDetails.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/PastAppointments/PastAppointmentDetails.tsx
@@ -51,7 +51,7 @@ function PastAppointmentDetails({ route, navigation }: PastAppointmentDetailsPro
getAppointmentAnalyticsDays(attributes),
),
)
- registerReviewEvent()
+ registerReviewEvent(true)
}
}, [appointment, pendingAppointment, attributes])
diff --git a/VAMobile/src/screens/HealthScreen/Appointments/UpcomingAppointments/UpcomingAppointmentDetails.tsx b/VAMobile/src/screens/HealthScreen/Appointments/UpcomingAppointments/UpcomingAppointmentDetails.tsx
index 3f3e5e7e803..29aaddfa458 100644
--- a/VAMobile/src/screens/HealthScreen/Appointments/UpcomingAppointments/UpcomingAppointmentDetails.tsx
+++ b/VAMobile/src/screens/HealthScreen/Appointments/UpcomingAppointments/UpcomingAppointmentDetails.tsx
@@ -72,7 +72,7 @@ function UpcomingAppointmentDetails({ route, navigation }: UpcomingAppointmentDe
getAppointmentAnalyticsDays(attributes),
),
)
- registerReviewEvent()
+ registerReviewEvent(true)
}
}, [trueAppointment, pendingAppointment, attributes])
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.test.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.test.tsx
index 3f02be229e8..a5a5ca22b82 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.test.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.test.tsx
@@ -1,9 +1,11 @@
import React from 'react'
import { screen } from '@testing-library/react-native'
+import { t } from 'i18next'
import { PrescriptionAttributeData } from 'api/types'
import { context, render } from 'testUtils'
+import { a11yLabelVA } from 'utils/a11yLabel'
import {
emptyStatePrescriptionList as emptyMockData,
defaultPrescriptionsList as mockData,
@@ -24,6 +26,16 @@ context('PrescriptionListItem', () => {
render()
}
+ it('renders prescription with data', () => {
+ initializeTestInstance()
+ expect(screen.getByRole('header', { name: 'ALLOPURINOL 100MG TAB.' })).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.rxNumber.a11yLabel')} 3 6 3 6 6 9 1.`)).toBeTruthy()
+ expect(screen.getByLabelText('TAKE ONE TABLET EVERY DAY FOR 30 DAYS TAKE WITH FOOD.')).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.refillsLeft')} 1.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${t('fillDate')} September 21, 2021.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${a11yLabelVA(t('prescription.vaFacility'))} SLC10 TEST LAB.`)).toBeTruthy()
+ })
+
describe('when there is no data provided', () => {
describe('and hideInstructions is set to true', () => {
it('should show None noted for everything besides instructions', () => {
@@ -34,10 +46,11 @@ context('PrescriptionListItem', () => {
},
true,
)
- expect(screen.getByText('Rx #: None noted')).toBeTruthy()
- expect(screen.getByText('Refills left: None noted')).toBeTruthy()
- expect(screen.getByText('Fill date: None noted')).toBeTruthy()
- expect(screen.getByText('VA facility: None noted')).toBeTruthy()
+ expect(screen.getByRole('header', { name: 'ALLOPURINOL 100MG TAB.' })).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.rxNumber.a11yLabel')} None noted.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.refillsLeft')} None noted.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${t('fillDate')} None noted.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${a11yLabelVA(t('prescription.vaFacility'))} None noted.`)).toBeTruthy()
})
})
@@ -50,11 +63,12 @@ context('PrescriptionListItem', () => {
},
false,
)
- expect(screen.getByText('Rx #: None noted')).toBeTruthy()
- expect(screen.getByText('Instructions not noted')).toBeTruthy()
- expect(screen.getByText('Refills left: None noted')).toBeTruthy()
- expect(screen.getByText('Fill date: None noted')).toBeTruthy()
- expect(screen.getByText('VA facility: None noted')).toBeTruthy()
+ expect(screen.getByRole('header', { name: 'ALLOPURINOL 100MG TAB.' })).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.rxNumber.a11yLabel')} None noted.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.instructions.noneNoted')}.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.refillsLeft')} None noted.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${t('fillDate')} None noted.`)).toBeTruthy()
+ expect(screen.getByLabelText(`${a11yLabelVA(t('prescription.vaFacility'))} None noted.`)).toBeTruthy()
})
})
})
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.tsx
index 3f6dd682362..9ffb0f82a57 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionCommon/PrescriptionListItem.tsx
@@ -49,7 +49,7 @@ function PrescriptionListItem({ prescription, hideInstructions, includeRefillTag
return (
-
+
{prescriptionName}
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/DetailsTextSections.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/DetailsTextSections.tsx
index c7095a97af9..2187c4bac8f 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/DetailsTextSections.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/DetailsTextSections.tsx
@@ -46,7 +46,7 @@ function DetailsTextSections({
) => {
return (
<>
-
+
{headerText}
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.test.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.test.tsx
index ee6c4b5bf72..e43946d9cd7 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.test.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.test.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { screen } from '@testing-library/react-native'
+import { t } from 'i18next'
import { PrescriptionAttributeData, RefillStatusConstants } from 'api/types'
import { context, mockNavProps, render } from 'testUtils'
@@ -43,14 +44,13 @@ context('PrescriptionDetails', () => {
describe('when showing prescription details data', () => {
it('should show prescription fields', () => {
initializeTestInstance()
- expect(screen.getByText('Instructions')).toBeTruthy()
- expect(screen.getByText('Refills left')).toBeTruthy()
- expect(screen.getByText('Fill date')).toBeTruthy()
- expect(screen.getByText('Quantity')).toBeTruthy()
- expect(screen.getByText('Expires on')).toBeTruthy()
- expect(screen.getByText('Ordered on')).toBeTruthy()
- expect(screen.getByText('VA facility')).toBeTruthy()
-
+ expect(screen.getByRole('header', { name: t('prescription.details.instructionsHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.refillLeftHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('fillDate') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.quantityHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.expiresOnHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.orderedOnHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.vaFacilityHeader') })).toBeTruthy()
expect(screen.getByRole('link', { name: '(217) 636-6712' })).toBeTruthy()
expect(screen.getByRole('link', { name: 'TTY: 711' })).toBeTruthy()
})
@@ -68,15 +68,16 @@ context('PrescriptionDetails', () => {
facilityName: '',
prescriptionNumber: '',
})
- expect(screen.getByText('Rx #: None noted')).toBeTruthy()
- expect(screen.getByText('Instructions')).toBeTruthy()
+ expect(screen.getByRole('header', { name: 'SOMATROPIN 5MG INJ (VI)' })).toBeTruthy()
+ expect(screen.getByLabelText(`${t('prescription.rxNumber.a11yLabel')} None noted`)).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.instructionsHeader') })).toBeTruthy()
expect(screen.getAllByText('None noted')).toBeTruthy()
- expect(screen.getByText('Refills left')).toBeTruthy()
- expect(screen.getByText('Fill date')).toBeTruthy()
- expect(screen.getByText('Quantity')).toBeTruthy()
- expect(screen.getByText('Expires on')).toBeTruthy()
- expect(screen.getByText('Ordered on')).toBeTruthy()
- expect(screen.getByText('VA facility')).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.refillLeftHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('fillDate') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.quantityHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.expiresOnHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.orderedOnHeader') })).toBeTruthy()
+ expect(screen.getByRole('header', { name: t('prescription.details.vaFacilityHeader') })).toBeTruthy()
})
})
@@ -86,14 +87,14 @@ context('PrescriptionDetails', () => {
initializeTestInstance({
refillStatus: RefillStatusConstants.TRANSFERRED,
})
- expect(screen.getByRole('button', { name: 'Go to My VA Health' })).toBeTruthy()
+ expect(screen.getByRole('button', { name: t('goToMyVAHealth') })).toBeTruthy()
})
})
describe('when status is not RefillStatusConstants.TRANSFERRED', () => {
it('should not display FooterButton', () => {
initializeTestInstance()
- expect(screen.queryByRole('button', { name: 'Go to My VA Health' })).toBeFalsy()
+ expect(screen.queryByRole('button', { name: t('goToMyVAHealth') })).toBeFalsy()
})
})
})
@@ -104,14 +105,14 @@ context('PrescriptionDetails', () => {
initializeTestInstance({
isRefillable: true,
})
- expect(screen.getByRole('button', { name: 'Request refill' })).toBeTruthy()
+ expect(screen.getByRole('button', { name: t('prescriptions.refill.RequestRefillButtonTitle') })).toBeTruthy()
})
})
describe('when isRefillable is false', () => {
it('should not display FooterButton', () => {
initializeTestInstance()
- expect(screen.queryByRole('button', { name: 'Request refill' })).toBeFalsy()
+ expect(screen.queryByRole('button', { name: t('prescriptions.refill.RequestRefillButtonTitle') })).toBeFalsy()
})
})
})
@@ -123,14 +124,14 @@ context('PrescriptionDetails', () => {
refillStatus: RefillStatusConstants.TRANSFERRED,
})
- expect(screen.getByText("We can't refill this prescription in the app")).toBeTruthy()
+ expect(screen.getByText(t('prescription.details.banner.title'))).toBeTruthy()
})
})
describe('when status is not RefillStatusConstants.TRANSFERRED', () => {})
it('should not display the PrescriptionsDetailsBanner', () => {
initializeTestInstance()
- expect(screen.queryByText("We can't refill this prescription in the app")).toBeFalsy()
+ expect(screen.queryByText(t('prescription.details.banner.title'))).toBeFalsy()
})
})
})
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.tsx
index ea4ab6761fc..917d3301007 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/PrescriptionDetails/PrescriptionDetails.tsx
@@ -60,7 +60,7 @@ function PrescriptionDetails({ route, navigation }: PrescriptionDetailsProps) {
useFocusEffect(
React.useCallback(() => {
setAnalyticsUserProperty(UserAnalytics.vama_uses_rx())
- registerReviewEvent()
+ registerReviewEvent(true)
}, []),
)
@@ -122,6 +122,7 @@ function PrescriptionDetails({ route, navigation }: PrescriptionDetailsProps) {
)
@@ -143,7 +144,8 @@ function PrescriptionDetails({ route, navigation }: PrescriptionDetailsProps) {
+ title={t('prescriptionDetails')}
+ backLabelTestID="prescriptionsDetailsBackTestID">
{loadingHistory ? (
) : (
@@ -152,7 +154,9 @@ function PrescriptionDetails({ route, navigation }: PrescriptionDetailsProps) {
{getRefillVAHealthButton()}
) : (
<>>
@@ -180,7 +181,7 @@ function RefillTrackingDetails({ route, navigation }: RefillTrackingDetailsProps
return (
<>
-
+
{prescriptionName}
@@ -198,7 +199,8 @@ function RefillTrackingDetails({ route, navigation }: RefillTrackingDetailsProps
+ testID="refillTrackingDetailsTestID"
+ rightButtonTestID="prescriptionsBackTestID">
{prescriptionInDowntime ? (
) : loadingTrackingInfo ? (
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.test.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.test.tsx
index 87dfde7547a..f2efd2ea88a 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.test.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.test.tsx
@@ -1,9 +1,11 @@
import React from 'react'
import { screen } from '@testing-library/react-native'
+import { t } from 'i18next'
import { RefillStatus, RefillStatusConstants } from 'api/types'
import { context, mockNavProps, render } from 'testUtils'
+import { a11yLabelVA } from 'utils/a11yLabel'
import StatusDefinition from './StatusDefinition'
@@ -27,11 +29,7 @@ context('StatusDefinition', () => {
display: 'Active',
value: RefillStatusConstants.ACTIVE,
})
- expect(screen.getByText('Active')).toBeTruthy()
- expect(
- screen.getByText(
- 'A prescription that can be filled at the local VA pharmacy. If this prescription is refillable, you may request a refill of this VA prescription.',
- ),
- ).toBeTruthy()
+ expect(screen.getByRole('header', { name: 'Active' })).toBeTruthy()
+ expect(screen.getByLabelText(a11yLabelVA(t('statusDefinition.active')))).toBeTruthy()
})
})
diff --git a/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.tsx b/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.tsx
index 963e14c28ba..59ed1bb2991 100644
--- a/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.tsx
+++ b/VAMobile/src/screens/HealthScreen/Pharmacy/StatusDefinition/StatusDefinition.tsx
@@ -30,9 +30,11 @@ function StatusDefinition({ navigation, route }: StatusDefinitionProps) {
})
return (
-
+
- {display}
+
+ {display}
+
{text}
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx
index 3c75d4be7c6..ac68fa5c401 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx
@@ -447,6 +447,7 @@ function EditDraft({ navigation, route }: EditDraftProps) {
: undefined,
buttonPress: attachmentsList.length < theme.dimensions.maxNumMessageAttachments ? onAddFiles : undefined,
attachmentsList,
+ testID: 'messagesAttachmentsAddFilesID',
},
},
{
@@ -665,7 +666,8 @@ function EditDraft({ navigation, route }: EditDraftProps) {
menuViewActions={isLoading ? undefined : menuViewActions}
showCrisisLineButton={!(isLoading || hasError)}
leftButtonTestID="editDraftCancelTestID"
- testID="editDraftTestID">
+ testID="editDraftTestID"
+ rightButtonTestID="editDraftMoreID">
{isLoading ? (
) : hasError ? (
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/FolderMessages/FolderMessages.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/FolderMessages/FolderMessages.tsx
index 34efcc909f9..9b88877718f 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/FolderMessages/FolderMessages.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/FolderMessages/FolderMessages.tsx
@@ -119,7 +119,8 @@ function FolderMessages({ route }: FolderMessagesProps) {
navigateTo('SecureMessaging', { activeTab: 1 })
}}
title={title}
- scrollViewProps={scrollViewProps}>
+ scrollViewProps={scrollViewProps}
+ backLabelTestID="foldersBackToMessagesID">
{loadingFolderMessages ? (
) : folderMessagesError ? (
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyHelp/ReplyHelp.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyHelp/ReplyHelp.tsx
index a84a1bd3839..ed0f7a721a6 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyHelp/ReplyHelp.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyHelp/ReplyHelp.tsx
@@ -42,7 +42,6 @@ function ReplyHelp() {
{
boldedTextPrefix: t('secureMessaging.replyHelp.ifYoureInCrisis'),
text: t('secureMessaging.replyHelp.connectWithOur'),
- a11yLabel: t('secureMessaging.replyHelp.ifYoureInCrisis') + t('secureMessaging.replyHelp.connectWithOur'),
},
]}
paragraphSpacing={true}
@@ -56,7 +55,6 @@ function ReplyHelp() {
{
boldedTextPrefix: t('secureMessaging.replyHelp.ifYouThink'),
text: t('secureMessaging.replyHelp.call911OrGoTo'),
- a11yLabel: t('secureMessaging.replyHelp.ifYouThink') + t('secureMessaging.replyHelp.call911OrGoTo'),
},
]}
paragraphSpacing={true}
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx
index edba186abb7..4ce4b02b9be 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx
@@ -222,6 +222,7 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) {
: undefined,
buttonPress: attachmentsList.length < theme.dimensions.maxNumMessageAttachments ? onAddFiles : undefined,
attachmentsList,
+ testID: 'messagesAttachmentsAddFilesID',
},
},
{
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx
index 33069c94023..0fb8a036d43 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx
@@ -80,6 +80,7 @@ function SecureMessaging({ navigation, route }: SecureMessagingScreen) {
const inboxLabelCount = inboxUnreadCount !== 0 ? `(${inboxUnreadCount})` : ''
const inboxLabel = `${t('secureMessaging.inbox')} ${inboxLabelCount}`.trim()
const controlLabels = [inboxLabel, t('secureMessaging.folders')]
+ const controlIDs = ['inboxID', 'foldersID']
const [scrollPage, setScrollPage] = useState(1)
// Resets scroll position to top whenever current page appointment list changes:
@@ -175,6 +176,7 @@ function SecureMessaging({ navigation, route }: SecureMessagingScreen) {
selected={secureMessagingTab}
a11yHints={a11yHints}
a11yLabels={[t('secureMessaging.inbox')]}
+ testIDs={controlIDs}
/>
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/Attachments/Attachments.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/Attachments/Attachments.tsx
index 2307727456f..c069cbdab03 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/Attachments/Attachments.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/Attachments/Attachments.tsx
@@ -175,10 +175,12 @@ function Attachments({ navigation, route }: AttachmentsProps) {
scrollViewRef={scrollViewRef}
title={t('secureMessaging.startNewMessage.attachments.title')}
leftButtonText={t('cancel')}
+ leftButtonTestID="attachmentsCancelID"
onLeftButtonPress={navigation.goBack}
primaryContentButtonText={
displaySelectFile ? t('secureMessaging.attachments.selectAFile') : t('secureMessaging.startNewMessage.attach')
}
+ primaryButtonTestID="messagesSelectAFileID"
onPrimaryContentButtonPress={displaySelectFile ? onSelectAFile : onAttach}>
{!!error && (
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx
index bc6d054d929..6e1ed383abe 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx
@@ -261,6 +261,7 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) {
includeBlankPlaceholder: true,
isRequiredField: true,
testID: 'to field',
+ confirmTestID: 'messagePickerConfirmID',
},
fieldErrorMessage: t('secureMessaging.startNewMessage.to.fieldError'),
},
@@ -274,6 +275,7 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) {
includeBlankPlaceholder: true,
isRequiredField: true,
testID: 'picker',
+ confirmTestID: 'messagePickerConfirmID',
},
fieldErrorMessage: t('secureMessaging.startNewMessage.category.fieldError'),
},
@@ -306,6 +308,7 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) {
: undefined,
buttonPress: attachmentsList.length < theme.dimensions.maxNumMessageAttachments ? onAddFiles : undefined,
attachmentsList,
+ testID: 'messagesAttachmentsAddFilesID',
},
},
{
diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx
index 606265aeb16..bcb6ec070e1 100644
--- a/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx
+++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx
@@ -152,7 +152,7 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) {
useEffect(() => {
if (threadFetched) {
setAnalyticsUserProperty(UserAnalytics.vama_uses_sm())
- registerReviewEvent()
+ registerReviewEvent(true)
}
}, [threadFetched])
@@ -369,6 +369,7 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) {
logAnalyticsEvent(Events.vama_sm_move())
setShowModalPicker(true)
},
+ testID: 'pickerMoveMessageID',
}
return (
@@ -377,7 +378,8 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) {
backLabelOnPress={navigation.goBack}
title={t('reviewMessage')}
headerButton={headerButton}
- testID="viewMessageTestID">
+ testID="viewMessageTestID"
+ backLabelTestID="backToMessagesID">
{isLoading ? (
) : hasError ? (
@@ -405,6 +407,8 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) {
confirmBtnText={'pickerLaunchBtn'}
key={newCurrentFolderID}
showModalByDefault={true}
+ cancelTestID="pickerMoveMessageCancelID"
+ confirmTestID="pickerMoveMessageConfirmID"
/>
)}
{replyExpired && (
@@ -413,6 +417,7 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) {
variant="warning"
header={t('secureMessaging.reply.youCanNoLonger')}
description={t('secureMessaging.reply.olderThan45Days')}
+ testID="secureMessagingOlderThan45DaysAlertID"
/>
)}
diff --git a/VAMobile/src/screens/HealthScreen/Vaccines/VaccineDetails/VaccineDetailsScreen.tsx b/VAMobile/src/screens/HealthScreen/Vaccines/VaccineDetails/VaccineDetailsScreen.tsx
index d7bda5744ff..219087bbc3a 100644
--- a/VAMobile/src/screens/HealthScreen/Vaccines/VaccineDetails/VaccineDetailsScreen.tsx
+++ b/VAMobile/src/screens/HealthScreen/Vaccines/VaccineDetails/VaccineDetailsScreen.tsx
@@ -72,7 +72,8 @@ function VaccineDetailsScreen({ route, navigation }: VaccineDetailsScreenProps)
backLabel={t('vaVaccines')}
backLabelA11y={a11yLabelVA(t('vaVaccines'))}
backLabelOnPress={navigation.goBack}
- title={t('details')}>
+ title={t('details')}
+ backLabelTestID="vaccinesDetailsBackID">
{detailsLoading ? (
) : (
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/ContactInformationScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/ContactInformationScreen.tsx
index 73fa188f012..ceaa6a07e90 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/ContactInformationScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/ContactInformationScreen.tsx
@@ -155,7 +155,7 @@ function ContactInformationScreen({ navigation }: ContactInformationScreenProps)
const [reviewEventRegistered, setReviewEventRegistered] = useState(false)
if (!reviewEventRegistered) {
console.debug('REVIEW EVENT REGISTERED')
- registerReviewEvent()
+ registerReviewEvent(true)
setReviewEventRegistered(true)
}
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/MilitaryInformationScreen/MilitaryInformationScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/MilitaryInformationScreen/MilitaryInformationScreen.tsx
index f5582a6c5fd..e23d1ef830e 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/MilitaryInformationScreen/MilitaryInformationScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/MilitaryInformationScreen/MilitaryInformationScreen.tsx
@@ -78,7 +78,8 @@ function MilitaryInformationScreen({ navigation }: MilitaryInformationScreenProp
+ title={t('militaryInformation.title')}
+ backLabelTestID="backToProfileID">
{!mhNotInDowntime ? (
) : loadingCheck ? (
@@ -109,7 +110,7 @@ function MilitaryInformationScreen({ navigation }: MilitaryInformationScreenProp
type="custom"
text={t('militaryInformation.incorrectServiceInfo')}
onPress={onIncorrectService}
- testID={t('militaryInformation.incorrectServiceInfo')}
+ testID="militaryServiceIncorrectLinkID"
/>
>
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx
index 8e105c4e15d..2362cc268ca 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx
@@ -163,7 +163,9 @@ function GenderIdentityScreen({ navigation }: GenderIdentityScreenProps) {
onLeftButtonPress={navigation.goBack}
primaryContentButtonText={errorCheck || loadingCheck ? undefined : t('save')}
onPrimaryContentButtonPress={onSave}
- testID="PersonalInformationTestID">
+ testID="genderIdentityID"
+ leftButtonTestID="genderIdentityBackID"
+ primaryButtonTestID="genderIdentitySaveID">
{loadingCheck ? (
.
-
-
+
+
{t('personalInformation.genderIdentity.whatToKnow')}
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/WhatToKnowScreen/WhatToKnowScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/WhatToKnowScreen/WhatToKnowScreen.tsx
index f4a0ba92b48..f26aacac375 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/WhatToKnowScreen/WhatToKnowScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/WhatToKnowScreen/WhatToKnowScreen.tsx
@@ -18,7 +18,11 @@ function WhatToKnowScreen({}: WhatToKnowScreenProps) {
const { t } = useTranslation(NAMESPACE.COMMON)
return (
-
+
{t('personalInformation.genderIdentity.whatToKnow.title')}
@@ -33,33 +37,21 @@ function WhatToKnowScreen({}: WhatToKnowScreenProps) {
variant: 'MobileBody',
boldedTextPrefix: t('personalInformation.genderIdentity.whatToKnow.ReasonsToShare.1'),
text: t('personalInformation.genderIdentity.whatToKnow.ReasonsToShare.2'),
- a11yLabel:
- t('personalInformation.genderIdentity.whatToKnow.ReasonsToShare.1') +
- t('personalInformation.genderIdentity.whatToKnow.ReasonsToShare.2'),
},
{
variant: 'MobileBody',
boldedTextPrefix: t('personalInformation.genderIdentity.whatToKnow.whoCanAccess'),
text: t('personalInformation.genderIdentity.whatToKnow.privacy'),
- a11yLabel:
- t('personalInformation.genderIdentity.whatToKnow.whoCanAccess') +
- t('personalInformation.genderIdentity.whatToKnow.privacy'),
},
{
variant: 'MobileBody',
boldedTextPrefix: t('personalInformation.genderIdentity.whatToKnow.healthRecordsOnly.1'),
text: t('personalInformation.genderIdentity.whatToKnow.healthRecordsOnly.2'),
- a11yLabel:
- t('personalInformation.genderIdentity.whatToKnow.healthRecordsOnly.1') +
- t('personalInformation.genderIdentity.whatToKnow.healthRecordsOnly.2'),
},
{
variant: 'MobileBody',
boldedTextPrefix: t('personalInformation.genderIdentity.whatToKnow.birthCertificate.1'),
text: t('personalInformation.genderIdentity.whatToKnow.birthCertificate.2'),
- a11yLabel:
- t('personalInformation.genderIdentity.whatToKnow.birthCertificate.1') +
- t('personalInformation.genderIdentity.whatToKnow.birthCertificate.2'),
},
]}
/>
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/HowDoIUpdateScreen/HowDoIUpdateScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/HowDoIUpdateScreen/HowDoIUpdateScreen.tsx
index 02885e96557..ec717282989 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/HowDoIUpdateScreen/HowDoIUpdateScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/HowDoIUpdateScreen/HowDoIUpdateScreen.tsx
@@ -45,6 +45,7 @@ function HowDoIUpdateScreen({ route }: HowDoIUpdateScreenProps) {
text={t('howDoIUpdate.findYourNearestVAMedicalCenter')}
a11yLabel={a11yLabelVA(t('howDoIUpdate.findYourNearestVAMedicalCenter'))}
a11yHint={t('howDoIUpdate.findYourNearestVAMedicalCenter.a11yHint')}
+ testID="findNearestVAMedicalCenterID"
/>
+
{renderUI()}
)
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PersonalInformationScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PersonalInformationScreen.tsx
index e9893ba338e..e55df48754e 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PersonalInformationScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PersonalInformationScreen.tsx
@@ -86,7 +86,7 @@ function PersonalInformationScreen({ navigation }: PersonalInformationScreenProp
/** IN-App review events need to be recorded once, so we use the setState hook to guard this **/
const [reviewEventRegistered, setReviewEventRegistered] = useState(false)
if (!reviewEventRegistered) {
- registerReviewEvent()
+ registerReviewEvent(true)
setReviewEventRegistered(true)
}
@@ -98,6 +98,7 @@ function PersonalInformationScreen({ navigation }: PersonalInformationScreenProp
{ text: getPreferredName(demographics, t) },
],
onPress: () => navigateTo('PreferredName'),
+ detoxTestID: 'preferredNameRowID',
},
]
@@ -108,6 +109,7 @@ function PersonalInformationScreen({ navigation }: PersonalInformationScreenProp
{ text: getGenderIdentity(demographics, t, genderIdentityOptions) },
],
onPress: () => navigateTo('GenderIdentity'),
+ detoxTestID: 'genderIdentityRowID',
})
}
return items
@@ -146,7 +148,8 @@ function PersonalInformationScreen({ navigation }: PersonalInformationScreenProp
backLabel={t('profile.title')}
backLabelOnPress={navigation.goBack}
title={t('personalInformation.title')}
- testID="PersonalInformationTestID">
+ testID="PersonalInformationTestID"
+ backLabelTestID="backToProfileID">
{loadingCheck ? (
) : errorCheck ? (
@@ -165,6 +168,7 @@ function PersonalInformationScreen({ navigation }: PersonalInformationScreenProp
type="custom"
text={t('personalInformation.howToFixLegalName')}
onPress={() => navigateTo('HowDoIUpdate', { screenType: 'name' })}
+ testID="howToFixLegalNameID"
/>
navigateTo('HowDoIUpdate', { screenType: 'DOB' })}
+ testID="howToFixDOBID"
/>
{featureEnabled('preferredNameGenderWaygate') && }
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx
index df1897463be..ac10720d395 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx
@@ -137,7 +137,8 @@ function PreferredNameScreen({ navigation }: PreferredNameScreenProps) {
onLeftButtonPress={onConfirmCancel}
title={t('personalInformation.preferredName.title')}
primaryContentButtonText={preferredNameMutation.isPending ? undefined : t('save')}
- onPrimaryContentButtonPress={() => setOnSaveClicked(true)}>
+ onPrimaryContentButtonPress={() => setOnSaveClicked(true)}
+ leftButtonTestID="preferredNameBackID">
{preferredNameMutation.isPending ? (
) : (
diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/AccountSecurity/AccountSecurity.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/AccountSecurity/AccountSecurity.tsx
index 037349d802a..5fe964ab519 100644
--- a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/AccountSecurity/AccountSecurity.tsx
+++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/AccountSecurity/AccountSecurity.tsx
@@ -18,7 +18,9 @@ function AccountSecurity({ navigation }: AccountSecurityProps) {
+ title={t('accountSecurity')}
+ testID="accountSecurityScreenID"
+ backLabelTestID="backToSettingsScreenID">
-
+
diff --git a/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx b/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx
index c99920f2d91..14b6311f657 100644
--- a/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx
+++ b/VAMobile/src/screens/HomeScreen/VeteranStatusScreen/VeteranStatusScreen.tsx
@@ -50,7 +50,7 @@ function VeteranStatusScreen({ navigation }: VeteranStatusScreenProps) {
: undefined
useBeforeNavBackListener(navigation, () => {
- registerReviewEvent()
+ registerReviewEvent(true)
})
const getPeriodOfService: React.ReactNode = map(serviceHistory, (service: ServiceData) => {
@@ -94,7 +94,8 @@ function VeteranStatusScreen({ navigation }: VeteranStatusScreenProps) {
rightButtonText={t('close')}
dividerMarginBypass={true}
removeInsets={true}
- testID="veteranStatusTestID">
+ testID="veteranStatusTestID"
+ rightButtonTestID="veteranStatusCloseID">
+ {
- registerReviewEvent()
+ registerReviewEvent(true)
}, []),
)
@@ -45,7 +45,8 @@ function PaymentDetailsScreen({ navigation, route }: PaymentDetailsScreenProps)
+ title={t('paymentDetails.title')}
+ backLabelTestID="paymentDetailsBackID">