diff --git a/.cursor/qa/rules/packages/template-retail-react-app/testing/retail-react-app-test-patterns.mdc b/.cursor/qa/rules/packages/template-retail-react-app/testing/retail-react-app-test-patterns.mdc new file mode 100644 index 0000000000..f0134fb7df --- /dev/null +++ b/.cursor/qa/rules/packages/template-retail-react-app/testing/retail-react-app-test-patterns.mdc @@ -0,0 +1,59 @@ +--- +description: QA Tests for Template Retail React App Test Generation Rules +globs: ["packages/template-retail-react-app/app/components/**/*-underTest.test.{js,jsx}"] +alwaysApply: false +--- +# QA Tests for Template Retail React App Test Patterns + +## Purpose +This file contains test cases to verify that the `unit-tests-template-retail-react-app.mdc` rule effectively guides the creation of consistent and robust React component tests. + +## Test Cases + +### Test 1: DrawerMenu Component Test Generation +**Workflow:** Generate → Analyze → Cleanup (NO test execution) + +**Steps:** +1. **Generate:** Create new test file `drawer-menu-underTest.test.js` (colocated with existing drawer-menu component at `packages/template-retail-react-app/app/components/drawer-menu/`) +2. **Apply Rules:** Use `@/testing` (located at `.cursor/rules/testing/unit-tests-generic.mdc` and `.cursor/rules/testing/unit-tests-template-retail-react-app.mdc`) +3. **Prompt:** "Write unit test for drawer-menu component" +4. **Analyze:** Perform static code analysis against verification patterns (see below) +5. **Cleanup:** Delete the generated test file after validation + +**Important:** DO NOT run the test after creation - skip test execution entirely + +**Verify that the newly generated test file follows these patterns:** +1. Test Setup + - Uses `renderWithProviders` from `@salesforce/retail-react-app/app/utils/test-utils` + - Gets user events from return value: `const {user} = renderWithProviders(...)` + - Includes `beforeEach(() => jest.clearAllMocks())` + +2. Import Structure + - Does NOT import `userEvent` directly + - Uses existing mock data from `@salesforce/retail-react-app/app/mocks/` + - Imports `screen` from `@testing-library/react` + +3. Test Organization + - Uses `describe` block with component name + - Individual `test` or `it` blocks for different scenarios + - Async/await patterns for user interactions + +4. API Mocking + - Uses `prependHandlersToServer` or `msw` for API mocking when needed + +**Failure Indicators:** +- Direct import of `userEvent` from `@testing-library/user-event` +- Using custom render function instead of `renderWithProviders` +- Creating new mock data instead of using existing mocks +- Missing Commerce SDK context providers +- Not using async/await for user interactions + +**Expected Output:** +Provide a clear, structured report based on **static code analysis only** (no test execution): +- ✅ **PASS** or ❌ **FAIL** for each verification point +- Specific line numbers and code snippets for any failures +- Summary: `X/Y patterns followed correctly` +- Overall result: **RULES EFFECTIVE** or **RULES NEED IMPROVEMENT** + +**Cleanup:** +- Delete the generated test file `drawer-menu-underTest.test.js` after QA validation is complete diff --git a/.cursor/rules/cursor-rule.mdc b/.cursor/rules/cursor-rule.mdc new file mode 100644 index 0000000000..774d83ff2c --- /dev/null +++ b/.cursor/rules/cursor-rule.mdc @@ -0,0 +1,66 @@ +--- +description: How to add or edit Cursor rules in our project +globs: +alwaysApply: false +--- +# Cursor Rules Location + +How to add new cursor rules to the project + +1. Always place rule files in PROJECT_ROOT/.cursor/rules/: + ``` + .cursor/rules/ + ├── your-rule-name.mdc + ├── another-rule.mdc + └── ... + ``` + +2. Follow the naming convention: + - Use kebab-case for filenames + - Always use .mdc extension + - Make names descriptive of the rule's purpose + +3. Directory structure: + ``` + PROJECT_ROOT/ + ├── .cursor/ + │ └── rules/ + │ ├── your-rule-name.mdc + │ └── ... + └── ... + ``` + +4. Never place rule files: + - In the project root + - In subdirectories outside .cursor/rules + - In any other location + +5. Cursor rules have the following structure: + +```` +--- +description: Short description of the rule's purpose +globs: optional/path/pattern/**/* +alwaysApply: false +--- +# Rule Title + +Main content explaining the rule with markdown formatting. + +1. Step-by-step instructions +2. Code examples +3. Guidelines + +Example: +```typescript +// Good example +function goodExample() { + // Implementation following guidelines +} + +// Bad example +function badExample() { + // Implementation not following guidelines +} +``` +```` \ No newline at end of file diff --git a/.cursor/rules/testing/unit-tests-generic.mdc b/.cursor/rules/testing/unit-tests-generic.mdc index 83a395aad9..63970b79d5 100644 --- a/.cursor/rules/testing/unit-tests-generic.mdc +++ b/.cursor/rules/testing/unit-tests-generic.mdc @@ -7,22 +7,6 @@ USE WHEN writing unit tests for components in template packages # 🧪 Generic Component Test Rules -# CRITICAL: AI Attribution Requirements -* **IMPORTANT** All individual test methods generated or modified by Cursor MUST include an AI attribution comment directly above the test stating the following: -"DO NOT REMOVE THIS COMMENT! This test was generated by Cursor". The comment should go on the test method and not the test class. Failure to add an AI Attribution Comment will be considered a failure of test generation. -* The AI attribution comment MUST include a comment declaring the LLM model that was used in writing the test on its own line. - -*Sample AI Attribution Comment* -``` -/* - * DO NOT REMOVE THIS COMMENT! This test was generated by Cursor - * This test was generated with the following model: Claude 3.5 Sonnet - */ -test('renders component correctly', () => { - // test implementation -}) -``` - ## Structure & Best Practices - Use `describe` blocks to group tests, `test` for individual cases - Use `beforeEach` for setup, clear mocks after each test diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4c0f56afbf..7140e05a3a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,9 +1,64 @@ # https://help.github.com/en/enterprise/2.17/user/articles/about-code-owners -# These owners will be the default owners for everything in -# the repo. Unless a later match takes precedence, -# @global-owner1 and @global-owner2 will be requested for -# review when someone opens a pull request. +# Global directories +.cursor/ @SalesforceCommerceCloud/mobifyers +.github/ @SalesforceCommerceCloud/mobifyers +e2e/ @SalesforceCommerceCloud/mobifyers +scripts/ @SalesforceCommerceCloud/mobifyers + +# Package-specific ownership +packages/commerce-sdk-react/ @SalesforceCommerceCloud/mobifyers +packages/internal-lib-build/ @SalesforceCommerceCloud/mobifyers +packages/pwa-kit-create-app/ @SalesforceCommerceCloud/mobifyers +packages/pwa-kit-dev/ @SalesforceCommerceCloud/mobifyers +packages/pwa-kit-mcp/ @SalesforceCommerceCloud/mobifyers +packages/pwa-kit-react-sdk/ @SalesforceCommerceCloud/mobifyers +packages/pwa-kit-runtime/ @SalesforceCommerceCloud/mobifyers +packages/template-express-minimal/ @SalesforceCommerceCloud/mobifyers +packages/template-mrt-reference-app/ @SalesforceCommerceCloud/mobifyers +packages/template-retail-react-app/ @SalesforceCommerceCloud/mobifyers +packages/template-typescript-minimal/ @SalesforceCommerceCloud/mobifyers +packages/test-commerce-sdk-react/ @SalesforceCommerceCloud/mobifyers + +# Root configuration and documentation files +/README.md @SalesforceCommerceCloud/mobifyers +/CODE_OF_CONDUCT.md @SalesforceCommerceCloud/mobifyers +/CONTRIBUTING.md @SalesforceCommerceCloud/mobifyers +/SECURITY.md @SalesforceCommerceCloud/mobifyers +/STATEMENTS.md @SalesforceCommerceCloud/mobifyers +/TERMS_OF_USE.md @SalesforceCommerceCloud/mobifyers +/LICENSE @SalesforceCommerceCloud/mobifyers +/.eslintrc.js @SalesforceCommerceCloud/mobifyers +/.gitattributes @SalesforceCommerceCloud/mobifyers +/.gitignore @SalesforceCommerceCloud/mobifyers +/.prettierignore @SalesforceCommerceCloud/mobifyers +/.prettierrc.yaml @SalesforceCommerceCloud/mobifyers +/lerna.json @SalesforceCommerceCloud/mobifyers +/package.json @SalesforceCommerceCloud/mobifyers +/package-lock.json @SalesforceCommerceCloud/mobifyers +/playwright.config.js @SalesforceCommerceCloud/mobifyers +/.git2gus/ @SalesforceCommerceCloud/mobifyers + +# Specific feature file ownership (overrides package-level rules above) + +# BOPIS (Buy Online Pick up In Store) feature files - PR #2646 +packages/template-retail-react-app/app/components/store-display/ @SalesforceCommerceCloud/cc-spark +packages/template-retail-react-app/app/hooks/use-selected-store.js @SalesforceCommerceCloud/cc-spark +packages/template-retail-react-app/app/hooks/use-pickup-shipment.js @SalesforceCommerceCloud/cc-spark +packages/template-retail-react-app/app/hooks/use-pickup-shipment.test.js @SalesforceCommerceCloud/cc-spark +e2e/tests/desktop/bopis.spec.js @SalesforceCommerceCloud/cc-spark + +# Bonus Products feature files - PR #2704 +packages/template-retail-react-app/app/components/product-item/bonus-product-quantity.jsx @SalesforceCommerceCloud/cc-sharks +packages/template-retail-react-app/app/components/product-item/bonus-product-quantity.test.jsx @SalesforceCommerceCloud/cc-sharks +packages/template-retail-react-app/app/components/product-item/product-quantity-picker.jsx @SalesforceCommerceCloud/cc-sharks +packages/template-retail-react-app/app/components/product-item/product-quantity-picker.test.jsx @SalesforceCommerceCloud/cc-sharks +packages/template-retail-react-app/app/pages/cart/partials/bonus-products-title.jsx @SalesforceCommerceCloud/cc-sharks +packages/template-retail-react-app/app/pages/cart/partials/bonus-products-title.test.js @SalesforceCommerceCloud/cc-sharks + +# Standard Products feature files - PR #2697 +packages/template-retail-react-app/app/mocks/standard-product.js @SalesforceCommerceCloud/cc-sharks +packages/template-retail-react-app/app/utils/add-to-cart-utils.js @SalesforceCommerceCloud/cc-sharks + -* @SalesforceCommerceCloud/mobifyers #ECCN:Open Source \ No newline at end of file diff --git a/.github/workflows/e2e-pr.yml b/.github/workflows/e2e-pr.yml new file mode 100644 index 0000000000..710b73e62c --- /dev/null +++ b/.github/workflows/e2e-pr.yml @@ -0,0 +1,112 @@ +name: SalesforceCommerceCloud/pwa-kit/e2e-pr +on: + workflow_dispatch: + pull_request: # Default: opened, reopened, synchronize (head branch updated) + merge_group: # Trigger GA workflow when a pull request is added to a merge queue. + push: + branches: + - develop + - 'release-*' + +jobs: + test_e2e_private: + runs-on: ubuntu-latest + steps: + # Skipping the entire workflow for now until all steps are implemented. + - name: Skip Check + run: | + echo "SKIP_WORKFLOW=true" >> "$GITHUB_ENV" + + - name: Checkout + uses: actions/checkout@v4 + + - name: Check PWA Kit Version + run: |- + version=`jq -r ".version" package.json` + echo "pwa_kit_version=$version" >> "$GITHUB_ENV" + + # TODO: Skip the entire workflow since we don't have e2e tests for PWA Kit v2.x + - name: Skip if PWA Kit version older than v3.x + if: ${{ env.SKIP_WORKFLOW != 'true' }} + run: | + major_version=$(echo "${{ env.pwa_kit_version }}" | cut -d. -f1) + if [ "$major_version" -lt 3 ]; then + echo "PWA Kit version is older than v3.x, skipping workflow." + echo "SKIP_WORKFLOW=true" >> "$GITHUB_ENV" + fi + + # Only test for latest Node version supported by MRT + - name: Setup Node + if: ${{ env.SKIP_WORKFLOW != 'true' }} + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + # Check central resource allocation on AWS and get a lock on an available environment from the pool. + # Returns the MRT target ID if lock is acquired, otherwise returns an error state. + - name: Get MRT Target lock + if: ${{ env.SKIP_WORKFLOW != 'true' }} + id: get_mrt_target_lock + run: | + echo "TODO: Implement .github/actions/get_mrt_target_lock" + + - name: Create MRT target + id: create_mrt_target + if: ${{ env.SKIP_WORKFLOW != 'true' && steps.get_mrt_target_lock.outputs.status == 'ERR_NO_AVAILABLE_TARGETS' }} + run: | + echo "TODO: Call .github/actions/create_mrt_target with correct inputs" + + - name: Get Template Version + if: ${{ env.SKIP_WORKFLOW != 'true' }} + run: |- + version=`jq -r ".version" packages/template-retail-react-app/package.json` + echo "retail_app_template_version=$version" >> "$GITHUB_ENV" + + - name: Generate Retail App Private Client + if: ${{ env.SKIP_WORKFLOW != 'true' }} + uses: ./.github/actions/e2e_generate_app + with: + PROJECT_KEY: 'retail-app-private-client' + TEMPLATE_VERSION: ${{ env.retail_app_template_version }} + + - name: Validate Retail App Without Extensibility + if: ${{ env.SKIP_WORKFLOW != 'true' }} + uses: ./.github/actions/e2e_validate_generated_app + with: + PROJECT_KEY: 'retail-app-no-ext' + TEMPLATE_VERSION: ${{ env.retail_app_template_version }} + + # TODO: Revisit the next 2 steps to see if we can use the existing .github/actions/deploy_app action. + - name: Create MRT credentials file + if: ${{ env.SKIP_WORKFLOW != 'true' }} + uses: './.github/actions/create_mrt' + with: + mobify_user: ${{ secrets.MOBIFY_CLIENT_USER }} + mobify_api_key: ${{ secrets.MOBIFY_CLIENT_API_KEY }} + + - name: Push Bundle to MRT (E2E Test PWA Kit) + if: ${{ env.SKIP_WORKFLOW != 'true' }} + uses: './.github/actions/push_to_mrt' + with: + CWD: '../generated-projects/retail-app-no-ext' + # TODO: Use the MRT target ID from the target lock step above. + TARGET: e2e-tests-pwa-kit + FLAGS: --wait + + - name: Install Playwright Browsers + if: ${{ env.SKIP_WORKFLOW != 'true' }} + run: npx playwright install --with-deps + + - name: Run Playwright tests + if: ${{ env.SKIP_WORKFLOW != 'true' }} + run: npm run test:e2e + + - name: Run Playwright a11y tests + if: ${{ env.SKIP_WORKFLOW != 'true' }} + run: npm run test:e2e:a11y + + - name: Release MRT Target Lock + if: always() # Always release the target lock back to the pool even if the tests fail. + run: | + echo "TODO: Implement .github/actions/release_mrt_target_lock" \ No newline at end of file diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 4e2c98fe90..e5e88f7967 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -411,3 +411,25 @@ jobs: } env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + + test-extra-features: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - name: Install Monorepo Dependencies + run: node ./scripts/gtime.js monorepo_install npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Set PWA Kit E2E Test User + run: export PWA_E2E_USER_EMAIL=e2e.pwa.kit@gmail.com PWA_E2E_USER_PASSWORD=hpv_pek-JZK_xkz0wzf + - name: Run extra features tests + env: + PWA_E2E_USER_EMAIL: e2e.pwa.kit@gmail.com + PWA_E2E_USER_PASSWORD: hpv_pek-JZK_xkz0wzf + run: npm run test:e2e:extra_features diff --git a/.github/workflows/sync_extra_features_e2e.yml b/.github/workflows/sync_extra_features_e2e.yml new file mode 100644 index 0000000000..5bfff89a23 --- /dev/null +++ b/.github/workflows/sync_extra_features_e2e.yml @@ -0,0 +1,170 @@ +name: Sync Extra Features E2E Branch with Develop + +on: + # Trigger when develop branch is updated + push: + branches: + - develop + # Run daily at 11 PM PST (7 AM UTC) to catch any missed syncs + schedule: + - cron: '0 7 * * *' + workflow_dispatch: + +permissions: + contents: write + issues: write + pull-requests: read + +jobs: + sync-branch: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure git + run: | + git config --global user.name ${{ secrets.GIT_CONFIG_USERNAME }} + git config --global user.email ${{ secrets.GIT_CONFIG_EMAIL }} + + - name: Sync extra-features-e2e-branch with develop + id: sync + continue-on-error: true + run: | + set -e + + # Fetch all branches + git fetch origin + + # Check if the target branch exists + if ! git show-ref --verify --quiet refs/remotes/origin/extra-features-e2e-branch; then + echo "Branch extra-features-e2e-branch does not exist. Creating it from develop..." + git checkout -b extra-features-e2e-branch origin/develop + git push origin extra-features-e2e-branch + echo "✅ Created extra-features-e2e-branch branch from develop" + echo "status=created" >> $GITHUB_OUTPUT + exit 0 + fi + + # Switch to the target branch + git checkout extra-features-e2e-branch + git reset --hard origin/extra-features-e2e-branch + + # Check if we're already up to date + if git merge-base --is-ancestor origin/develop HEAD; then + echo "✅ extra-features-e2e-branch is already up to date with develop" + echo "status=up-to-date" >> $GITHUB_OUTPUT + exit 0 + fi + + if git merge origin/develop --no-edit; then + echo "✅ Successfully merged develop into extra-features-e2e-branch" + git push origin extra-features-e2e-branch + echo "status=merged" >> $GITHUB_OUTPUT + else + echo "❌ Merge conflicts detected!" + echo "📋 Files with conflicts:" + git diff --name-only --diff-filter=U || true + git merge --abort + echo "status=conflict" >> $GITHUB_OUTPUT + exit 1 + fi + + - name: Create conflict resolution issue + if: steps.sync.outputs.status == 'conflict' + uses: actions/github-script@v7 + with: + script: | + const conflictFiles = `${{ steps.sync.outputs.conflict_files || 'Unknown files' }}`; + const issueBody = ` + ## 🚨 Automatic Sync Failed - Merge Conflicts Detected + + Some features in PWA kit are defaulted to be off in \`develop\` branch (e.g. if they only work with private client). + Hence there is another site that has these features enabled that E2E tests of these extra features are run against. + The \`extra-features-e2e-branch\` is used for this site. + + A job is run nightly to sync \`develop\` to \`extra-features-e2e-branch\` branch, but today this automatic sync from \`develop\` to \`extra-features-e2e-branch\` failed due to merge conflicts. + + ### Conflicting Files: + \`\`\` + ${conflictFiles} + \`\`\` + + + ### Manual Resolution: + \`\`\`bash + git checkout extra-features-e2e-branch + git pull origin extra-features-e2e-branch + git merge develop + # Resolve conflicts manually + git add . + git commit -m "Resolve merge conflicts from develop" + git push origin extra-features-e2e-branch + \`\`\` + + ### After resolving the conflicts, close this issue + `; + + // Check if issue already exists + const existingIssues = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'sync-conflict' + }); + + if (existingIssues.data.length === 0) { + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '🚨 Extra Features E2E Branch Sync Conflict - Manual Resolution Required', + body: issueBody, + labels: ['sync-conflict', 'automation'] + }); + } + + deploy: + needs: sync-branch + if: needs.sync-branch.outputs.status != 'conflict' && needs.sync-branch.outputs.status != 'up-to-date' + runs-on: ubuntu-latest + environment: extra-features-e2e + + steps: + - name: Checkout extra-features-e2e-branch branch + uses: actions/checkout@v4 + with: + ref: extra-features-e2e-branch + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + + - name: Install Monorepo Dependencies + run: | + # Install node dependencies + node ./scripts/gtime.js monorepo_install npm ci + + - name: Build project + run: | + cd packages/template-retail-react-app + npm run build + + - name: Create MRT credentials file + uses: "./.github/actions/create_mrt" + with: + mobify_user: ${{ secrets.MOBIFY_CLIENT_USER }} + mobify_api_key: ${{ secrets.MOBIFY_CLIENT_API_KEY }} + + - name: Deploy to MRT + uses: "./.github/actions/push_to_mrt" + with: + CWD: "./packages/template-retail-react-app" + TARGET: extra-features-e2e + PROJECT: scaffold-pwa + MESSAGE: "Auto-sync from develop - build ${{ github.run_id }} (${{ github.sha }})" + FLAGS: --wait \ No newline at end of file diff --git a/.github/workflows/validate-codeowners.yml b/.github/workflows/validate-codeowners.yml new file mode 100644 index 0000000000..cfa1a452e0 --- /dev/null +++ b/.github/workflows/validate-codeowners.yml @@ -0,0 +1,32 @@ +name: Validate CODEOWNERS + +# Only run when CODEOWNERS file changes - efficient! +on: + pull_request: + paths: + - '.github/CODEOWNERS' + push: + branches: + - develop + - 'release-*' + paths: + - '.github/CODEOWNERS' + +jobs: + validate: + name: Validate CODEOWNERS File + runs-on: ubuntu-latest + # Only run on pushes or PRs from the same repository (not forks) + # This prevents permission issues with GITHUB_TOKEN on external PRs + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Validate CODEOWNERS structure + uses: mszostok/codeowners-validator@v0.7.4 + with: + # files: paths exist, duppatterns: no duplicates, syntax: valid format + checks: "files,duppatterns,syntax" + github_access_token: "${{ secrets.GITHUB_TOKEN }}" \ No newline at end of file diff --git a/e2e/config.js b/e2e/config.js index d610da3487..f51f1cc158 100644 --- a/e2e/config.js +++ b/e2e/config.js @@ -9,6 +9,7 @@ module.exports = { RETAIL_APP_HOME: process.env.RETAIL_APP_HOME || "https://scaffold-pwa-e2e-tests-pwa-kit.mobify-storefront.com", + RETAIL_APP_HOME_SITE: "RefArch", GENERATED_PROJECTS_DIR: "../generated-projects", GENERATE_PROJECTS: ["retail-app-demo", "retail-app-ext", "retail-app-no-ext"], GENERATOR_CMD: @@ -111,6 +112,7 @@ module.exports = { }, EXPECTED_GENERATED_ARTIFACTS: { "retail-app-demo": [ + ".cursor", ".eslintignore", ".eslintrc.js", ".prettierrc.yaml", @@ -124,6 +126,7 @@ module.exports = { "worker", ], "retail-app-ext": [ + ".cursor", ".eslintignore", ".eslintrc.js", ".prettierrc.yaml", @@ -162,5 +165,6 @@ module.exports = { }, PWA_E2E_USER_EMAIL: process.env.PWA_E2E_USER_EMAIL, PWA_E2E_USER_PASSWORD: process.env.PWA_E2E_USER_PASSWORD, - SOCIAL_LOGIN_RETAIL_APP_HOME: "https://wasatch-mrt-feature-public.mrt-storefront-staging.com" + EXTRA_FEATURES_E2E_RETAIL_APP_HOME: "https://scaffold-pwa-extra-features-e2e.mobify-storefront.com", + EXTRA_FEATURES_E2E_RETAIL_APP_HOME_SITE: "RefArchGlobal" }; diff --git a/e2e/scripts/pageHelpers.js b/e2e/scripts/pageHelpers.js index 4152b20ea8..5c55d3b95c 100644 --- a/e2e/scripts/pageHelpers.js +++ b/e2e/scripts/pageHelpers.js @@ -19,25 +19,35 @@ const {getCreditCardExpiry, runAccessibilityTest} = require('../scripts/utils.js */ export const answerConsentTrackingForm = async (page, dnt = false) => { try { - const consentFormVisible = await page.locator('text=Tracking Consent').isVisible().catch(() => false) + const consentFormVisible = await page + .locator('text=Tracking Consent') + .isVisible() + .catch(() => false) if (!consentFormVisible) { return } const buttonText = dnt ? 'Decline' : 'Accept' - await page.getByRole('button', { name: new RegExp(buttonText, 'i') }).first().waitFor({ timeout: 3000 }) - + await page + .getByRole('button', {name: new RegExp(buttonText, 'i')}) + .first() + .waitFor({timeout: 3000}) + // Find and click consent buttons (handles both mobile and desktop versions existing in the DOM) const clickSuccess = await page.evaluate((targetText) => { // Try aria-label first, then fallback to text content - let buttons = Array.from(document.querySelectorAll(`button[aria-label="${targetText} tracking"]`)) - + let buttons = Array.from( + document.querySelectorAll(`button[aria-label="${targetText} tracking"]`) + ) + if (buttons.length === 0) { - buttons = Array.from(document.querySelectorAll('button')).filter(btn => - btn.textContent && btn.textContent.trim().toLowerCase() === targetText.toLowerCase() + buttons = Array.from(document.querySelectorAll('button')).filter( + (btn) => + btn.textContent && + btn.textContent.trim().toLowerCase() === targetText.toLowerCase() ) } - + let clickedCount = 0 buttons.forEach((button) => { // Only click visible buttons @@ -46,14 +56,17 @@ export const answerConsentTrackingForm = async (page, dnt = false) => { clickedCount++ } }) - + return clickedCount }, buttonText) // after clicking an answering button, the tracking consent should not stay in the DOM if (clickSuccess > 0) { await page.waitForTimeout(2000) - await page.locator('text=Tracking Consent').isHidden({ timeout: 5000 }).catch(() => {}) + await page + .locator('text=Tracking Consent') + .isHidden({timeout: 5000}) + .catch(() => {}) } } catch (error) { // Silently continue - consent form handling should not break tests @@ -164,7 +177,7 @@ export const navigateToPDPDesktopSocial = async ({ productColor, productPrice }) => { - await page.goto(config.SOCIAL_LOGIN_RETAIL_APP_HOME) + await page.goto(config.EXTRA_FEATURES_E2E_RETAIL_APP_HOME) await answerConsentTrackingForm(page) await page.getByRole('link', {name: 'Womens'}).hover() @@ -249,7 +262,7 @@ export const registerShopper = async ({page, userCredentials, isMobile = false}) const registrationFormHeading = page.getByText(/Let's get started!/i) try { - await registrationFormHeading.waitFor({ timeout: 10000 }) + await registrationFormHeading.waitFor({timeout: 10000}) } catch (error) { // Check if user was redirected to account page during wait const urlAfterWait = page.url() @@ -273,7 +286,7 @@ export const registerShopper = async ({page, userCredentials, isMobile = false}) const tokenResponse = await tokenResponsePromise expect(tokenResponse.status()).toBe(200) - await page.waitForURL(/.*\/account.*/, { timeout: 10000 }) + await page.waitForURL(/.*\/account.*/, {timeout: 10000}) await expect(page.getByText(userCredentials.email)).toBeVisible() } @@ -349,14 +362,14 @@ export const loginShopper = async ({page, userCredentials}) => { '**/shopper/auth/v1/organizations/**/oauth2/token' ) await page.getByRole('button', {name: /Sign In/i}).click() - + const loginResponse = await loginResponsePromise expect(loginResponse.status()).toBe(303) // Login returns a 303 redirect to /callback with authCode and usid - + const tokenResponse = await tokenResponsePromise expect(tokenResponse.status()).toBe(200) - await page.waitForURL(/.*\/account.*/, { timeout: 10000 }) + await page.waitForURL(/.*\/account.*/, {timeout: 10000}) await expect(page.getByText(userCredentials.email)).toBeVisible() return true @@ -373,7 +386,7 @@ export const loginShopper = async ({page, userCredentials}) => { */ export const socialLoginShopper = async ({page}) => { try { - await page.goto(config.SOCIAL_LOGIN_RETAIL_APP_HOME + '/login') + await page.goto(config.EXTRA_FEATURES_E2E_RETAIL_APP_HOME + '/login') await page.getByText(/Google/i).click() await expect(page.getByText(/Sign in with Google/i)).toBeVisible({timeout: 10000}) @@ -531,7 +544,7 @@ export const registeredUserHappyPath = async ({page, registeredUserCredentials, } await answerConsentTrackingForm(page) await page.waitForLoadState() - + // Verify we're on account page and user is logged in const currentUrl = page.url() expect(currentUrl).toMatch(/\/account/) @@ -643,7 +656,7 @@ export const registeredUserHappyPath = async ({page, registeredUserCredentials, /** * Executes the wishlist flow for a registered user. - * + * * Includes robust authentication handling with fallback mechanisms. * * @param {Object} options.page - Playwright page object representing a browser tab/window @@ -696,3 +709,86 @@ export const wishlistFlow = async ({page, registeredUserCredentials, a11y = {}}) // wishlist await validateWishlist({page, a11y}) } + +/** + * Navigates to a PLP and opens the store inventory filter to select a store. + * + * This helper function demonstrates the store inventory filtering functionality by: + * 1. Navigating to the Womens > Tops category PLP + * 2. Opening the store locator modal + * 3. Searching for stores by postal code + * 4. Returning the available store selection options + * + * This is useful for testing store inventory features and BOPIS (Buy Online, Pick Up In Store) functionality. + * + * @param {Object} options.page - Playwright page object representing a browser tab/window + */ +export const selectStoreFromPLP = async ({page}) => { + // Navigate to a product category (Womens > Tops) + await page.getByRole('link', {name: 'Womens'}).hover() + const topsNav = await page.getByRole('link', {name: 'Tops', exact: true}) + await expect(topsNav).toBeVisible() + await topsNav.click() + + // Verify we're on the PLP + await expect(page.getByRole('heading', {name: 'Tops'})).toBeVisible() + const productTile = page.getByRole('link', { + name: /Cotton Turtleneck Sweater/i + }) + const productTileImg = productTile.locator('img') + await productTileImg.waitFor({state: 'visible'}) + + // Look for the store inventory filter component + const storeInventoryFilter = page.getByTestId('sf-store-inventory-filter') + await expect(storeInventoryFilter).toBeVisible() + + // Verify the filter shows "Select Store" initially + await expect(page.getByText('Select Store')).toBeVisible() + await expect(page.getByText('Shop by Availability')).toBeVisible() + + // Click on the store inventory filter checkbox to open store locator + const inventoryCheckbox = page.getByTestId('sf-store-inventory-filter-checkbox') + await inventoryCheckbox.click() + + // Verify store locator modal opens and select a store + await expect(page.getByText('Find a Store')).toBeVisible() + await page.locator('select[name="countryCode"]').selectOption({label: 'United States'}) + await page.locator('input[name="postalCode"]').fill('01803') + const searchStoreButton = page.getByRole('button', {name: 'Find'}) + await expect(searchStoreButton).toBeVisible() + + const storeSearchResponsePromise = page.waitForResponse( + (resp) => + resp.url().includes('/shopper-stores/v1/organizations/') && + resp.url().includes('/store-search') + ) + await searchStoreButton.click() + const storeSearchResponse = await storeSearchResponsePromise + + expect(storeSearchResponse.status()).toBe(200) + + // Select the first available store (if any stores are available) + await expect(page.getByText(/Burlington Retail Store/i)).toBeVisible() + + // Find and click the first available store label + const storeRadioLabels = page.locator( + 'label.chakra-radio:has(input[aria-describedby^="store-info-"])' + ) + const storeCount = await storeRadioLabels.count() + + if (storeCount > 0) { + // Select the first store + await storeRadioLabels.first().click() + + // Close the store locator modal + await page.locator('button[aria-label="Close"]').click() + await page.waitForLoadState() + await expect(page.getByText('Find a Store')).not.toBeVisible() + } else { + // If no stores are available, verify the appropriate message is shown + await expect(page.getByText('Sorry, there are no locations in this area.')).toBeVisible() + + // Close the modal + await page.getByRole('button', {name: 'Close'}).click() + } +} diff --git a/e2e/scripts/utils.js b/e2e/scripts/utils.js index e7168cbb20..58bf36a0f9 100644 --- a/e2e/scripts/utils.js +++ b/e2e/scripts/utils.js @@ -42,10 +42,11 @@ const getCreditCardExpiry = (yearsFromNow = 5) => { */ function simplifyViolations(violations) { return violations.map((violation) => ({ - id: violation.id, // Rule ID - impact: violation.impact, // Impact (critical, serious, moderate, minor) - description: violation.description, // Description of the rule - help: violation.help, // Short description + id: violation.id, + // Severity of violation (critical, serious, moderate, minor) + impact: violation.impact, + description: violation.description, + help: violation.help, helpUrl: violation.helpUrl, nodes: violation.nodes.map((node) => ({ // Simplify the HTML to make it more stable for snapshots @@ -54,7 +55,13 @@ function simplifyViolations(violations) { failureSummary: node.failureSummary, // Simplify target selectors for stability // #app-header[data-v-12345] > .navigation[data-testid="main-nav"] => #app-header > .navigation - target: node.target.map((t) => t.split(/\[.*?\]/).join('')) + // Also handle Chakra UI dynamic selectors like #popover-trigger-:r5l4v: + target: node.target.map((t) => + t + .split(/\[.*?\]/).join('') // Remove data attributes + .replace(/#([^-\s]+(?:-[^:]*)?):([^"\s]*)/g, '#$1-...') // Remove Chakra UI dynamic IDs + .replace(/\.css-[a-zA-Z0-9]+/g, '.css-...') // Simplify Chakra UI CSS classes + ) })) })) } @@ -77,6 +84,10 @@ function sanitizeHtml(html) { .replace(/style="[^"]*"/g, '') // Remove content of script tags .replace(/]*>([\s\S]*?)<\/script>/gi, '') + // Dynamic values - keep stable part: + // Before: aria-controls="popover-content-:rn:" + // After: aria-controls="popover-content-..." + .replace(/(aria-(?:controls|describedby|labelledby|owns))="([^:]*?)(?::[^"]*)?"/g, '$1="$2..."') // Trim whitespace .trim() ) diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/cart-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/guest/cart-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/cart-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/cart-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "
", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-0.json b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-0.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-0.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-0.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-1.json b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-1.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-1.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-1.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-2.json b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-2.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-2.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-2.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-3.json b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-3.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-3.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-3.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-4-order-confirmation.json b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-4-order-confirmation.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-4-order-confirmation.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/checkout-a11y-violations-step-4-order-confirmation.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/homepage-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/guest/homepage-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/homepage-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/homepage-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/pdp-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/guest/pdp-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/pdp-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/pdp-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/guest/plp-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/guest/plp-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/guest/plp-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/guest/plp-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/account-addresses-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/registered/account-addresses-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/account-addresses-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/account-addresses-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/account-details-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/registered/account-details-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/account-details-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/account-details-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-0.json b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-0.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-0.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-0.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-1.json b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-1.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-1.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-1.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-2.json b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-2.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-2.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-2.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-3.json b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-3.json index b8fefc3110..bd26ad728f 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-3.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-3.json @@ -26,7 +26,7 @@ "html": "", "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", "target": [ - ".css-1k2aozt" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-4-order-confirmation.json b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-4-order-confirmation.json index 14695c4a46..30e91e5e17 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-4-order-confirmation.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/checkout-a11y-violations-step-4-order-confirmation.json @@ -7,10 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:r3c\\:" + "#popover-trigger-\\-..." ] } ] @@ -26,23 +26,7 @@ "html": "Continue Shopping", "failureSummary": "Fix any of the following:\n Element has insufficient color contrast of 4.17 (foreground color: #0176d3, background color: #f3f3f3, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1", "target": [ - ".css-a4jxtg" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:r3c\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + ".css-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/order-history-a11y-violations.json b/e2e/tests/a11y/desktop/__snapshots__/registered/order-history-a11y-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/order-history-a11y-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/order-history-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/desktop/__snapshots__/registered/wishlist-violations.json b/e2e/tests/a11y/desktop/__snapshots__/registered/wishlist-violations.json index 6fc5fec21e..2aed2aa6f8 100644 --- a/e2e/tests/a11y/desktop/__snapshots__/registered/wishlist-violations.json +++ b/e2e/tests/a11y/desktop/__snapshots__/registered/wishlist-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:Rd95aqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/mobile/__snapshots__/guest/plp-a11y-violations.json b/e2e/tests/a11y/mobile/__snapshots__/guest/plp-a11y-violations.json index 3fc5b7cae3..2aed2aa6f8 100644 --- a/e2e/tests/a11y/mobile/__snapshots__/guest/plp-a11y-violations.json +++ b/e2e/tests/a11y/mobile/__snapshots__/guest/plp-a11y-violations.json @@ -7,26 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:RdalaqeqlbpH1\\:" - ] - } - ] - }, - { - "id": "region", - "impact": "moderate", - "description": "Ensure all page content is contained by landmarks", - "help": "All page content should be contained by landmarks", - "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/region?application=playwright", - "nodes": [ - { - "html": "", - "failureSummary": "Fix any of the following:\n Some page content is not contained by landmarks", - "target": [ - "#popover-trigger-\\:RdalaqeqlbpH1\\: > .css-1igwmid.chakra-stack > .chakra-input__group.css-1y0e7gb > .css-va76oz" + "#popover-trigger-\\-..." ] } ] diff --git a/e2e/tests/a11y/mobile/__snapshots__/registered/account-details-a11y-violations.json b/e2e/tests/a11y/mobile/__snapshots__/registered/account-details-a11y-violations.json index 5fc9621bfa..7ffb74c86d 100644 --- a/e2e/tests/a11y/mobile/__snapshots__/registered/account-details-a11y-violations.json +++ b/e2e/tests/a11y/mobile/__snapshots__/registered/account-details-a11y-violations.json @@ -7,10 +7,10 @@ "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=playwright", "nodes": [ { - "html": "", + "html": "", "failureSummary": "Fix all of the following:\n ARIA attribute is not allowed: aria-expanded=\"false\"", "target": [ - "#popover-trigger-\\:RdalaqeqlbpH1\\:" + "#popover-trigger-\\-..." ] } ] @@ -26,23 +26,7 @@ "html": "