From b0cebadac05beba5cc70522c290a80608d14dc4b Mon Sep 17 00:00:00 2001 From: Florian Zia Date: Wed, 4 Sep 2024 15:59:37 +0200 Subject: [PATCH] wip: Debug E2E test failures in CI --- .env | 4 +- .github/workflows/build.yaml | 22 - .github/workflows/conflicts.yml | 16 - .github/workflows/docker_build_deploy.yml | 49 - .github/workflows/docker_check.yml | 15 - .github/workflows/e2e_cron.yml | 6 +- .github/workflows/e2e_pr_full.yml | 21 +- .github/workflows/e2e_pr_smoke.yml | 5 +- .github/workflows/glean-probe-scraper.yml | 13 - .github/workflows/preview_deploy_gcp.yml | 93 -- .../workflows/preview_deploy_gcp_cleanup.yml | 46 - .github/workflows/production_deploy.yml | 40 - .github/workflows/reference_linter.yaml | 25 - .github/workflows/release_retag.yaml | 36 - .github/workflows/unittests.yaml | 26 - playwright.config.js | 5 +- src/e2e/pages/purchasePage.ts | 2 +- src/e2e/pages/welcomeScanPage.ts | 15 +- src/e2e/specs/breachResolution.spec.ts | 211 ++- src/e2e/specs/dashboard.spec.ts | 1239 ++++++++--------- src/e2e/specs/landing.spec.ts | 274 ++-- src/e2e/specs/purchase.spec.ts | 362 ++--- 22 files changed, 1069 insertions(+), 1456 deletions(-) delete mode 100644 .github/workflows/build.yaml delete mode 100644 .github/workflows/conflicts.yml delete mode 100644 .github/workflows/docker_build_deploy.yml delete mode 100644 .github/workflows/docker_check.yml delete mode 100644 .github/workflows/glean-probe-scraper.yml delete mode 100644 .github/workflows/preview_deploy_gcp.yml delete mode 100644 .github/workflows/preview_deploy_gcp_cleanup.yml delete mode 100644 .github/workflows/production_deploy.yml delete mode 100644 .github/workflows/reference_linter.yaml delete mode 100644 .github/workflows/release_retag.yaml delete mode 100644 .github/workflows/unittests.yaml diff --git a/.env b/.env index 1ab1f6628ca..a86e9a734f9 100755 --- a/.env +++ b/.env @@ -115,8 +115,8 @@ E2E_TEST_ACCOUNT_EMAIL_ZERO_BROKERS= E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES_ZERO_BROKERS= E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED= -E2E_TEST_PAYPAL_LOGIN = -E2E_TEST_PAYPAL_PASSWORD = +E2E_TEST_PAYPAL_LOGIN= +E2E_TEST_PAYPAL_PASSWORD= # Monitor Premium features # Link to start user on the subscription process. PREMIUM_ENABLED must be set to `true`. diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 88b41611de9..00000000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: Build - -on: - pull_request: - types: [closed] - -jobs: - npm-build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version: '22.6.x' - - run: npm ci - - run: npm run build-glean - # Verify that the build (incl. type-checking) succeeds - # Upload sourcemaps to Sentry - - run: npm run build diff --git a/.github/workflows/conflicts.yml b/.github/workflows/conflicts.yml deleted file mode 100644 index 60d77098313..00000000000 --- a/.github/workflows/conflicts.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: No unresolved conflicts -on: - pull_request: - branches: [ main, localization ] -jobs: - detect-unresolved-conflicts: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: List files with merge conflict markers - # Encode conflict markers so this file does not trigger git's conflict detection. - run: git --no-pager grep "$(echo 'PDw8PDw8PAo=' | base64 -d)" ":(exclude).github/" || true - - name: Fail or succeed job if any files with merge conflict markers have been checked in - # Find lines containing conflict markers then count the number of lines. - # 0 matching lines results in exit code 0, i.e. success. - run: exit $(git grep "$(echo 'PDw8PDw8PAo=' | base64 -d)" ":(exclude).github/" | wc --lines) diff --git a/.github/workflows/docker_build_deploy.yml b/.github/workflows/docker_build_deploy.yml deleted file mode 100644 index c235a37807f..00000000000 --- a/.github/workflows/docker_build_deploy.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Build Docker image and publish - -on: - pull_request: - types: [closed] -jobs: - push_to_registry: - name: Push Docker image to Docker Hub - runs-on: ubuntu-latest - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: mozilla/blurts-server - tags: | - type=semver,pattern={{raw}} - type=raw,value={{sha}},event=tag - - - name: Create version.json - run: | - echo "{\"commit\":\"$GITHUB_SHA\",\"version\":\"$GITHUB_REF\",\"source\":\"https://github.com/$GITHUB_REPOSITORY\",\"build\":\"$GITHUB_RUN_ID\"}" > version.json - - - name: Build Docker image - env: - UPLOAD_SENTRY_SOURCEMAPS: true - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - run: | - docker build --tag blurts-server \ - --build-arg SENTRY_RELEASE="$GITHUB_REF_NAME" \ - . - - - name: Deploy to Dockerhub - env: - DOCKERHUB_REPO: ${{ env.DOCKERHUB_REPO }} - run: | - # deploy main - docker tag blurts-server ${{ steps.meta.outputs.tags }} - docker push ${{ steps.meta.outputs.tags }} - diff --git a/.github/workflows/docker_check.yml b/.github/workflows/docker_check.yml deleted file mode 100644 index 214f7667391..00000000000 --- a/.github/workflows/docker_check.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Build Docker image check -on: - pull_request: - types: [closed] -jobs: - docker_build: - name: Build Docker image - runs-on: ubuntu-latest - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Build Docker image - run: docker build . - diff --git a/.github/workflows/e2e_cron.yml b/.github/workflows/e2e_cron.yml index fd6b763836d..d3e91705a7b 100644 --- a/.github/workflows/e2e_cron.yml +++ b/.github/workflows/e2e_cron.yml @@ -48,7 +48,7 @@ jobs: run: npm run e2e timeout-minutes: 40 env: - E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'local' }} + E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'stage' }} E2E_TEST_BASE_URL: ${{ secrets.E2E_TEST_BASE_URL }} E2E_TEST_ACCOUNT_EMAIL: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL }} E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} @@ -78,7 +78,7 @@ jobs: retention-days: 30 - name: Send GitHub Action trigger data to Slack workflow id: slack - uses: slackapi/slack-github-action@v1.27.0 + uses: slackapi/slack-github-action@v1.26.0 if: failure() && github.ref == 'refs/heads/main' with: # For posting a message using Block Kit @@ -89,7 +89,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "*Link to job:* **" + "text": "*Link to job:* **" } }, { diff --git a/.github/workflows/e2e_pr_full.yml b/.github/workflows/e2e_pr_full.yml index ac99044c264..59f9fe343ea 100644 --- a/.github/workflows/e2e_pr_full.yml +++ b/.github/workflows/e2e_pr_full.yml @@ -42,7 +42,6 @@ jobs: PLAYWRIGHT_VERSION=$(npx playwright --version | sed 's/Version //') echo "Playwright Version: $PLAYWRIGHT_VERSION" echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV - - name: Cache Playwright Browsers for Playwright's Version id: cache-playwright-browsers uses: actions/cache@v4 @@ -59,21 +58,31 @@ jobs: run: npm run e2e timeout-minutes: 40 env: - E2E_TEST_ENV: ${{ inputs.environment != null && inputs.environment || 'local' }} - E2E_TEST_BASE_URL: ${{ secrets.E2E_TEST_BASE_URL }} + E2E_TEST_ENV: local + E2E_TEST_BASE_URL: http://localhost:6060 E2E_TEST_ACCOUNT_EMAIL: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL }} - E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES }} E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED }} - E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} + E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} + E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} E2E_TEST_PAYPAL_PASSWORD: ${{ secrets.E2E_TEST_PAYPAL_PASSWORD }} ADMINS: ${{ secrets.ADMINS }} - OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }} + OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET_LOCAL }} + OAUTH_ACCOUNT_URI: ${{ secrets.OAUTH_ACCOUNT_URI }} ONEREP_API_KEY: ${{ secrets.ONEREP_API_KEY }} NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }} NEXTAUTH_URL: ${{ secrets.NEXTAUTH_URL }} + DATABASE_URL: postgres://postgres:postgres@localhost:5432/blurts HIBP_KANON_API_TOKEN: ${{ secrets.HIBP_KANON_API_TOKEN }} HIBP_API_TOKEN: ${{ secrets.HIBP_API_TOKEN }} + HIBP_KANON_API_ROOT: "http://localhost:6060/api/mock/hibp" + ONEREP_API_BASE: "http://localhost:6060/api/mock/onerep/" + PREMIUM_PRODUCT_ID: ${{ secrets.STAGE_PREMIUM_PRODUCT_ID }} + PREMIUM_PLAN_ID_MONTHLY_US: ${{ secrets.STAGE_PREMIUM_PLAN_ID_MONTHLY_US }} + PREMIUM_PLAN_ID_YEARLY_US: ${{ secrets.STAGE_PREMIUM_PLAN_ID_YEARLY_US }} + # MNTOR-3516: Our tests are currently set up to expect accounts to act like + # old user accounts, so let's pretend they all are: + BROKER_SCAN_RELEASE_DATE: "3000-12-31" REDIS_URL: "redis://redis.mock" - uses: actions/upload-artifact@v4 if: always() diff --git a/.github/workflows/e2e_pr_smoke.yml b/.github/workflows/e2e_pr_smoke.yml index 35df9fef3b9..04cc1990a87 100644 --- a/.github/workflows/e2e_pr_smoke.yml +++ b/.github/workflows/e2e_pr_smoke.yml @@ -1,5 +1,5 @@ name: Monitor E2E Test Suite (smoke) -on: push +on: merge jobs: e2e-tests: timeout-minutes: 60 @@ -42,7 +42,6 @@ jobs: PLAYWRIGHT_VERSION=$(npx playwright --version | sed 's/Version //') echo "Playwright Version: $PLAYWRIGHT_VERSION" echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV - - name: Cache Playwright Browsers for Playwright's Version id: cache-playwright-browsers uses: actions/cache@v4 @@ -65,7 +64,7 @@ jobs: E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_ZERO_BREACHES }} E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED: ${{ secrets.E2E_TEST_ACCOUNT_EMAIL_EXPOSURES_STARTED }} E2E_TEST_ACCOUNT_PASSWORD: ${{ secrets.E2E_TEST_ACCOUNT_PASSWORD }} - E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} + E2E_TEST_PAYPAL_LOGIN: ${{ secrets.E2E_TEST_PAYPAL_LOGIN }} E2E_TEST_PAYPAL_PASSWORD: ${{ secrets.E2E_TEST_PAYPAL_PASSWORD }} ADMINS: ${{ secrets.ADMINS }} OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET_LOCAL }} diff --git a/.github/workflows/glean-probe-scraper.yml b/.github/workflows/glean-probe-scraper.yml deleted file mode 100644 index 47f97fd430e..00000000000 --- a/.github/workflows/glean-probe-scraper.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Glean probe-scraper -on: - push: - paths: - - src/telemetry/metrics.yaml - - src/telemetry/backend-metrics.yaml - pull_request: - paths: - - src/telemetry/metrics.yaml - - src/telemetry/backend-metrics.yaml -jobs: - glean-probe-scraper: - uses: mozilla/probe-scraper/.github/workflows/glean.yaml@main \ No newline at end of file diff --git a/.github/workflows/preview_deploy_gcp.yml b/.github/workflows/preview_deploy_gcp.yml deleted file mode 100644 index 9115a1a72a0..00000000000 --- a/.github/workflows/preview_deploy_gcp.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Deploy Preview - -on: - pull_request: - types: [closed] - -env: - PROJECT_ID: ${{ secrets.GCP_PROJECT }} - SERVICE: blurts-server - REGION: us-east4 - TAG: pr-${{ github.event.pull_request.number }} - DB_HOST: ${{ secrets.PREVIEW_DB_HOST }} - -jobs: - deploy: - permissions: - pull-requests: write - # Secrets aren't available for Dependabot PR (because the updated - # dependencies might abuse them), so they don't have enough rights to - # do a preview deployment: - if: github.actor != 'dependabot[bot]' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Cloud SDK - uses: 'google-github-actions/auth@v2' - with: - credentials_json: '${{ secrets.GCP_SA_KEY }}' - - - name: Use gcloud CLI - run: gcloud info - - - name: Generate database on the fly - id: db_create - # This can fail on the subsequent runs, we can ignore the error (database already exists) - continue-on-error: true - run: | - gcloud sql instances create ${{ env.SERVICE }}-${{ env.TAG }} --tier=db-f1-micro --region=${{ env.REGION }} --database-version=POSTGRES_15 --edition=enterprise - gcloud sql users set-password postgres --host=% --instance ${{ env.SERVICE }}-${{ env.TAG }} --password postgres - gcloud sql databases create blurts --instance=${{ env.SERVICE }}-${{ env.TAG }} - gcloud sql databases list --instance=${{ env.SERVICE }}-${{ env.TAG }} - gcloud sql instances list - - - name: Authorize Docker push - run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev - - - name: Build and Push Container - run: |- - docker build -t ${{env.REGION}}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}/${{ env.SERVICE }}:${{ env.TAG }} -f './Dockerfile.cloudrun' . - docker push ${{env.REGION}}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}/${{ env.SERVICE }}:${{ env.TAG }} - - - name: Deploy to Cloud Run - id: deploy - uses: google-github-actions/deploy-cloudrun@v2 - with: - service: ${{ env.SERVICE }}-${{ env.TAG }} - image: ${{env.REGION}}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.SERVICE }}/${{ env.SERVICE }}:${{ env.TAG }} - region: ${{ env.REGION }} - flags: "--allow-unauthenticated --add-cloudsql-instances=${{ env.PROJECT_ID }}:${{env.REGION}}:${{ env.SERVICE }}-${{ env.TAG }}" - # tag: ${{ env.TAG }} - env_vars: | - NEXTAUTH_URL= ${{ secrets.NEXTAUTH_URL }} - NEXTAUTH_SECRET=${{ secrets.NEXTAUTH_SECRET }} - OAUTH_ACCOUNT_URI=${{ secrets.OAUTH_ACCOUNT_URI }} - OAUTH_CLIENT_ID=${{ secrets.OAUTH_CLIENT_ID }} - OAUTH_CLIENT_SECRET=${{ secrets.OAUTH_CLIENT_SECRET }} - ONEREP_API_KEY=${{ secrets.ONEREP_API_KEY }} - APP_ENV=cloudrun - COOKIE_SECRET=secret - PG_HOST=/cloudsql/${{ env.PROJECT_ID }}:${{env.REGION}}:${{ env.SERVICE }}-${{ env.TAG }} - ADMINS=${{ secrets.ADMINS }} - HIBP_API_TOKEN=${{ secrets.HIBP_API_TOKEN }} - HIBP_KANON_API_TOKEN=${{ secrets.HIBP_KANON_API_TOKEN }} - AUTH_REDIRECT_PROXY_URL=${{ secrets.AUTH_REDIRECT_PROXY_URL }} - PGUSER=postgres - PGDATABASE=postgres - DB_NAME=blurts - DB_USER=postgres - DB_PASSWORD=postgres - CLOUD_SQL_CONNECTION_NAME=${{ env.PROJECT_ID }}:${{env.REGION}}:${{ env.SERVICE }}-${{ env.TAG }} - DATABASE_URL= postgres://postgres:postgres@localhost:5432/blurts - - - name: Comment on Pull Request - uses: thollander/actions-comment-pull-request@v2 - with: - GITHUB_TOKEN: ${{ github.token }} - message: | - Preview URL :rocket: : ${{ steps.deploy.outputs.url }} - comment_tag: preview_url - create_if_not_exists: true - diff --git a/.github/workflows/preview_deploy_gcp_cleanup.yml b/.github/workflows/preview_deploy_gcp_cleanup.yml deleted file mode 100644 index 83acc461453..00000000000 --- a/.github/workflows/preview_deploy_gcp_cleanup.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Deploy Preview Cleanup - -on: - # when pull request is merged or closed - pull_request: - types: [closed] - -env: - PROJECT_ID: ${{ secrets.GCP_PROJECT }} - SERVICE: blurts-server - REGION: us-east4 - TAG: pr-${{ github.event.pull_request.number }} - DB_HOST: ${{ secrets.PREVIEW_DB_HOST }} - -jobs: - deploy: - permissions: - pull-requests: write - # Secrets aren't available for Dependabot PR (because the updated - # dependencies might abuse them), so they don't have enough rights to - # do a preview deployment: - if: github.actor != 'dependabot[bot]' - runs-on: ubuntu-latest - steps: - - name: Setup Cloud SDK - uses: 'google-github-actions/auth@v2' - with: - credentials_json: '${{ secrets.GCP_SA_KEY }}' - - - name: Use gcloud CLI - run: 'gcloud info' - - - name: Delete created database - id: db_delete - # Delete cloud sql instance - run: 'gcloud sql instances delete blurts-server-${{ env.TAG }}' - - - name: Delete created cloud run service - id: cloudrun_delete - run: gcloud run services delete blurts-server-${{ env.TAG }} --region ${{ env.REGION }} --platform managed --quiet - - - name: Comment on Pull Request - uses: thollander/actions-comment-pull-request@v2 - with: - GITHUB_TOKEN: ${{ github.token }} - message: Cleanup completed - database 'blurts-server-${{ env.TAG }}' destroyed, cloud run service 'blurts-server-${{ env.TAG }}' destroyed diff --git a/.github/workflows/production_deploy.yml b/.github/workflows/production_deploy.yml deleted file mode 100644 index 093a3ba512d..00000000000 --- a/.github/workflows/production_deploy.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Monitor 1-click Deployment -on: - workflow_dispatch: - inputs: - environment: - description: 'Environment to deploy to' - required: true - default: 'prod' - type: choice - options: - - stage - - prod - originalImageTag: - description: 'The original image tag that has been deployed to dockerhub' - required: true - type: string -env: - DOCKER_IMAGE_NAME: mozilla/blurts-server -jobs: - pull_retag_push: - name: Push Docker image to Docker Hub - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Pull Docker image - run: docker pull ${{ env.DOCKER_IMAGE_NAME }}:${{ inputs.originalImageTag }} - - - name: Retag image - run: docker tag ${{ env.DOCKER_IMAGE_NAME }}:${{ inputs.originalImageTag }} ${{ env.DOCKER_IMAGE_NAME }}:${{ inputs.environment }}-${{ inputs.originalImageTag }} - - - name: Redeploy image - run: docker push ${{ env.DOCKER_IMAGE_NAME }}:${{ inputs.environment }}-${{ inputs.originalImageTag }} \ No newline at end of file diff --git a/.github/workflows/reference_linter.yaml b/.github/workflows/reference_linter.yaml deleted file mode 100644 index 0355144fb89..00000000000 --- a/.github/workflows/reference_linter.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Lint Reference Files -on: - pull_request: - types: [closed] -jobs: - l10n-lint: - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v4 - - name: Set up Python 3 - uses: actions/setup-python@v5 - with: - python-version: '3.10' - cache: 'pip' - - name: Install Python dependencies - run: | - pip install -r .github/requirements.txt - - name: Lint reference strings - run: | - moz-fluent-lint ./locales/en/ --config .github/linter_config.yml - - name: Lint pending strings - if: always() # This step should run even if the previous one fails - run: | - moz-fluent-lint ./locales-pending/ --config .github/linter_config.yml diff --git a/.github/workflows/release_retag.yaml b/.github/workflows/release_retag.yaml deleted file mode 100644 index a9b6d38b2ae..00000000000 --- a/.github/workflows/release_retag.yaml +++ /dev/null @@ -1,36 +0,0 @@ -name: Retag and Push Docker Image on Release -# GH release should always create a tag automatically -on: - push: - tags: - - '*' - -jobs: - retag-and-push: - runs-on: ubuntu-latest - - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: mozilla/blurts-server - tags: type=sha,format=short,prefix= - - - name: Pull Docker image with commit tag - run: docker pull ${{ steps.meta.outputs.tags }} - - - name: Tag Docker image with release tag - run: docker tag ${{ steps.meta.outputs.tags }} mozilla/blurts-server:${{ github.ref_name }} - - - name: Push Docker image with release tag - run: docker push mozilla/blurts-server:${{ github.ref_name }} diff --git a/.github/workflows/unittests.yaml b/.github/workflows/unittests.yaml deleted file mode 100644 index b8ef110377a..00000000000 --- a/.github/workflows/unittests.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: Unit Tests - -on: - pull_request: - types: [closed] - -jobs: - unit-tests: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version: '22.6.x' - - run: npm ci - - run: npm run build-glean - - run: npm test - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: coverage-report - path: coverage/ - retention-days: 30 diff --git a/playwright.config.js b/playwright.config.js index 1c3039b2b66..f400189f150 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -51,7 +51,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, /* Limit the number of failures */ - maxFailures: process.env.CI ? 1 : undefined, + maxFailures: 1, /* Retry on CI only */ retries: process.env.CI ? 1 : 0, @@ -68,8 +68,7 @@ export default defineConfig({ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: process.env.E2E_TEST_BASE_URL ?? 'https://stage.firefoxmonitor.nonprod.cloudops.mozgcp.net', - // baseURL: 'http://localhost:6060', + baseURL: process.env.E2E_TEST_BASE_URL, /* automatically take screenshot only on failures */ screenshot: 'only-on-failure', diff --git a/src/e2e/pages/purchasePage.ts b/src/e2e/pages/purchasePage.ts index 2892c736f75..3c1b15659de 100644 --- a/src/e2e/pages/purchasePage.ts +++ b/src/e2e/pages/purchasePage.ts @@ -124,7 +124,7 @@ export class PurchasePage { (await this.planDetails.textContent()) as string, ); expect(planDetails).toContain( - `${process.env.E2E_TEST_ENV === "prod" ? "yearly" : "every 2 months"}`, + `${process.env.E2E_TEST_ENV === "local" ? "every 2 months" : "yearly"}`, ); } diff --git a/src/e2e/pages/welcomeScanPage.ts b/src/e2e/pages/welcomeScanPage.ts index 2368ef638e0..c840c42adb7 100644 --- a/src/e2e/pages/welcomeScanPage.ts +++ b/src/e2e/pages/welcomeScanPage.ts @@ -28,6 +28,8 @@ export class WelcomePage { readonly modalConfirmButton: Locator; readonly modalEditButton: Locator; + readonly findExposuresTitle: Locator; + constructor(page: Page) { this.page = page; @@ -67,9 +69,11 @@ export class WelcomePage { this.isThisCorrectModal = page.getByLabel("Is this correct?"); this.modalConfirmButton = page.getByRole("button", { name: "Confirm" }); this.modalEditButton = page.getByRole("button", { name: "Edit" }); + + this.findExposuresTitle = page.getByText("Scanning for exposures…"); } - async goThroughFirstScan() { + async goThroughFirstScan(options: { skipLoader: boolean }) { // confirm get started step elements expect(await this.getStartedStep.count()).toEqual(3); await expect(this.page.getByText("Get started")).toBeVisible(); @@ -88,6 +92,15 @@ export class WelcomePage { await this.findExposuresButton.click(); await this.modalConfirmButton.click(); + await this.findExposuresTitle.waitFor(); + + // reloading page skips the loader and routes directly to the dashboard + if (options.skipLoader) { + // wait for scan to be finished before reloading the page + await this.page.waitForTimeout(10000); + await this.page.reload(); + } + // Waiting for scan to complete const dashboardPage = new DashboardPage(this.page); await dashboardPage.actionNeededTab.waitFor(); diff --git a/src/e2e/specs/breachResolution.spec.ts b/src/e2e/specs/breachResolution.spec.ts index 16bcd0a4a7e..e17370ed457 100644 --- a/src/e2e/specs/breachResolution.spec.ts +++ b/src/e2e/specs/breachResolution.spec.ts @@ -6,115 +6,112 @@ import { test, expect } from "../fixtures/basePage.js"; // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, - () => { - test("Verify that the site header is displayed correctly for signed in users", async ({ - dataBreachPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095101", - }); - - // should go directly to data breach page - await dataBreachPage.open(); - - // verify logo and profile button - await expect(dataBreachPage.dataBreachesLogo).toBeVisible(); - await expect(dataBreachPage.dataBreachesNavbarProfile).toBeVisible(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers`, () => { + test("Verify that the site header is displayed correctly for signed in users", async ({ + dataBreachPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095101", }); - // skip as settings dropdown menu is currently wip for redesign TODO: update for redesign when its done - test.skip("Verify that the site header options work correctly for a signed in user", async ({ - dataBreachPage, - settingsPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095102", - }); - - // should go directly to data breach page - await settingsPage.open(); - - // verify logo and profile button - expect( - await dataBreachPage.dataBreachesLogoLink.first().getAttribute("href"), - ).toBe("/user/breaches"); - - await page.waitForLoadState("networkidle"); - await dataBreachPage.dataBreachesNavbarProfile.click(); - - // verify manage your Mozilla account link, settings option, help and support option, sign out option - // menu is open - expect(await dataBreachPage.profileMenuExpanded()).toBe(true); - - // menu header - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHeader, - ).toBeVisible(); - - // head text - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHeaderSubtitle, - ).toHaveText("Manage your Mozilla account"); - - // check settings - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuSettings, - ).toBeVisible(); - - // help and support - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuHelpAndSupport, - ).toBeVisible(); - - // sign out - await expect( - dataBreachPage.dataBreachesNavbarProfileMenuSignOut, - ).toBeVisible(); + // should go directly to data breach page + await dataBreachPage.open(); + + // verify logo and profile button + await expect(dataBreachPage.dataBreachesLogo).toBeVisible(); + await expect(dataBreachPage.dataBreachesNavbarProfile).toBeVisible(); + }); + + // skip as settings dropdown menu is currently wip for redesign TODO: update for redesign when its done + test.skip("Verify that the site header options work correctly for a signed in user", async ({ + dataBreachPage, + settingsPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095102", }); - test(" Verify that the user can navigate through the Monitor dashboard", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2095103", - }); - - // open dashboard page - await dashboardPage.open(); - - // get expected links - const links = dashboardPage.dashboardLinks(); - - // verify the navigation within monitor - // settings button redirects the user to "Settings" tab - await expect(dashboardPage.settingsPageLink).toHaveAttribute( - "href", - links.settingsNavButtonLink, - ); - - // redirects the user to the "Resolve data breaches (dashboard)" tab - await expect(dashboardPage.dashboardPageLink).toHaveAttribute( - "href", - links.resolveDataBreachesNavButtonLink, - ); - - // opens a new tab in which user is redirected to the "Monitor Help (FAQs)" page - await expect(dashboardPage.faqsPageLink).toHaveAttribute( - "href", - links.helpAndSupportNavButtonLink, - ); + // should go directly to data breach page + await settingsPage.open(); + + // verify logo and profile button + expect( + await dataBreachPage.dataBreachesLogoLink.first().getAttribute("href"), + ).toBe("/user/breaches"); + + await page.waitForLoadState("networkidle"); + await dataBreachPage.dataBreachesNavbarProfile.click(); + + // verify manage your Mozilla account link, settings option, help and support option, sign out option + // menu is open + expect(await dataBreachPage.profileMenuExpanded()).toBe(true); + + // menu header + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHeader, + ).toBeVisible(); + + // head text + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHeaderSubtitle, + ).toHaveText("Manage your Mozilla account"); + + // check settings + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuSettings, + ).toBeVisible(); + + // help and support + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuHelpAndSupport, + ).toBeVisible(); + + // sign out + await expect( + dataBreachPage.dataBreachesNavbarProfileMenuSignOut, + ).toBeVisible(); + }); + + test(" Verify that the user can navigate through the Monitor dashboard", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2095103", }); - }, -); + + // open dashboard page + await dashboardPage.open(); + + // get expected links + const links = dashboardPage.dashboardLinks(); + + // verify the navigation within monitor + // settings button redirects the user to "Settings" tab + await expect(dashboardPage.settingsPageLink).toHaveAttribute( + "href", + links.settingsNavButtonLink, + ); + + // redirects the user to the "Resolve data breaches (dashboard)" tab + await expect(dashboardPage.dashboardPageLink).toHaveAttribute( + "href", + links.resolveDataBreachesNavButtonLink, + ); + + // opens a new tab in which user is redirected to the "Monitor Help (FAQs)" page + await expect(dashboardPage.faqsPageLink).toHaveAttribute( + "href", + links.helpAndSupportNavButtonLink, + ); + }); +}); diff --git a/src/e2e/specs/dashboard.spec.ts b/src/e2e/specs/dashboard.spec.ts index d30c1745e3b..e73a41c6b10 100644 --- a/src/e2e/specs/dashboard.spec.ts +++ b/src/e2e/specs/dashboard.spec.ts @@ -20,216 +20,213 @@ import { // bypass login test.use({ storageState: "./e2e/storageState.json" }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Headers @smoke`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - test("Verify that the site header is displayed correctly for signed in users", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301512", - }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - await expect(dashboardPage.dashboardNavButton).toHaveAttribute( - "href", - "/user/dashboard", - ); - await expect(dashboardPage.FAQsNavButton).toHaveAttribute( - "href", - "https://support.mozilla.org/kb/firefox-monitor-faq", - ); + test("Verify that the site header is displayed correctly for signed in users", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301512", }); - test("Verify that the site header and navigation bar is displayed correctly", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push( - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", - }, - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463567", - }, - ); - - // verify the navigation bar left side elements - await expect(dashboardPage.fireFoxMonitorLogoImgButton).toBeVisible(); - await expect(dashboardPage.dashboardNavButton).toBeVisible(); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - await expect(dashboardPage.settingsPageLink).toBeVisible(); - await expect(dashboardPage.FAQsNavButton).toBeVisible(); - - // verify the site header elements - await expect(dashboardPage.actionNeededTab).toBeVisible(); - await expect(dashboardPage.fixedTab).toBeVisible(); - - // auto data removal button - await expect(dashboardPage.subscribeButton).toBeVisible(); - - // apps and services - await expect(dashboardPage.appsAndServices).toBeVisible(); - await dashboardPage.appsAndServices.click(); - await expect(dashboardPage.servicesVpn).toBeVisible(); - await expect(dashboardPage.servicesRelay).toBeVisible(); - await expect(dashboardPage.servicesPocket).toBeVisible(); - await expect(dashboardPage.servicesFirefoxDesktop).toBeVisible(); - await expect(dashboardPage.servicesFirefoxMobile).toBeVisible(); - - // profile button - await dashboardPage.closeAppsAndServices.click(); - await expect(dashboardPage.profileButton).toBeVisible(); - await dashboardPage.profileButton.click(); - await expect(dashboardPage.profileEmail).toBeVisible(); - await expect(dashboardPage.manageProfile).toBeVisible(); - await expect(dashboardPage.settingsPageLink).toBeVisible(); - await expect(dashboardPage.helpAndSupport).toBeVisible(); - await expect(dashboardPage.signOut).toBeVisible(); - }); + await expect(dashboardPage.dashboardNavButton).toHaveAttribute( + "href", + "/user/dashboard", + ); + await expect(dashboardPage.FAQsNavButton).toHaveAttribute( + "href", + "https://support.mozilla.org/kb/firefox-monitor-faq", + ); + }); - test("Verify that the correct message is displayed on the Action Needed tab when all the exposures are fixed", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ + test("Verify that the site header and navigation bar is displayed correctly", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push( + { type: "testrail", description: "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", - }); + }, + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463567", + }, + ); - // verify overview card - await expect(dashboardPage.dashboardMozLogo).toBeVisible(); + // verify the navigation bar left side elements + await expect(dashboardPage.fireFoxMonitorLogoImgButton).toBeVisible(); + await expect(dashboardPage.dashboardNavButton).toBeVisible(); + await expect(dashboardPage.exposuresHeading).toBeVisible(); + await expect(dashboardPage.settingsPageLink).toBeVisible(); + await expect(dashboardPage.FAQsNavButton).toBeVisible(); + + // verify the site header elements + await expect(dashboardPage.actionNeededTab).toBeVisible(); + await expect(dashboardPage.fixedTab).toBeVisible(); + + // auto data removal button + await expect(dashboardPage.subscribeButton).toBeVisible(); + + // apps and services + await expect(dashboardPage.appsAndServices).toBeVisible(); + await dashboardPage.appsAndServices.click(); + await expect(dashboardPage.servicesVpn).toBeVisible(); + await expect(dashboardPage.servicesRelay).toBeVisible(); + await expect(dashboardPage.servicesPocket).toBeVisible(); + await expect(dashboardPage.servicesFirefoxDesktop).toBeVisible(); + await expect(dashboardPage.servicesFirefoxMobile).toBeVisible(); + + // profile button + await dashboardPage.closeAppsAndServices.click(); + await expect(dashboardPage.profileButton).toBeVisible(); + await dashboardPage.profileButton.click(); + await expect(dashboardPage.profileEmail).toBeVisible(); + await expect(dashboardPage.manageProfile).toBeVisible(); + await expect(dashboardPage.settingsPageLink).toBeVisible(); + await expect(dashboardPage.helpAndSupport).toBeVisible(); + await expect(dashboardPage.signOut).toBeVisible(); + }); - // TODO: add verifications for all fixed exposures state + test("Verify that the correct message is displayed on the Action Needed tab when all the exposures are fixed", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301511", }); - test("Verify that the Fixed tab layout and tooltips are displayed correctly", async ({ - dashboardPage, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301532", - }); + // verify overview card + await expect(dashboardPage.dashboardMozLogo).toBeVisible(); - // verify fixed tab's tooltips and popups - await dashboardPage.fixedTab.click(); + // TODO: add verifications for all fixed exposures state + }); - // verify tooltip - await expect(dashboardPage.fixedHeading).toBeVisible(); - await dashboardPage.chartTooltip.click(); - await expect(dashboardPage.aboutFixedExposuresPopup).toBeVisible(); - await dashboardPage.popupCloseButton.click(); - await expect(dashboardPage.aboutFixedExposuresPopup).toBeHidden(); + test("Verify that the Fixed tab layout and tooltips are displayed correctly", async ({ + dashboardPage, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301532", }); - test("Verify that the Apps and Services header options work correctly.", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463569", - }); + // verify fixed tab's tooltips and popups + await dashboardPage.fixedTab.click(); - await dashboardPage.fixedTab.click(); - expect(page.url()).toMatch(/.*dashboard\/fixed\/?/); - await dashboardPage.actionNeededTab.click(); - expect(page.url()).toMatch(/.*dashboard\/action-needed\/?/); - - //apps and services button check - const clickOnLinkAndGoBack = async ( - aTag: Locator, - host: string | RegExp = /.*/, - path: string | RegExp = /.*/, - ) => { - await expect(dashboardPage.appsAndServices).toBeVisible(); - await dashboardPage.appsAndServices.click(); - await expect(dashboardPage.appsAndServicesMenu).toBeVisible(); - await clickOnATagCheckDomain(aTag, host, path, page); - }; - - await clickOnLinkAndGoBack( - dashboardPage.servicesVpn, - "www.mozilla.org", - /.*\/products\/vpn\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesRelay, - "relay.firefox.com", - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesPocket, - /getpocket\.com|apps\.apple\.com|app\.adjust\.com/, - /.*(\/pocket-and-firefox\/?).*|.*about.*|.*pocket-stay-informed.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesFirefoxDesktop, - "www.mozilla.org", - /.*\/firefox\/new\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesFirefoxMobile, - "www.mozilla.org", - /.*\/browsers\/mobile\/?.*/, - ); - await clickOnLinkAndGoBack( - dashboardPage.servicesMozilla, - "www.mozilla.org", - ); + // verify tooltip + await expect(dashboardPage.fixedHeading).toBeVisible(); + await dashboardPage.chartTooltip.click(); + await expect(dashboardPage.aboutFixedExposuresPopup).toBeVisible(); + await dashboardPage.popupCloseButton.click(); + await expect(dashboardPage.aboutFixedExposuresPopup).toBeHidden(); + }); - const openProfileMenuItem = async ( - what: Locator, - whatUrl: string | RegExp, - ) => { - await dashboardPage.open(); - await dashboardPage.profileButton.click(); - await expect(what).toBeVisible(); - if (await what.evaluate((e) => e.hasAttribute("href"))) { - const href = await what.getAttribute("href"); - expect(href).not.toBeNull(); - await page.goto(href!); - } else { - await what.click(); - } - await page.waitForURL(whatUrl); - }; + test("Verify that the Apps and Services header options work correctly.", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463569", + }); - await openProfileMenuItem( - dashboardPage.manageProfile, - /.*accounts.*settings.*/, - ); - await openProfileMenuItem( - dashboardPage.profileSettings, - /.*\/user\/settings.*/, - ); + await dashboardPage.fixedTab.click(); + expect(page.url()).toMatch(/.*dashboard\/fixed\/?/); + await dashboardPage.actionNeededTab.click(); + expect(page.url()).toMatch(/.*dashboard\/action-needed\/?/); + + //apps and services button check + const clickOnLinkAndGoBack = async ( + aTag: Locator, + host: string | RegExp = /.*/, + path: string | RegExp = /.*/, + ) => { + await expect(dashboardPage.appsAndServices).toBeVisible(); + await dashboardPage.appsAndServices.click(); + await expect(dashboardPage.appsAndServicesMenu).toBeVisible(); + await clickOnATagCheckDomain(aTag, host, path, page); + }; + + await clickOnLinkAndGoBack( + dashboardPage.servicesVpn, + "www.mozilla.org", + /.*\/products\/vpn\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesRelay, + "relay.firefox.com", + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesPocket, + /getpocket\.com|apps\.apple\.com|app\.adjust\.com/, + /.*(\/pocket-and-firefox\/?).*|.*about.*|.*pocket-stay-informed.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesFirefoxDesktop, + "www.mozilla.org", + /.*\/firefox\/new\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesFirefoxMobile, + "www.mozilla.org", + /.*\/browsers\/mobile\/?.*/, + ); + await clickOnLinkAndGoBack( + dashboardPage.servicesMozilla, + "www.mozilla.org", + ); - const base_url = process.env["E2E_TEST_BASE_URL"]; - expect(base_url).toBeTruthy(); - await openProfileMenuItem(dashboardPage.profileSignOut, base_url!); - }); - }, -); + const openProfileMenuItem = async ( + what: Locator, + whatUrl: string | RegExp, + ) => { + await dashboardPage.open(); + await dashboardPage.profileButton.click(); + await expect(what).toBeVisible(); + if (await what.evaluate((e) => e.hasAttribute("href"))) { + const href = await what.getAttribute("href"); + expect(href).not.toBeNull(); + await page.goto(href!); + } else { + await what.click(); + } + await page.waitForURL(whatUrl); + }; + + await openProfileMenuItem( + dashboardPage.manageProfile, + /.*accounts.*settings.*/, + ); + await openProfileMenuItem( + dashboardPage.profileSettings, + /.*\/user\/settings.*/, + ); + + const base_url = process.env["E2E_TEST_BASE_URL"]; + expect(base_url).toBeTruthy(); + await openProfileMenuItem(dashboardPage.profileSignOut, base_url!); + }); +}); // fix coming - playwright does not currently have access to the aws headers, skipping for now test.describe.skip( @@ -264,487 +261,469 @@ test.describe.skip( }, ); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Content @smoke`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); + + test("Verify that the exposure list contains action needed", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", }); - test("Verify that the exposure list contains action needed", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ + await expect(dashboardPage.exposuresHeading).toBeVisible(); + const listCount = await page + .locator('//div[starts-with(@class, "StatusPill_pill")]') + .count(); + + // verify exposure list conatins only exposures that need to be fixed + if (listCount > 0) { + for (let i = 0; i < listCount; i++) { + await expect( + page.locator( + `(//div[starts-with(@class, 'StatusPill_pill')])[${i + 1}]`, + ), + ).toHaveText("Action needed"); + } + } + }); + + test("Verify that the exposure list contains only fixed and in progress cards", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push( + { type: "testrail", description: "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", - }); - - await expect(dashboardPage.exposuresHeading).toBeVisible(); - const listCount = await page - .locator('//div[starts-with(@class, "StatusPill_pill")]') - .count(); - - // verify exposure list conatins only exposures that need to be fixed - if (listCount > 0) { - for (let i = 0; i < listCount; i++) { - await expect( - page.locator( - `(//div[starts-with(@class, 'StatusPill_pill')])[${i + 1}]`, - ), - ).toHaveText("Action needed"); - } - } - }); - - test("Verify that the exposure list contains only fixed and in progress cards", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push( - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301533", - }, - { - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2546463", - }, - ); + }, + { + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2546463", + }, + ); - await expect(dashboardPage.exposuresHeading).toBeVisible(); - await dashboardPage.fixedTab.click(); - - // verify fixed or in-progress - await expect(dashboardPage.fixedHeading).toBeVisible(); - - // TODO: add stub to fill in fixed/in-progress items - const listCount = await page - .locator('//div[starts-with(@class, "StatusPill_pill")]') - .count(); - // verify exposure list contains only exposures that need to be fixed - if (listCount > 0) { - for (let i = 0; i < listCount; i++) { - await expect( - page.locator( - `(//div[starts-with(@class, "StatusPill_pill")])[${i + 1}]`, - ), - ).toHaveText(/In progress|Fixed/); - } + await expect(dashboardPage.exposuresHeading).toBeVisible(); + await dashboardPage.fixedTab.click(); + + // verify fixed or in-progress + await expect(dashboardPage.fixedHeading).toBeVisible(); + + // TODO: add stub to fill in fixed/in-progress items + const listCount = await page + .locator('//div[starts-with(@class, "StatusPill_pill")]') + .count(); + // verify exposure list contains only exposures that need to be fixed + if (listCount > 0) { + for (let i = 0; i < listCount; i++) { + await expect( + page.locator( + `(//div[starts-with(@class, "StatusPill_pill")])[${i + 1}]`, + ), + ).toHaveText(/In progress|Fixed/); } - }); - }, -); + } + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Payment`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - test("Verify that the user can select what type of plan they want, verify that the Premium upsell modal is displayed correctly", async ({ - dashboardPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", - }, - { - type: "testrail id #3", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463624", - }, - ); + test("Verify that the user can select what type of plan they want, verify that the Premium upsell modal is displayed correctly", async ({ + dashboardPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", + }, + { + type: "testrail id #3", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463624", + }, + ); - await dashboardPage.subscribeButton.click(); - await dashboardPage.verifyPremiumUpsellModalOptions(); - }); - }, -); + await dashboardPage.subscribeButton.click(); + await dashboardPage.verifyPremiumUpsellModalOptions(); + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, Continuous Protection, Data Profile Actions`, - () => { - test.use({ storageState: { cookies: [], origins: [] } }); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Breaches Scan, Continuous Protection, Data Profile Actions`, () => { + test.use({ storageState: { cookies: [], origins: [] } }); - test.beforeEach(async ({ landingPage, page, authPage, welcomePage }) => { - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + test.beforeEach(async ({ landingPage, page, authPage, welcomePage }) => { + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - await landingPage.open(); - await landingPage.goToSignIn(); + await landingPage.open(); + await landingPage.goToSignIn(); - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); + expect(page.url()).toContain("/user/dashboard"); + }); - test("Verify that the Premium upsell modal is displayed correctly - Continuous Protection, verify that the user can mark Data broker profiles as fixed", async ({ - dashboardPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "(continuous protection step) https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463591", - }, - ); - let initialExposuresCount = - (await dashboardPage.numExposures.textContent()) as string; - initialExposuresCount = removeUnicodeChars(initialExposuresCount); - - if (initialExposuresCount !== "0") { - await dashboardPage.allExposures.first().click(); - await dashboardPage.fixExposureButton.click(); - await dashboardPage.removeExposuresManually.click(); - await dashboardPage.reviewAndRemoveProfiles.waitFor(); - - const count = await dashboardPage.allExposures.count(); - // Fix first exposure - await dashboardPage.markAsFixed.click(); - - for (let i = 1; i < count; i++) { - const exposure = dashboardPage.allExposures.nth(i); - await exposure.click(); - - if (await dashboardPage.markAsFixed.isVisible()) { - await dashboardPage.markAsFixed.click(); - } + test("Verify that the Premium upsell modal is displayed correctly - Continuous Protection, verify that the user can mark Data broker profiles as fixed", async ({ + dashboardPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", + description: + "(continuous protection step) https://testrail.stage.mozaws.net/index.php?/cases/view/2463623", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463591", + }, + ); + let initialExposuresCount = + (await dashboardPage.numExposures.textContent()) as string; + initialExposuresCount = removeUnicodeChars(initialExposuresCount); + + if (initialExposuresCount !== "0") { + await dashboardPage.allExposures.first().click(); + await dashboardPage.fixExposureButton.click(); + await dashboardPage.removeExposuresManually.click(); + await dashboardPage.reviewAndRemoveProfiles.waitFor(); + + const count = await dashboardPage.allExposures.count(); + // Fix first exposure + await dashboardPage.markAsFixed.click(); + + for (let i = 1; i < count; i++) { + const exposure = dashboardPage.allExposures.nth(i); + await exposure.click(); + + if (await dashboardPage.markAsFixed.isVisible()) { + await dashboardPage.markAsFixed.click(); } - - await dashboardPage.skipExposureRemoval.click(); } - await dashboardPage.continuousProtectionButton.waitFor(); - await expect(dashboardPage.continuousProtectionButton).toBeVisible(); - await dashboardPage.continuousProtectionButton.click(); - await dashboardPage.verifyPremiumUpsellModalOptions(); - // Using toMatch to avoid invisible unicode chars mismatch - expect(await dashboardPage.numExposures.textContent()).toMatch("0"); - await dashboardPage.fixedTab.click(); - const fixedExposures = await dashboardPage.numFixed.textContent(); - expect(fixedExposures as string).toMatch(initialExposuresCount); - }); - }, -); + await dashboardPage.skipExposureRemoval.click(); + } + + await dashboardPage.continuousProtectionButton.waitFor(); + await expect(dashboardPage.continuousProtectionButton).toBeVisible(); + await dashboardPage.continuousProtectionButton.click(); + await dashboardPage.verifyPremiumUpsellModalOptions(); + // Using toMatch to avoid invisible unicode chars mismatch + expect(await dashboardPage.numExposures.textContent()).toMatch("0"); + await dashboardPage.fixedTab.click(); + const fixedExposures = await dashboardPage.numFixed.textContent(); + expect(fixedExposures as string).toMatch(initialExposuresCount); + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Overview Card`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } - }); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - test("Verify that the Premium upsell screen is displayed correctly - overview card", async ({ - dashboardPage, - automaticRemovePage, - dataBrokersPage, - page, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463625", - }); + test("Verify that the Premium upsell screen is displayed correctly - overview card", async ({ + dashboardPage, + automaticRemovePage, + dataBrokersPage, + page, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463625", + }); - //checking that the user can reach upsell page - await dashboardPage.goToDashboard(); - await expect(dashboardPage.upsellScreenButton).toBeVisible(); - await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); - await dataBrokersPage.removeThemForMeButton.click(); - await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); + //checking that the user can reach upsell page + await dashboardPage.goToDashboard(); + await expect(dashboardPage.upsellScreenButton).toBeVisible(); + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); + await dataBrokersPage.removeThemForMeButton.click(); + await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); + + //checking the bullet points + await expect(automaticRemovePage.ulElement).toBeVisible(); + + for (const itemText of automaticRemovePage.bulletPointsExpected) { + const liElement = automaticRemovePage.liElements.getByText(itemText); + await expect(liElement).toBeVisible(); + } + + //testing that toggles work + await automaticRemovePage.planToggle0.click(); + const price0 = await automaticRemovePage.price.textContent(); + const plan0 = await automaticRemovePage.plan.textContent(); + await automaticRemovePage.planToggle1.click(); + const price1 = await automaticRemovePage.price.textContent(); + const plan1 = await automaticRemovePage.plan.textContent(); + expect(price0).not.toEqual(price1); + expect(plan0).not.toEqual(plan1); + }); - //checking the bullet points - await expect(automaticRemovePage.ulElement).toBeVisible(); + test("Verify that the navigation of the Premium upsell screen works correctly - from overview card", async ({ + dashboardPage, + automaticRemovePage, + dataBrokersPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463626", + }); - for (const itemText of automaticRemovePage.bulletPointsExpected) { - const liElement = automaticRemovePage.liElements.getByText(itemText); - await expect(liElement).toBeVisible(); - } + await dashboardPage.open(); + await page.waitForURL("**/dashboard/**"); + + //get the number of exposures count + const overviewCardSummary = + await dashboardPage.overviewCardSummary.textContent(); + const overviewCardFindings = + await dashboardPage.overviewCardFindings.textContent(); + expect(overviewCardFindings).not.toContain("No exposures found"); + expect(overviewCardSummary).not.toBeNull(); + const exposuresCountMatches = overviewCardSummary!.match(/\d+/); + expect(exposuresCountMatches).toBeTruthy(); + expect(exposuresCountMatches!.length).toBeGreaterThan(0); + const exposuresCount = parseInt(exposuresCountMatches![0]); + + //check that premium upsell screen loads + await dashboardPage.upsellScreenButton.click(); + await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); + await dataBrokersPage.removeThemForMeButton.click(); + await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); + + //check that X returns back to /dashboard + await expect(automaticRemovePage.xButton).toBeVisible(); + + await automaticRemovePage.xButton.click(); + await page.waitForURL(dashboardPage.urlRegex); + + //forward arrow checks + await automaticRemovePage.open(); + await expect(automaticRemovePage.forwardArrowButton).toBeVisible(); + + const breachString0 = "high-risk-data-breaches"; + const breachString1 = "leaked-passwords"; + const breachString2 = "security-recommendations"; + + const breachOrDashboard = (excludeThis: string) => { + const escapedExclude = escapeRegExp(excludeThis); + const pattern = [ + dashboardPage.urlRegex.source, + breachString0, + breachString1, + breachString2, + ] + .map((s) => `.*${s}.*`) + .join("|"); + + return new RegExp(`^(?!.*${escapedExclude})(${pattern})`); + }; + + const checkBreachLink = async () => { + const currentUrl = page.url(); + await automaticRemovePage.forwardArrowButton.click(); + await page.waitForURL(breachOrDashboard(currentUrl)); + const urlToCheck = page.url(); + const breachStringRE = new RegExp( + `.*(${[breachString0, breachString1, breachString2].join("|")}).*`, + ); + return breachStringRE.test(urlToCheck); + }; - //testing that toggles work - await automaticRemovePage.planToggle0.click(); - const price0 = await automaticRemovePage.price.textContent(); - const plan0 = await automaticRemovePage.plan.textContent(); - await automaticRemovePage.planToggle1.click(); - const price1 = await automaticRemovePage.price.textContent(); - const plan1 = await automaticRemovePage.plan.textContent(); - expect(price0).not.toEqual(price1); - expect(plan0).not.toEqual(plan1); - }); + let iter = 0; + while (await checkBreachLink()) iter++; + const visitedBreachPages = iter !== 0; + const exposuresExist = exposuresCount !== 0; + expect(visitedBreachPages).toBe(exposuresExist); - test("Verify that the navigation of the Premium upsell screen works correctly - from overview card", async ({ - dashboardPage, - automaticRemovePage, - dataBrokersPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463626", - }); + //price&plan toggle checks + await automaticRemovePage.open(); + const subplatRegex = /\/products\/prod_/; - await dashboardPage.open(); - await page.waitForURL("**/dashboard/**"); - - //get the number of exposures count - const overviewCardSummary = - await dashboardPage.overviewCardSummary.textContent(); - const overviewCardFindings = - await dashboardPage.overviewCardFindings.textContent(); - expect(overviewCardFindings).not.toContain("No exposures found"); - expect(overviewCardSummary).not.toBeNull(); - const exposuresCountMatches = overviewCardSummary!.match(/\d+/); - expect(exposuresCountMatches).toBeTruthy(); - expect(exposuresCountMatches!.length).toBeGreaterThan(0); - const exposuresCount = parseInt(exposuresCountMatches![0]); - - //check that premium upsell screen loads - await dashboardPage.upsellScreenButton.click(); - await page.waitForURL(/.*\/fix\/.*\/view-data-brokers\/?/); - await dataBrokersPage.removeThemForMeButton.click(); - await page.waitForURL(/.*\/fix\/.*\/automatic-remove\/?/); - - //check that X returns back to /dashboard - await expect(automaticRemovePage.xButton).toBeVisible(); - - await automaticRemovePage.xButton.click(); - await page.waitForURL(dashboardPage.urlRegex); - - //forward arrow checks - await automaticRemovePage.open(); - await expect(automaticRemovePage.forwardArrowButton).toBeVisible(); - - const breachString0 = "high-risk-data-breaches"; - const breachString1 = "leaked-passwords"; - const breachString2 = "security-recommendations"; - - const breachOrDashboard = (excludeThis: string) => { - const escapedExclude = escapeRegExp(excludeThis); - const pattern = [ - dashboardPage.urlRegex.source, - breachString0, - breachString1, - breachString2, - ] - .map((s) => `.*${s}.*`) - .join("|"); - - return new RegExp(`^(?!.*${escapedExclude})(${pattern})`); - }; - - const checkBreachLink = async () => { - const currentUrl = page.url(); - await automaticRemovePage.forwardArrowButton.click(); - await page.waitForURL(breachOrDashboard(currentUrl)); - const urlToCheck = page.url(); - const breachStringRE = new RegExp( - `.*(${[breachString0, breachString1, breachString2].join("|")}).*`, - ); - return breachStringRE.test(urlToCheck); - }; - - let iter = 0; - while (await checkBreachLink()) iter++; - const visitedBreachPages = iter !== 0; - const exposuresExist = exposuresCount !== 0; - expect(visitedBreachPages).toBe(exposuresExist); - - //price&plan toggle checks + const checkToggleButtonWorks = async (toggleButton: Locator) => { await automaticRemovePage.open(); - const subplatRegex = /\/products\/prod_/; - - const checkToggleButtonWorks = async (toggleButton: Locator) => { - await automaticRemovePage.open(); - await expect(toggleButton).toBeVisible(); - await toggleButton.click(); - const toggleText = await toggleButton.textContent(); - expect(toggleText).not.toBeNull(); - await automaticRemovePage.subplatButton.click(); - await page.waitForURL(subplatRegex); - return page.url(); - }; - - const subplat0 = await checkToggleButtonWorks( - automaticRemovePage.planToggle0, - ); - const subplat1 = await checkToggleButtonWorks( - automaticRemovePage.planToggle1, - ); - expect(subplat0).not.toBe(subplat1); - }); - }, -); + await expect(toggleButton).toBeVisible(); + await toggleButton.click(); + const toggleText = await toggleButton.textContent(); + expect(toggleText).not.toBeNull(); + await automaticRemovePage.subplatButton.click(); + await page.waitForURL(subplatRegex); + return page.url(); + }; + + const subplat0 = await checkToggleButtonWorks( + automaticRemovePage.planToggle0, + ); + const subplat1 = await checkToggleButtonWorks( + automaticRemovePage.planToggle1, + ); + expect(subplat0).not.toBe(subplat1); + }); +}); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Footer`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); + + test("Verify that the site footer is displayed correctly", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463570", }); - test("Verify that the site footer is displayed correctly", async ({ - dashboardPage, + expect(process.env["E2E_TEST_BASE_URL"]).toBeTruthy(); + const baseUrl = process.env["E2E_TEST_BASE_URL"]!; + await dashboardPage.goToDashboard(); + await expect(page.locator("footer a >> img")).toBeVisible(); + await clickOnATagCheckDomain( + dashboardPage.mozillaLogoFooter, + "www.mozilla.org", + /^(\/en-US\/)?$/, page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463570", - }); + ); + await clickOnATagCheckDomain( + dashboardPage.allBreachesFooter, + baseUrl, + "/breaches", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.faqsFooter, + "support.mozilla.org", + /.*\/kb.*\/mozilla-monitor-faq.*/, + page, + ); + await clickOnATagCheckDomain( + dashboardPage.termsOfServiceFooter, + "www.mozilla.org", + "/about/legal/terms/subscription-services/", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.privacyNoticeFooter, + "www.mozilla.org", + "/privacy/subscription-services/", + page, + ); + await clickOnATagCheckDomain( + dashboardPage.githubFooter, + "github.com", + "/mozilla/blurts-server", + page, + ); + }); +}); - expect(process.env["E2E_TEST_BASE_URL"]).toBeTruthy(); - const baseUrl = process.env["E2E_TEST_BASE_URL"]!; - await dashboardPage.goToDashboard(); - await expect(page.locator("footer a >> img")).toBeVisible(); - await clickOnATagCheckDomain( - dashboardPage.mozillaLogoFooter, - "www.mozilla.org", - /^(\/en-US\/)?$/, - page, - ); - await clickOnATagCheckDomain( - dashboardPage.allBreachesFooter, - baseUrl, - "/breaches", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.faqsFooter, - "support.mozilla.org", - /.*\/kb.*\/mozilla-monitor-faq.*/, - page, - ); - await clickOnATagCheckDomain( - dashboardPage.termsOfServiceFooter, - "www.mozilla.org", - "/about/legal/terms/subscription-services/", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.privacyNoticeFooter, - "www.mozilla.org", - "/privacy/subscription-services/", - page, - ); - await clickOnATagCheckDomain( - dashboardPage.githubFooter, - "github.com", - "/mozilla/blurts-server", - page, - ); - }); - }, -); +test.describe(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, () => { + test.beforeEach(async ({ dashboardPage, page }) => { + await dashboardPage.open(); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Breaches Dashboard - Navigation @smoke`, - () => { - test.beforeEach(async ({ dashboardPage, page }) => { - await dashboardPage.open(); + try { + await checkAuthState(page); + } catch { + console.log("[E2E_LOG] - No fxa auth required, proceeding..."); + } + }); - try { - await checkAuthState(page); - } catch { - console.log("[E2E_LOG] - No fxa auth required, proceeding..."); - } + test("Verify that the navigation bar options work correctly", async ({ + dashboardPage, + page, + }) => { + // link to testrail + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463568", }); - test("Verify that the navigation bar options work correctly", async ({ - dashboardPage, - page, - }) => { - // link to testrail - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463568", - }); - - const goToHrefOf = async (aTag: Locator) => { - const href = await aTag.getAttribute("href"); - expect(href).toBeTruthy(); - await page.goto(href!); - }; - - //testrail's step 1 - await dashboardPage.goToDashboard(); - await goToHrefOf(dashboardPage.settingsPageLink); - await expect(page).toHaveURL(/\/settings$/); - - //testrail's step 2 - await goToHrefOf(dashboardPage.dashboardPageLink); - await expect(page).toHaveURL(/.*\/dashboard.*/); - - // testrail's step 3 - await dashboardPage.goToSettings(); - await goToHrefOf(dashboardPage.fireFoxMonitorLogoAtag); - await expect(page).toHaveURL(/.*\/dashboard.*/); - - //testrail's step 4 - await dashboardPage.goToDashboard(); - await goToHrefOf(dashboardPage.faqsPageLink); - await expect(page).toHaveURL( - /.*support\.mozilla\.org.*\/kb\/.*firefox-monitor-faq.*/, - ); - }); - }, -); + const goToHrefOf = async (aTag: Locator) => { + const href = await aTag.getAttribute("href"); + expect(href).toBeTruthy(); + await page.goto(href!); + }; + + //testrail's step 1 + await dashboardPage.goToDashboard(); + await goToHrefOf(dashboardPage.settingsPageLink); + await expect(page).toHaveURL(/\/settings$/); + + //testrail's step 2 + await goToHrefOf(dashboardPage.dashboardPageLink); + await expect(page).toHaveURL(/.*\/dashboard.*/); + + // testrail's step 3 + await dashboardPage.goToSettings(); + await goToHrefOf(dashboardPage.fireFoxMonitorLogoAtag); + await expect(page).toHaveURL(/.*\/dashboard.*/); + + //testrail's step 4 + await dashboardPage.goToDashboard(); + await goToHrefOf(dashboardPage.faqsPageLink); + await expect(page).toHaveURL( + /.*support\.mozilla\.org.*\/kb\/.*firefox-monitor-faq.*/, + ); + }); +}); // These tests rely heavily on mocks test.skip(`${process.env.E2E_TEST_ENV} - Breaches Dashboard - Data Breaches`, () => { diff --git a/src/e2e/specs/landing.spec.ts b/src/e2e/specs/landing.spec.ts index 5cd5edc5518..ddfa51ddc40 100644 --- a/src/e2e/specs/landing.spec.ts +++ b/src/e2e/specs/landing.spec.ts @@ -14,7 +14,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await landingPage.open(); }); - test.skip("Observe page header", async ({ landingPage, page }) => { + test("Observe page header", async ({ landingPage, page }) => { // link to testrail case test.info().annotations.push({ type: "testrail", @@ -28,7 +28,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( expect(page.url()).toContain("oauth"); }); - test.skip('Observe "Find where your private info is exposed and take it back" section', async ({ + test('Observe "Find where your private info is exposed and take it back" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -48,7 +48,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.monitorLandingMidHeading).toBeVisible(); }); - test.skip('Observe "We will help you fix your exposures" section', async ({ + test('Observe "We will help you fix your exposures" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -66,7 +66,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.fixExposuresGraphic).toBeVisible(); }); - test.skip('Observe "What info could be at risk?" section', async ({ + test('Observe "What info could be at risk?" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -84,7 +84,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.couldBeAtRiskGraphic).toBeVisible(); }); - test.skip('Observe "Scan your email to get started" section', async ({ + test('Observe "Scan your email to get started" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -99,7 +99,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await expect(landingPage.getStartedScanFormSubmitButton).toBeVisible(); }); - test.skip('Observe "Choose your level of protection" section', async ({ + test('Observe "Choose your level of protection" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -114,7 +114,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( ); }); - test.skip("Observe FAQ section", async ({ landingPage }) => { + test("Observe FAQ section", async ({ landingPage }) => { test.info().annotations.push({ type: "testrail", description: @@ -127,7 +127,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( ); }); - test.skip('Observe "Take back control of your data" section', async ({ + test('Observe "Take back control of your data" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -145,7 +145,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( } }); - test.skip("Observe footer section", async ({ landingPage }) => { + test("Observe footer section", async ({ landingPage }) => { test.info().annotations.push({ type: "testrail", description: @@ -184,7 +184,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( await purchasePage.verifyYearlyPlanDetails(); }); - test.skip('Verify the "Get free scan" corresponding email fields', async ({ + test('Verify the "Get free scan" corresponding email fields', async ({ landingPage, authPage, }) => { @@ -219,7 +219,7 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( } }); - test.skip('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ + test('Verify manual/automatic removal "more info" tips from "Choose your level of protection" section', async ({ landingPage, }) => { test.info().annotations.push({ @@ -235,146 +235,140 @@ test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page content`, ( }); }); -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, - () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); +test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - without existing Account`, () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); + + test('Verify "Get free scan" buttons functionality without existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463502", }); - test('Verify "Get free scan" buttons functionality without existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463502", + const randomEmail = `${Date.now()}_tstact@restmail.net`; + if (await emailInputShouldExist(landingPage)) { + await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await page.waitForURL("**/oauth/**"); + } else { + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, }); - - const randomEmail = `${Date.now()}_tstact@restmail.net`; - if (await emailInputShouldExist(landingPage)) { - await landingPage.monitorHeroFormEmailInputField.fill(randomEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await page.waitForURL("**/oauth/**"); - } else { - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, - }); - await authPage.emailInputField.fill(randomEmail); - await authPage.continueButton.click(); - } - // continue with the common steps - await authPage.passwordInputField.fill( - process.env.E2E_TEST_ACCOUNT_PASSWORD as string, - ); - await authPage.passwordConfirmInputField.fill( - process.env.E2E_TEST_ACCOUNT_PASSWORD as string, - ); - await authPage.ageInputField.fill("31"); + await authPage.emailInputField.fill(randomEmail); await authPage.continueButton.click(); - const vc = await getVerificationCode(randomEmail, page); - await authPage.enterVerificationCode(vc); - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; - expect(page.url()).toBe(successUrl); - }); - - test('Verify the "Start free monitoring" button UI and functionality without existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push( - { - type: "testrail id #1", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", - }, - { - type: "testrail id #2", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }, - ); - - await landingPage.startFreeMonitoringButton.click(); - - const randomEmail = `${Date.now()}_tstact@restmail.net`; - await authPage.signUp(randomEmail, page); - - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; - expect(page.url()).toBe(successUrl); - }); - }, -); - -test.describe.skip( - `${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - with existing account`, - () => { - test.beforeEach(async ({ landingPage }) => { - await landingPage.open(); - }); + } + // continue with the common steps + await authPage.passwordInputField.fill( + process.env.E2E_TEST_ACCOUNT_PASSWORD as string, + ); + await authPage.passwordConfirmInputField.fill( + process.env.E2E_TEST_ACCOUNT_PASSWORD as string, + ); + await authPage.ageInputField.fill("31"); + await authPage.continueButton.click(); + const vc = await getVerificationCode(randomEmail, page); + await authPage.enterVerificationCode(vc); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + expect(page.url()).toBe(successUrl); + }); - test('Verify "Get free scan" buttons functionality with existing account', async ({ - landingPage, - page, - authPage, - }) => { - // link to testrail case - test.info().annotations.push({ - type: "testrail", + test('Verify the "Start free monitoring" button UI and functionality without existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push( + { + type: "testrail id #1", description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463503", - }); + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + }, + { + type: "testrail id #2", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }, + ); + + await landingPage.startFreeMonitoringButton.click(); + + const randomEmail = `${Date.now()}_tstact@restmail.net`; + await authPage.signUp(randomEmail, page); - const existingEmail = process.env.E2E_TEST_ACCOUNT_EMAIL as string; - - if (await emailInputShouldExist(landingPage)) { - // Scenario where the form is still used - await landingPage.monitorHeroFormEmailInputField.fill(existingEmail); - await landingPage.monitorHeroFormInputSubmitButton.click(); - await page.waitForURL("**/oauth/**"); - } else { - // Scenario where direct redirection happens - await landingPage.monitorHeroFormInputSubmitButton.click(); - await authPage.emailInputField.waitFor({ - state: "visible", - timeout: 10000, - }); - await authPage.emailInputField.fill(existingEmail); - await authPage.continueButton.click(); - } - - // complete sign in form - await authPage.enterPassword(); - - // verify dashboard redirect - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; - expect(page.url()).toBe(successUrl); + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/welcome`; + expect(page.url()).toBe(successUrl); + }); +}); + +test.describe(`${process.env.E2E_TEST_ENV} - Verify the Landing Page Functionality - with existing account`, () => { + test.beforeEach(async ({ landingPage }) => { + await landingPage.open(); + }); + + test('Verify "Get free scan" buttons functionality with existing account', async ({ + landingPage, + page, + authPage, + }) => { + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463503", }); - test('Verify the "Start free monitoring" button UI and functionality with existing account', async ({ - landingPage, - page, - authPage, - }) => { - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", + const existingEmail = process.env.E2E_TEST_ACCOUNT_EMAIL as string; + + if (await emailInputShouldExist(landingPage)) { + // Scenario where the form is still used + await landingPage.monitorHeroFormEmailInputField.fill(existingEmail); + await landingPage.monitorHeroFormInputSubmitButton.click(); + await page.waitForURL("**/oauth/**"); + } else { + // Scenario where direct redirection happens + await landingPage.monitorHeroFormInputSubmitButton.click(); + await authPage.emailInputField.waitFor({ + state: "visible", + timeout: 10000, }); + await authPage.emailInputField.fill(existingEmail); + await authPage.continueButton.click(); + } - await landingPage.startFreeMonitoringButton.click(); + // complete sign in form + await authPage.enterPassword(); - await authPage.enterEmail(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - await authPage.enterPassword(); + // verify dashboard redirect + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; + expect(page.url()).toBe(successUrl); + }); - // verify dashboard redirect - const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; - expect(page.url()).toBe(successUrl); + test('Verify the "Start free monitoring" button UI and functionality with existing account', async ({ + landingPage, + page, + authPage, + }) => { + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463524", }); - }, -); + + await landingPage.startFreeMonitoringButton.click(); + + await authPage.enterEmail(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + await authPage.enterPassword(); + + // verify dashboard redirect + const successUrl = `${process.env.E2E_TEST_BASE_URL}/user/dashboard`; + expect(page.url()).toBe(successUrl); + }); +}); diff --git a/src/e2e/specs/purchase.spec.ts b/src/e2e/specs/purchase.spec.ts index d95242622c8..90d23f61d1a 100644 --- a/src/e2e/specs/purchase.spec.ts +++ b/src/e2e/specs/purchase.spec.ts @@ -5,197 +5,201 @@ import { test, expect } from "../fixtures/basePage.js"; import { checkAuthState, setEnvVariables } from "../utils/helpers.js"; -test.describe(`${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, () => { - test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { - test.info().annotations.push({ - type: "testrail id", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", - }); +test.describe.skip( + `${process.env.E2E_TEST_ENV} - Breach Scan, Monitor Plus Purchase Flow`, + () => { + test.beforeEach(async ({ page, authPage, landingPage, welcomePage }) => { + test.info().annotations.push({ + type: "testrail id", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463564", + }); + + test.slow( + true, + "this test runs through the welcome scan flow, increasing timeout to address it", + ); - test.slow( - true, - "this test runs through the welcome scan flow, increasing timeout to address it", - ); + setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); - setEnvVariables(process.env.E2E_TEST_ACCOUNT_EMAIL as string); + // speed up test by ignoring non necessary requests + await page.route(/(analytics)/, async (route) => { + await route.abort(); + }); - // speed up test by ignoring non necessary requests - await page.route(/(analytics)/, async (route) => { - await route.abort(); - }); + // start authentication flow + await landingPage.open(); + await landingPage.goToSignIn(); + + // Fill out sign up form + const randomEmail = `_${Date.now()}@restmail.net`; + await authPage.signUp(randomEmail, page); + + // wait for welcome page + await page.waitForURL("**/user/welcome"); + await welcomePage.goThroughFirstScan({ skipLoader: true }); - // start authentication flow - await landingPage.open(); - await landingPage.goToSignIn(); - - // Fill out sign up form - const randomEmail = `_${Date.now()}@restmail.net`; - await authPage.signUp(randomEmail, page); - - // wait for welcome page - await page.waitForURL("**/user/welcome"); - await welcomePage.goThroughFirstScan(); - expect(page.url()).toContain("/user/dashboard"); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ - dashboardPage, - purchasePage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + expect(page.url()).toContain("/user/dashboard"); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + test("Verify that the user can purchase the plus subscription with a Stripe card - Yearly", async ({ + dashboardPage, + purchasePage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.waitFor(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor(); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ - purchasePage, - dashboardPage, - page, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to multiple testrail cases - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe yearly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + await dashboardPage.subscribeDialogSelectYearlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.waitFor(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor(); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + test("Verify that the user can purchase the plus subscription with a Stripe card - Monthly", async ({ + purchasePage, + dashboardPage, + page, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to multiple testrail cases + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463627", + }); + + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2301529", + }); + + try { + await checkAuthState(page); + } catch { + console.log( + "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + ); + } + + // navigate to subscription + await dashboardPage.open(); + await dashboardPage.subscribeButton.click(); + + // verify user purchase choices + await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); + await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); + await dashboardPage.yearlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectYearlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await expect( + dashboardPage.subscribeDialogSelectMonthlyPlanLink, + ).toBeVisible(); + + await dashboardPage.monthlyTab.click(); + await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); + await purchasePage.subscriptionHeader.waitFor(); + + // fill out subscription payment + await purchasePage.authorizationCheckbox.waitFor(); + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutStripeCardInfo(); + await purchasePage.payNowButton.click({ force: true }); + await page.getByText("Subscription confirmation").waitFor(); + // navigate to confirmation + await purchasePage.getStartedButton.click(); + await purchasePage.goToNextStep.click(); + + // confirm successful payment + await dashboardPage.plusSubscription.waitFor({ + state: "attached", + timeout: 5000, + }); + await expect(dashboardPage.plusSubscription).toBeVisible(); }); - try { - await checkAuthState(page); - } catch { - console.log( - "[E2E_LOG] - No fxa auth required, proceeding... with stripe monthly", + test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", ); - } - - // navigate to subscription - await dashboardPage.open(); - await dashboardPage.subscribeButton.click(); - - // verify user purchase choices - await expect(dashboardPage.subscribeDialogCloseButton).toBeVisible(); - await expect(dashboardPage.yearlyMonthlyTablist).toBeVisible(); - await dashboardPage.yearlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectYearlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await expect( - dashboardPage.subscribeDialogSelectMonthlyPlanLink, - ).toBeVisible(); - - await dashboardPage.monthlyTab.click(); - await dashboardPage.subscribeDialogSelectMonthlyPlanLink.click(); - await purchasePage.subscriptionHeader.waitFor(); - - // fill out subscription payment - await purchasePage.authorizationCheckbox.waitFor(); - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutStripeCardInfo(); - await purchasePage.payNowButton.click({ force: true }); - await page.getByText("Subscription confirmation").waitFor(); - // navigate to confirmation - await purchasePage.getStartedButton.click(); - await purchasePage.goToNextStep.click(); - - // confirm successful payment - await dashboardPage.plusSubscription.waitFor({ - state: "attached", - timeout: 5000, - }); - await expect(dashboardPage.plusSubscription).toBeVisible(); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - yearly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, true); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); - - test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ - purchasePage, - dashboardPage, - context, - }) => { - test.skip( - process.env.E2E_TEST_ENV === "production", - "payment method test not available in production", - ); - // link to testrail case - test.info().annotations.push({ - type: "testrail", - description: - "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + test("Verify that the user can purchase the plus subscription with a PayPal account - monthly", async ({ + purchasePage, + dashboardPage, + context, + }) => { + test.skip( + process.env.E2E_TEST_ENV === "production", + "payment method test not available in production", + ); + // link to testrail case + test.info().annotations.push({ + type: "testrail", + description: + "https://testrail.stage.mozaws.net/index.php?/cases/view/2463628", + }); + + await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); + // fill out subscription payment + await purchasePage.authorizationCheckbox.check(); + await purchasePage.fillOutPaypalInfo(context); + await purchasePage.postPaymentPageCheck(dashboardPage); }); - - await purchasePage.gotoPurchaseFromDashboard(dashboardPage, false); - // fill out subscription payment - await purchasePage.authorizationCheckbox.check(); - await purchasePage.fillOutPaypalInfo(context); - await purchasePage.postPaymentPageCheck(dashboardPage); - }); -}); + }, +);