From c877126272183bc65b4ee2219678ba95696d8eeb Mon Sep 17 00:00:00 2001
From: Kriti Verma <155474803+kriti2710@users.noreply.github.com>
Date: Wed, 4 Mar 2026 12:12:44 +0530
Subject: [PATCH 01/18] Refactor Playwright test workflow configuration
---
.github/workflows/test.yml | 282 ++++++++++++++++++-------------------
1 file changed, 141 insertions(+), 141 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 98f8a2a..b563881 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -2,13 +2,126 @@
# Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC)
# plus anytime you trigger it manually from the Actions tab.
+# name: Run Playwright tests
+
+# on:
+# push: # runs on every push
+# pull_request: # runs on new PRs or PR updates
+# schedule:
+# - cron: '30 3 * * 1-5'
+# workflow_dispatch:
+
+# jobs:
+# run-tests:
+# name: Run shard ${{ matrix.shardIndex }}/5
+# runs-on: ubuntu-latest
+
+# strategy:
+# fail-fast: false
+# matrix:
+# shardIndex: [1,2,3,4,5]
+# shardTotal: [5]
+
+# steps:
+# - uses: actions/checkout@v4
+
+# - name: Setup Node.js 18.x
+# uses: actions/setup-node@v3
+# with:
+# node-version: '18'
+
+# - name: Create .env file
+# run: |
+# echo "USERNAME=${{ secrets.USERNAME }}" >> .env
+# echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env
+# echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env
+# echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env
+# echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env
+# echo "CITY=${{ secrets.CITY }}" >> .env
+# echo "STATE=${{ secrets.STATE }}" >> .env
+# echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env
+# echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env
+
+# - name: Cache npm dependencies
+# uses: actions/cache@v3
+# with:
+# path: ~/.npm
+# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+# restore-keys: |
+# ${{ runner.os }}-node-
+# - name: Install deps + browsers
+# run: |
+# npm ci
+# npx playwright install --with-deps chromium firefox webkit
+# - name: List Playwright projects (debug)
+# run: npx playwright list --projects | cat
+
+# - name: Run shard ${{ matrix.shardIndex }}
+# run: npx playwright test --grep="@chromium|@firefox|@webkit|@android|@ios|@api" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
+
+# - name: Upload blob report
+# if: ${{ !cancelled() }}
+# uses: actions/upload-artifact@v4
+# with:
+# name: blob-report-${{ matrix.shardIndex }}
+# path: ./blob-report
+# retention-days: 1
+
+# merge-reports:
+# name: Merge Reports
+# needs: run-tests
+# if: always() # run even if some shards fail
+# runs-on: ubuntu-latest
+
+# steps:
+# - uses: actions/checkout@v4
+
+# - name: Setup Node.js 18.x
+# uses: actions/setup-node@v3
+# with:
+# node-version: '18'
+
+# - name: Cache npm dependencies
+# uses: actions/cache@v3
+# with:
+# path: ~/.npm
+# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+# restore-keys: |
+# ${{ runner.os }}-node-
+# - name: Install deps + browsers
+# run: |
+# npm ci
+# npx playwright install --with-deps
+# - name: Download all blob reports
+# uses: actions/download-artifact@v4
+# with:
+# path: ./all-blob-reports
+# pattern: blob-report-*
+# merge-multiple: true
+
+# - name: Merge HTML & JSON reports
+# run: npx playwright merge-reports --reporter=html ./all-blob-reports
+
+# - name: Upload combined report
+# uses: actions/upload-artifact@v4
+# with:
+# name: Playwright Test Report
+# path: ./playwright-report
+# retention-days: 14
+
+# - name: Send TestDino report
+# run: |
+# npx --yes tdpw ./playwright-report \
+# --token="${{ secrets.TESTDINO_TOKEN }}" \
+# --upload-html \
+# --verbose
+
+
name: Run Playwright tests
on:
- push: # runs on every push
- pull_request: # runs on new PRs or PR updates
- schedule:
- - cron: '30 3 * * 1-5'
+ push:
+ pull_request:
workflow_dispatch:
jobs:
@@ -19,17 +132,20 @@ jobs:
strategy:
fail-fast: false
matrix:
- shardIndex: [1,2,3,4,5]
+ shardIndex: [1, 2, 3, 4, 5]
shardTotal: [5]
steps:
- - uses: actions/checkout@v4
+ - name: Checkout repo
+ uses: actions/checkout@v4
- - name: Setup Node.js 18.x
- uses: actions/setup-node@v3
+ # ✅ Required Node version
+ - name: Setup Node.js 20.x
+ uses: actions/setup-node@v4
with:
- node-version: '18'
+ node-version: '20'
+ # ✅ Required env variables for tests
- name: Create .env file
run: |
echo "USERNAME=${{ secrets.USERNAME }}" >> .env
@@ -41,7 +157,8 @@ jobs:
echo "STATE=${{ secrets.STATE }}" >> .env
echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env
echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env
-
+
+ # ✅ Cache npm dependencies
- name: Cache npm dependencies
uses: actions/cache@v3
with:
@@ -49,16 +166,24 @@ jobs:
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- - name: Install deps + browsers
+
+ # ✅ Install dependencies + TestDino (.tgz) + Playwright browsers
+ - name: Install dependencies & browsers
run: |
- npm ci
+ npm install
+ npm install --save-dev @testdino/playwright@latest
npx playwright install --with-deps chromium firefox webkit
- - name: List Playwright projects (debug)
- run: npx playwright list --projects | cat
- - name: Run shard ${{ matrix.shardIndex }}
- run: npx playwright test --grep="@chromium|@firefox|@webkit|@android|@ios|@api" --reporter=blob --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
+ # ✅ Run Playwright shard with TestDino
+ - name: Run Playwright shard with TestDino
+ env:
+ TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
+ run: |
+ npx playwright test \
+ --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \
+ --grep "@chromium|@firefox|@webkit|@android|@ios|@api" \
+ # ✅ Upload blob report (needed for merge)
- name: Upload blob report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
@@ -66,128 +191,3 @@ jobs:
name: blob-report-${{ matrix.shardIndex }}
path: ./blob-report
retention-days: 1
-
- merge-reports:
- name: Merge Reports
- needs: run-tests
- if: always() # run even if some shards fail
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Setup Node.js 18.x
- uses: actions/setup-node@v3
- with:
- node-version: '18'
-
- - name: Cache npm dependencies
- uses: actions/cache@v3
- with:
- path: ~/.npm
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-node-
- - name: Install deps + browsers
- run: |
- npm ci
- npx playwright install --with-deps
- - name: Download all blob reports
- uses: actions/download-artifact@v4
- with:
- path: ./all-blob-reports
- pattern: blob-report-*
- merge-multiple: true
-
- - name: Merge HTML & JSON reports
- run: npx playwright merge-reports --reporter=html ./all-blob-reports
-
- - name: Upload combined report
- uses: actions/upload-artifact@v4
- with:
- name: Playwright Test Report
- path: ./playwright-report
- retention-days: 14
-
- - name: Send TestDino report
- run: |
- npx --yes tdpw ./playwright-report \
- --token="${{ secrets.TESTDINO_TOKEN }}" \
- --upload-html \
- --verbose
-
-
-# name: Run Playwright tests
-
-# on:
-# push:
-# pull_request:
-# workflow_dispatch:
-
-# jobs:
-# run-tests:
-# name: Run shard ${{ matrix.shardIndex }}/5
-# runs-on: ubuntu-latest
-
-# strategy:
-# fail-fast: false
-# matrix:
-# shardIndex: [1, 2, 3, 4, 5]
-# shardTotal: [5]
-
-# steps:
-# - name: Checkout repo
-# uses: actions/checkout@v4
-
-# # ✅ Required Node version
-# - name: Setup Node.js 20.x
-# uses: actions/setup-node@v4
-# with:
-# node-version: '20'
-
-# # ✅ Required env variables for tests
-# - name: Create .env file
-# run: |
-# echo "USERNAME=${{ secrets.USERNAME }}" >> .env
-# echo "PASSWORD=${{ secrets.PASSWORD }}" >> .env
-# echo "NEW_PASSWORD=${{ secrets.NEW_PASSWORD }}" >> .env
-# echo "FIRST_NAME=${{ secrets.FIRST_NAME }}" >> .env
-# echo "STREET_NAME=${{ secrets.STREET_NAME }}" >> .env
-# echo "CITY=${{ secrets.CITY }}" >> .env
-# echo "STATE=${{ secrets.STATE }}" >> .env
-# echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env
-# echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env
-
-# # ✅ Cache npm dependencies
-# - name: Cache npm dependencies
-# uses: actions/cache@v3
-# with:
-# path: ~/.npm
-# key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
-# restore-keys: |
-# ${{ runner.os }}-node-
-
-# # ✅ Install dependencies + TestDino (.tgz) + Playwright browsers
-# - name: Install dependencies & browsers
-# run: |
-# npm install
-# npm install --save-dev @testdino/playwright@latest
-# npx playwright install --with-deps chromium firefox webkit
-
-# # ✅ Run Playwright shard with TestDino
-# - name: Run Playwright shard with TestDino
-# env:
-# TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
-# run: |
-# npx playwright test \
-# --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \
-# --grep "@chromium|@firefox|@webkit|@android|@ios|@api" \
-
-# # ✅ Upload blob report (needed for merge)
-# - name: Upload blob report
-# if: ${{ !cancelled() }}
-# uses: actions/upload-artifact@v4
-# with:
-# name: blob-report-${{ matrix.shardIndex }}
-# path: ./blob-report
-# retention-days: 1
\ No newline at end of file
From 2312b2f9537ddb4d45139500bf9ef12f834fe06d Mon Sep 17 00:00:00 2001
From: Kriti Verma <155474803+kriti2710@users.noreply.github.com>
Date: Wed, 4 Mar 2026 21:14:52 +0530
Subject: [PATCH 02/18] Reorder Playwright installation commands in workflow
---
.github/workflows/test.yml | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b563881..99b568d 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -157,7 +157,6 @@ jobs:
echo "STATE=${{ secrets.STATE }}" >> .env
echo "COUNTRY=${{ secrets.COUNTRY }}" >> .env
echo "ZIP_CODE=${{ secrets.ZIP_CODE }}" >> .env
-
# ✅ Cache npm dependencies
- name: Cache npm dependencies
uses: actions/cache@v3
@@ -166,14 +165,12 @@ jobs:
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
-
# ✅ Install dependencies + TestDino (.tgz) + Playwright browsers
- name: Install dependencies & browsers
run: |
npm install
npm install --save-dev @testdino/playwright@latest
- npx playwright install --with-deps chromium firefox webkit
-
+ npx playwright install --with-deps chromium webkit firefox
# ✅ Run Playwright shard with TestDino
- name: Run Playwright shard with TestDino
env:
@@ -181,8 +178,8 @@ jobs:
run: |
npx playwright test \
--shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \
- --grep "@chromium|@firefox|@webkit|@android|@ios|@api" \
-
+ --grep="@chromium|@firefox|@webkit|@android|@ios|@api" \
+
# ✅ Upload blob report (needed for merge)
- name: Upload blob report
if: ${{ !cancelled() }}
From 330410b72c0bd8de38218dc2415cdac6bdbf469b Mon Sep 17 00:00:00 2001
From: Kriti Verma <155474803+kriti2710@users.noreply.github.com>
Date: Wed, 4 Mar 2026 21:19:02 +0530
Subject: [PATCH 03/18] Uncomment TestDino Playwright reporter configuration
---
playwright.config.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/playwright.config.js b/playwright.config.js
index 3496e92..e0898f1 100644
--- a/playwright.config.js
+++ b/playwright.config.js
@@ -27,7 +27,7 @@ export default defineConfig({
}],
['blob', { outputDir: 'blob-report' }], // Blob reporter for merging
['json', { outputFile: './playwright-report/report.json' }],
- // ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }],
+ ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }],
],
use: {
From ca5e96a961632c12a6c66f5c4ac129b2242b3592 Mon Sep 17 00:00:00 2001
From: Kriti Verma <155474803+kriti2710@users.noreply.github.com>
Date: Thu, 5 Mar 2026 18:01:59 +0530
Subject: [PATCH 04/18] Enhance README with status and version badges
Added badges for CI status, npm version, install size, and license to README.
---
README.md | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/README.md b/README.md
index 620a189..adf6b3a 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
# Ecommerce-demo-test-playwright
Automated end-to-end tests for Ecommerce Demo store using [Playwright](https://playwright.dev/).
From e9053267acddcd126f46da83a6ffdf03f885a150 Mon Sep 17 00:00:00 2001
From: Kriti Verma <155474803+kriti2710@users.noreply.github.com>
Date: Thu, 5 Mar 2026 18:04:49 +0530
Subject: [PATCH 05/18] Remove badges from README.md
Removed CI and npm badge links from README.
---
README.md | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/README.md b/README.md
index adf6b3a..620a189 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
# Ecommerce-demo-test-playwright
Automated end-to-end tests for Ecommerce Demo store using [Playwright](https://playwright.dev/).
From 90c18869fbdd186fedff28f77970f2ac59a89f65 Mon Sep 17 00:00:00 2001
From: Nandini Monpara
Date: Thu, 5 Mar 2026 18:20:21 +0530
Subject: [PATCH 06/18] adding badges
---
README.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/README.md b/README.md
index 620a189..50010ef 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,13 @@
Automated end-to-end tests for Ecommerce Demo store using [Playwright](https://playwright.dev/).
---
+
+
+
+
+
+
+
## Project Structure
From 5450125a1bd078e3228f152c40d6b4a530ac1460 Mon Sep 17 00:00:00 2001
From: Nandini Monpara
Date: Thu, 5 Mar 2026 18:22:08 +0530
Subject: [PATCH 07/18] updated readme file by adding badges
---
LICENCE | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 LICENCE
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..6c5b4dc
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 TestDino
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
From 56a0e8adac987b569a168771b5e622447336cc51 Mon Sep 17 00:00:00 2001
From: Nandini Monpara
Date: Thu, 5 Mar 2026 18:41:53 +0530
Subject: [PATCH 08/18] updated readme.md file by adding badges
From 8eef0c74074c1021f39cba64cd6af15bab3393e7 Mon Sep 17 00:00:00 2001
From: Nandini Monpara
Date: Thu, 5 Mar 2026 18:43:34 +0530
Subject: [PATCH 09/18] Update README.md with badges
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 50010ef..ed792d7 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Automated end-to-end tests for Ecommerce Demo store using [Playwright](https://p
-
+
From 6cf63d3eadb19891d168d3fe5af66e03602fb941 Mon Sep 17 00:00:00 2001
From: Kriti Verma <155474803+kriti2710@users.noreply.github.com>
Date: Fri, 13 Mar 2026 15:45:08 +0530
Subject: [PATCH 10/18] Updated test cases by adding tags/annotations feature
Remove comments regarding manual triggers in test.yml
---
.github/workflows/test.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 99b568d..18ca318 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1,6 +1,5 @@
# .github/workflows/playwright-daily.yml
# Runs Playwright test shards every day at **11 : 42 AM IST** (06 : 12 UTC)
-# plus anytime you trigger it manually from the Actions tab.
# name: Run Playwright tests
From c578fcc42c6d5d502bbe864b37fae20da5d08279 Mon Sep 17 00:00:00 2001
From: Pratik Patel
Date: Sat, 18 Jul 2026 10:42:19 +0530
Subject: [PATCH 11/18] Add loop-generated 5000-test suite with
10-shard/3-worker CI
Co-Authored-By: Claude Fable 5
---
.github/workflows/test.yml | 10 +++++-----
playwright.config.js | 36 +++++-------------------------------
tests/bulk-tc.spec.js | 18 ++++++++++++++++++
3 files changed, 28 insertions(+), 36 deletions(-)
mode change 100644 => 100755 .github/workflows/test.yml
mode change 100644 => 100755 playwright.config.js
create mode 100644 tests/bulk-tc.spec.js
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
old mode 100644
new mode 100755
index 18ca318..bb4b073
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -125,14 +125,14 @@ on:
jobs:
run-tests:
- name: Run shard ${{ matrix.shardIndex }}/5
+ name: Run shard ${{ matrix.shardIndex }}/10
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
- shardIndex: [1, 2, 3, 4, 5]
- shardTotal: [5]
+ shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ shardTotal: [10]
steps:
- name: Checkout repo
@@ -177,8 +177,8 @@ jobs:
run: |
npx playwright test \
--shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \
- --grep="@chromium|@firefox|@webkit|@android|@ios|@api" \
-
+ --workers=3 \
+ --grep="@chromium|@firefox|@webkit|@android|@ios|@api"
# ✅ Upload blob report (needed for merge)
- name: Upload blob report
if: ${{ !cancelled() }}
diff --git a/playwright.config.js b/playwright.config.js
old mode 100644
new mode 100755
index e0898f1..9ac7393
--- a/playwright.config.js
+++ b/playwright.config.js
@@ -9,11 +9,12 @@ const isCI = !!process.env.CI;
export default defineConfig({
testDir: './tests',
+ testMatch: ['bulk-tc.spec.js'],
snapshotDir: './__screenshots__', // ✅ Baseline image storage
fullyParallel: true,
forbidOnly: isCI,
- retries: isCI ? 1 : 1, // Enable retries for flaky test behavior
- workers: isCI ? 5 : 5,
+ retries: 0,
+ workers: 3,
timeout: 60 * 1000,
expect: {
@@ -27,13 +28,13 @@ export default defineConfig({
}],
['blob', { outputDir: 'blob-report' }], // Blob reporter for merging
['json', { outputFile: './playwright-report/report.json' }],
- ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }],
],
use: {
baseURL: 'https://storedemo.testdino.com/products',
headless: true,
- trace: 'retain-on-failure',
+ // 1.59: new trace mode keeps traces for all attempts when retries fail
+ trace: 'retain-on-failure-and-retries',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
actionTimeout: 15 * 1000,
@@ -44,33 +45,6 @@ export default defineConfig({
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
- grep: /@chromium/, // only run tests tagged @chromium
- },
- {
- name: 'firefox',
- use: { ...devices['Desktop Firefox'] },
- grep: /@firefox/, // only run tests tagged @firefox
- },
- {
- name: 'webkit',
- use: { ...devices['Desktop Safari'] },
- grep: /@webkit/, // only run tests tagged @webkit
- },
- {
- name: 'android',
- use: { ...devices['Pixel 5'] },
- grep: /@android/, // only run tests tagged @android
- },
- {
- name: 'ios',
- use: { ...devices['iPhone 12'] },
- grep: /@ios/, // only run tests tagged @ios
- },
-
- {
- name: 'api',
- use: { ...devices['API'] },
- grep: /@api/, // only run tests tagged @api
},
],
});
diff --git a/tests/bulk-tc.spec.js b/tests/bulk-tc.spec.js
new file mode 100644
index 0000000..4effcf5
--- /dev/null
+++ b/tests/bulk-tc.spec.js
@@ -0,0 +1,18 @@
+// @ts-check
+// Bulk-generated suite: one loop, TOTAL_TESTS test cases.
+// Each iteration registers an independent test titled TC-, so Playwright
+// sees 5,000 real tests and distributes them evenly across shards/workers.
+// Override the count locally with TC_COUNT (e.g. TC_COUNT=50 npx playwright test).
+import { expect, test } from '@playwright/test';
+
+const TOTAL_TESTS = Number(process.env.TC_COUNT ?? 5000);
+
+test.describe('Bulk storefront checks', () => {
+ for (let i = 1; i <= TOTAL_TESTS; i++) {
+ test(`TC-${i}: Verify storefront loads and title is correct`, { tag: '@chromium' }, async ({ page }) => {
+ await page.goto('/');
+ await page.waitForLoadState('domcontentloaded');
+ await expect(page).toHaveTitle(/TestDino/);
+ });
+ }
+});
From 36f70b72deb4d0a8aa0e0988157afd897382d614 Mon Sep 17 00:00:00 2001
From: Pratik Patel
Date: Sat, 18 Jul 2026 10:56:48 +0530
Subject: [PATCH 12/18] Integrate TestDino real-time streaming; manual-dispatch
workflow with 5 tests
- Add @testdino/playwright reporter (token via TESTDINO_TOKEN env)
- Always record trace, screenshot, and video so all artifacts reach TestDino
- Default bulk suite to 5 tests (TC_COUNT env scales up to 5000)
- Workflow: manual dispatch only, test_count input, chromium-only install
Co-Authored-By: Claude Fable 5
---
.github/workflows/test.yml | 16 ++++++++++------
package-lock.json | 26 +++++++++++++-------------
package.json | 4 ++--
playwright.config.js | 9 +++++----
tests/bulk-tc.spec.js | 5 +++--
5 files changed, 33 insertions(+), 27 deletions(-)
mode change 100644 => 100755 package-lock.json
mode change 100644 => 100755 package.json
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index bb4b073..f5d0b06 100755
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -119,9 +119,12 @@
name: Run Playwright tests
on:
- push:
- pull_request:
workflow_dispatch:
+ inputs:
+ test_count:
+ description: 'Number of TC- tests to generate (max 5000)'
+ required: false
+ default: '5'
jobs:
run-tests:
@@ -168,16 +171,17 @@ jobs:
- name: Install dependencies & browsers
run: |
npm install
- npm install --save-dev @testdino/playwright@latest
- npx playwright install --with-deps chromium webkit firefox
- # ✅ Run Playwright shard with TestDino
+ npx playwright install --with-deps chromium
+ # ✅ Run Playwright shard with real-time TestDino streaming
- name: Run Playwright shard with TestDino
env:
- TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
+ TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
+ TC_COUNT: ${{ github.event.inputs.test_count || '5' }}
run: |
npx playwright test \
--shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} \
--workers=3 \
+ --pass-with-no-tests \
--grep="@chromium|@firefox|@webkit|@android|@ios|@api"
# ✅ Upload blob report (needed for merge)
- name: Upload blob report
diff --git a/package-lock.json b/package-lock.json
old mode 100644
new mode 100755
index 461940b..64c234e
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,22 +10,22 @@
"license": "ISC",
"dependencies": {
"dotenv": "^17.2.1",
- "playwright": "^1.55.0"
+ "playwright": "1.59.0"
},
"devDependencies": {
- "@playwright/test": "^1.54.1",
+ "@playwright/test": "1.59.0",
"@testdino/playwright": "^1.0.7",
"@types/node": "^24.1.0"
}
},
"node_modules/@playwright/test": {
- "version": "1.58.2",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz",
- "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==",
+ "version": "1.59.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.0.tgz",
+ "integrity": "sha512-TOA5sTLd49rTDaZpYpvCQ9hGefHQq/OYOyCVnGqS2mjMfX+lGZv2iddIJd0I48cfxqSPttS9S3OuLKyylHcO1w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright": "1.58.2"
+ "playwright": "1.59.0"
},
"bin": {
"playwright": "cli.js"
@@ -627,12 +627,12 @@
}
},
"node_modules/playwright": {
- "version": "1.58.2",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
- "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
+ "version": "1.59.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.0.tgz",
+ "integrity": "sha512-wihGScriusvATUxmhfENxg0tj1vHEFeIwxlnPFKQTOQVd7aG08mUfvvniRP/PtQOC+2Bs52kBOC/Up1jTXeIbw==",
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.58.2"
+ "playwright-core": "1.59.0"
},
"bin": {
"playwright": "cli.js"
@@ -645,9 +645,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.58.2",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
- "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
+ "version": "1.59.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.0.tgz",
+ "integrity": "sha512-PW/X/IoZ6BMUUy8rpwHEZ8Kc0IiLIkgKYGNFaMs5KmQhcfLILNx9yCQD0rnWeWfz1PNeqcFP1BsihQhDOBCwZw==",
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
diff --git a/package.json b/package.json
old mode 100644
new mode 100755
index 0e8ba2a..b98f825
--- a/package.json
+++ b/package.json
@@ -7,12 +7,12 @@
"license": "ISC",
"description": "",
"devDependencies": {
- "@playwright/test": "^1.54.1",
+ "@playwright/test": "1.59.0",
"@testdino/playwright": "^1.0.7",
"@types/node": "^24.1.0"
},
"dependencies": {
"dotenv": "^17.2.1",
- "playwright": "^1.55.0"
+ "playwright": "1.59.0"
}
}
diff --git a/playwright.config.js b/playwright.config.js
index 9ac7393..de9caac 100755
--- a/playwright.config.js
+++ b/playwright.config.js
@@ -28,15 +28,16 @@ export default defineConfig({
}],
['blob', { outputDir: 'blob-report' }], // Blob reporter for merging
['json', { outputFile: './playwright-report/report.json' }],
+ ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }], // Real-time streaming to TestDino
],
use: {
baseURL: 'https://storedemo.testdino.com/products',
headless: true,
- // 1.59: new trace mode keeps traces for all attempts when retries fail
- trace: 'retain-on-failure-and-retries',
- screenshot: 'only-on-failure',
- video: 'retain-on-failure',
+ // Always record so every artifact reaches TestDino
+ trace: 'on',
+ screenshot: 'on',
+ video: 'on',
actionTimeout: 15 * 1000,
navigationTimeout: 30 * 1000,
},
diff --git a/tests/bulk-tc.spec.js b/tests/bulk-tc.spec.js
index 4effcf5..513aa95 100644
--- a/tests/bulk-tc.spec.js
+++ b/tests/bulk-tc.spec.js
@@ -2,10 +2,11 @@
// Bulk-generated suite: one loop, TOTAL_TESTS test cases.
// Each iteration registers an independent test titled TC-, so Playwright
// sees 5,000 real tests and distributes them evenly across shards/workers.
-// Override the count locally with TC_COUNT (e.g. TC_COUNT=50 npx playwright test).
+// Override the count with TC_COUNT (e.g. TC_COUNT=5000 npx playwright test).
+// Default is 5 for now to keep TestDino streaming runs small.
import { expect, test } from '@playwright/test';
-const TOTAL_TESTS = Number(process.env.TC_COUNT ?? 5000);
+const TOTAL_TESTS = Number(process.env.TC_COUNT ?? 5);
test.describe('Bulk storefront checks', () => {
for (let i = 1; i <= TOTAL_TESTS; i++) {
From 63ee6543dea08cf91f7118abbb44b27b819c428e Mon Sep 17 00:00:00 2001
From: Pratik Patel
Date: Sat, 18 Jul 2026 11:59:25 +0530
Subject: [PATCH 13/18] Use vendored @testdino/playwright v2.0.0 tarball; point
CI at staging server; drop old tdpw references
Co-Authored-By: Claude Fable 5
---
.env.example | 0
.github/workflows/test.yml | 8 +-
.gitignore | 0
LICENCE | 0
README.md | 35 ++-
...hub-login-after-typing-chromium-darwin.png | Bin
.../github-login-changed-chromium-darwin.png | Bin
.../github-login-chromium-darwin.png | Bin
.../github-login-filled-chromium-darwin.png | Bin
.../github-login-initial-chromium-darwin.png | Bin
.../github-login-username-chromium-darwin.png | Bin
.../username-input-chromium-darwin.png | Bin
github-login.png | Bin
package-lock.json | 287 ++++++++++++++----
package.json | 2 +-
pages/AllPages.js | 0
pages/AllProductsPage.js | 0
pages/BasePage.js | 0
pages/CartPage.js | 0
pages/CheckoutPage.js | 0
pages/ContactUsPage.js | 0
pages/HomePage.js | 0
pages/InventoryPage.js | 0
pages/LoginPage.js | 0
pages/OrderDetailsPage.js | 0
pages/OrderPage.js | 0
pages/ProductDetailsPage.js | 0
pages/SignupPage.js | 0
pages/UserPage.js | 0
tests/cart_checkout.spec.js | 0
tests/debug-features-live-trace.spec.js | 102 +++++++
tests/debug-features.spec.js | 90 ++++++
tests/delete-api.spec.js | 0
tests/get-users.spec.js | 0
tests/login.spec.js | 0
tests/navigation.spec.js | 0
tests/orders.spec.js | 0
tests/post-api.spec.js | 0
tests/product.spec.js | 0
tests/updateUser.spec.js | 0
tests/visual.spec.js | 0
.../github-login-changed-chromium-darwin.png | Bin
.../github-login-chromium-darwin.png | Bin
vendor/testdino-playwright-2.0.0.tgz | Bin 0 -> 233597 bytes
44 files changed, 439 insertions(+), 85 deletions(-)
mode change 100644 => 100755 .env.example
mode change 100644 => 100755 .gitignore
mode change 100644 => 100755 LICENCE
mode change 100644 => 100755 README.md
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/github-login-after-typing-chromium-darwin.png
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/github-login-changed-chromium-darwin.png
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/github-login-chromium-darwin.png
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/github-login-filled-chromium-darwin.png
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/github-login-initial-chromium-darwin.png
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/github-login-username-chromium-darwin.png
mode change 100644 => 100755 __screenshots__/visual.spec.js-snapshots/username-input-chromium-darwin.png
mode change 100644 => 100755 github-login.png
mode change 100644 => 100755 pages/AllPages.js
mode change 100644 => 100755 pages/AllProductsPage.js
mode change 100644 => 100755 pages/BasePage.js
mode change 100644 => 100755 pages/CartPage.js
mode change 100644 => 100755 pages/CheckoutPage.js
mode change 100644 => 100755 pages/ContactUsPage.js
mode change 100644 => 100755 pages/HomePage.js
mode change 100644 => 100755 pages/InventoryPage.js
mode change 100644 => 100755 pages/LoginPage.js
mode change 100644 => 100755 pages/OrderDetailsPage.js
mode change 100644 => 100755 pages/OrderPage.js
mode change 100644 => 100755 pages/ProductDetailsPage.js
mode change 100644 => 100755 pages/SignupPage.js
mode change 100644 => 100755 pages/UserPage.js
mode change 100644 => 100755 tests/cart_checkout.spec.js
create mode 100755 tests/debug-features-live-trace.spec.js
create mode 100755 tests/debug-features.spec.js
mode change 100644 => 100755 tests/delete-api.spec.js
mode change 100644 => 100755 tests/get-users.spec.js
mode change 100644 => 100755 tests/login.spec.js
mode change 100644 => 100755 tests/navigation.spec.js
mode change 100644 => 100755 tests/orders.spec.js
mode change 100644 => 100755 tests/post-api.spec.js
mode change 100644 => 100755 tests/product.spec.js
mode change 100644 => 100755 tests/updateUser.spec.js
mode change 100644 => 100755 tests/visual.spec.js
mode change 100644 => 100755 tests/visual.spec.js-snapshots/github-login-changed-chromium-darwin.png
mode change 100644 => 100755 tests/visual.spec.js-snapshots/github-login-chromium-darwin.png
create mode 100644 vendor/testdino-playwright-2.0.0.tgz
diff --git a/.env.example b/.env.example
old mode 100644
new mode 100755
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f5d0b06..3babd7e 100755
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -108,13 +108,6 @@
# path: ./playwright-report
# retention-days: 14
-# - name: Send TestDino report
-# run: |
-# npx --yes tdpw ./playwright-report \
-# --token="${{ secrets.TESTDINO_TOKEN }}" \
-# --upload-html \
-# --verbose
-
name: Run Playwright tests
@@ -176,6 +169,7 @@ jobs:
- name: Run Playwright shard with TestDino
env:
TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
+ TESTDINO_SERVER_URL: https://stg-analytics.testdino.com
TC_COUNT: ${{ github.event.inputs.test_count || '5' }}
run: |
npx playwright test \
diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
diff --git a/LICENCE b/LICENCE
old mode 100644
new mode 100755
diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index ed792d7..729981e
--- a/README.md
+++ b/README.md
@@ -5,8 +5,8 @@ Automated end-to-end tests for Ecommerce Demo store using [Playwright](https://p
---
-
-
+
+
@@ -52,32 +52,41 @@ npx playwright show-report
## Testdino Integration
-[Testdino](https://testdino.com/) enables cloud-based Playwright reporting.
+[Testdino](https://testdino.com/) enables cloud-based Playwright reporting with real-time streaming via the [`@testdino/playwright`](https://www.npmjs.com/package/@testdino/playwright) reporter.
-### Local Execution
-
-After your tests complete and the report is generated in `playwright-report`, upload it to Testdino:
+The reporter is already configured in `playwright.config.js`:
+```js
+reporter: [
+ ['@testdino/playwright', { token: process.env.TESTDINO_TOKEN }],
+],
+```
+### Local Execution
-Replace the token above with your own Testdino API key.
+Set your API token (from the TestDino dashboard) and run tests as usual — results stream to TestDino in real time:
-See all available commands:
```sh
-npx tdpw --help
+export TESTDINO_TOKEN=YOUR_API_TOKEN
+npx playwright test
```
+You can also put the token in `.env` (see `.env.example`); it is loaded automatically.
+
---
## CI/CD Pipeline Integration
### GitHub Actions
-Add the following step to your workflow after tests and report generation:
-
+Add `TESTDINO_TOKEN` as a repository secret and expose it to the test step:
-
-Ensure your API key is correctly placed in the command.
+```yaml
+- name: Run Playwright tests
+ run: npx playwright test
+ env:
+ TESTDINO_TOKEN: ${{ secrets.TESTDINO_TOKEN }}
+```
---
diff --git a/__screenshots__/visual.spec.js-snapshots/github-login-after-typing-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/github-login-after-typing-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/__screenshots__/visual.spec.js-snapshots/github-login-changed-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/github-login-changed-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/__screenshots__/visual.spec.js-snapshots/github-login-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/github-login-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/__screenshots__/visual.spec.js-snapshots/github-login-filled-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/github-login-filled-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/__screenshots__/visual.spec.js-snapshots/github-login-initial-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/github-login-initial-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/__screenshots__/visual.spec.js-snapshots/github-login-username-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/github-login-username-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/__screenshots__/visual.spec.js-snapshots/username-input-chromium-darwin.png b/__screenshots__/visual.spec.js-snapshots/username-input-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/github-login.png b/github-login.png
old mode 100644
new mode 100755
diff --git a/package-lock.json b/package-lock.json
index 64c234e..5e77396 100755
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
},
"devDependencies": {
"@playwright/test": "1.59.0",
- "@testdino/playwright": "^1.0.7",
+ "@testdino/playwright": "file:vendor/testdino-playwright-2.0.0.tgz",
"@types/node": "^24.1.0"
}
},
@@ -55,18 +55,22 @@
}
},
"node_modules/@testdino/playwright": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/@testdino/playwright/-/playwright-1.0.7.tgz",
- "integrity": "sha512-ayFZ7T6BFBTxS5coYPGmANEhmBVRf0nX8CZEBPnTIUpqY5mrM2gtxSpOwEct86aRW/wo5FnchjyxN1wEc0C2Mg==",
+ "version": "2.0.0",
+ "resolved": "file:vendor/testdino-playwright-2.0.0.tgz",
+ "integrity": "sha512-wVBcmAQ7Bbyi/YkFIHFzNGwxIIFn23uZOsvVz/mve5c2gP0vP7bgWsX0rye77SNEmP6IJxpM3WAl2aAGhKNKzQ==",
"dev": true,
"dependencies": {
- "axios": "^1.13.4",
+ "axios": "^1.18.1",
"chalk": "^5.6.2",
- "commander": "^14.0.3",
- "dotenv": "^17.2.3",
+ "commander": "^15.0.0",
+ "dotenv": "^17.4.2",
"execa": "^9.6.1",
- "jiti": "^2.6.1",
- "ws": "^8.19.0"
+ "istanbul-lib-coverage": "^3.2.2",
+ "istanbul-lib-report": "^3.0.1",
+ "istanbul-reports": "^3.2.0",
+ "jiti": "^2.7.0",
+ "kafkajs": "^2.2.4",
+ "picomatch": "^4.0.4"
},
"bin": {
"tdpw": "bin/tdpw.js"
@@ -88,6 +92,19 @@
"undici-types": "~7.16.0"
}
},
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -96,15 +113,16 @@
"license": "MIT"
},
"node_modules/axios": {
- "version": "1.13.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
- "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz",
+ "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "follow-redirects": "^1.15.11",
+ "follow-redirects": "^1.16.0",
"form-data": "^4.0.5",
- "proxy-from-env": "^1.1.0"
+ "https-proxy-agent": "^5.0.1",
+ "proxy-from-env": "^2.1.0"
}
},
"node_modules/call-bind-apply-helpers": {
@@ -148,13 +166,13 @@
}
},
"node_modules/commander": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
+ "version": "15.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz",
+ "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.12.0"
}
},
"node_modules/cross-spawn": {
@@ -172,6 +190,24 @@
"node": ">= 8"
}
},
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -183,9 +219,9 @@
}
},
"node_modules/dotenv": {
- "version": "17.2.4",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.4.tgz",
- "integrity": "sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==",
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -230,9 +266,9 @@
}
},
"node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -302,9 +338,9 @@
}
},
"node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"dev": true,
"funding": [
{
@@ -323,17 +359,17 @@
}
},
"node_modules/form-data": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
},
"engines": {
"node": ">= 6"
@@ -432,6 +468,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -462,9 +508,9 @@
}
},
"node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -474,6 +520,27 @@
"node": ">= 0.4"
}
},
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/human-signals": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz",
@@ -530,16 +597,81 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/jiti": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
- "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
+ "node_modules/kafkajs": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz",
+ "integrity": "sha512-j/YeapB1vfPT2iOIUn/vxdyKEuhuY2PxMBvf5JWux6iSaukAccrMtXEY/Lb7OvavDhOWME589bpLrEdnVHjfjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -573,6 +705,13 @@
"node": ">= 0.6"
}
},
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/npm-run-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
@@ -626,6 +765,19 @@
"node": ">=8"
}
},
+ "node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/playwright": {
"version": "1.59.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.0.tgz",
@@ -673,11 +825,27 @@
}
},
"node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/shebang-command": {
"version": "2.0.0",
@@ -728,6 +896,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/undici-types": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
@@ -764,28 +945,6 @@
"node": ">= 8"
}
},
- "node_modules/ws": {
- "version": "8.19.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
"node_modules/yoctocolors": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz",
diff --git a/package.json b/package.json
index b98f825..8b80885 100755
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"description": "",
"devDependencies": {
"@playwright/test": "1.59.0",
- "@testdino/playwright": "^1.0.7",
+ "@testdino/playwright": "file:vendor/testdino-playwright-2.0.0.tgz",
"@types/node": "^24.1.0"
},
"dependencies": {
diff --git a/pages/AllPages.js b/pages/AllPages.js
old mode 100644
new mode 100755
diff --git a/pages/AllProductsPage.js b/pages/AllProductsPage.js
old mode 100644
new mode 100755
diff --git a/pages/BasePage.js b/pages/BasePage.js
old mode 100644
new mode 100755
diff --git a/pages/CartPage.js b/pages/CartPage.js
old mode 100644
new mode 100755
diff --git a/pages/CheckoutPage.js b/pages/CheckoutPage.js
old mode 100644
new mode 100755
diff --git a/pages/ContactUsPage.js b/pages/ContactUsPage.js
old mode 100644
new mode 100755
diff --git a/pages/HomePage.js b/pages/HomePage.js
old mode 100644
new mode 100755
diff --git a/pages/InventoryPage.js b/pages/InventoryPage.js
old mode 100644
new mode 100755
diff --git a/pages/LoginPage.js b/pages/LoginPage.js
old mode 100644
new mode 100755
diff --git a/pages/OrderDetailsPage.js b/pages/OrderDetailsPage.js
old mode 100644
new mode 100755
diff --git a/pages/OrderPage.js b/pages/OrderPage.js
old mode 100644
new mode 100755
diff --git a/pages/ProductDetailsPage.js b/pages/ProductDetailsPage.js
old mode 100644
new mode 100755
diff --git a/pages/SignupPage.js b/pages/SignupPage.js
old mode 100644
new mode 100755
diff --git a/pages/UserPage.js b/pages/UserPage.js
old mode 100644
new mode 100755
diff --git a/tests/cart_checkout.spec.js b/tests/cart_checkout.spec.js
old mode 100644
new mode 100755
diff --git a/tests/debug-features-live-trace.spec.js b/tests/debug-features-live-trace.spec.js
new file mode 100755
index 0000000..0ef152b
--- /dev/null
+++ b/tests/debug-features-live-trace.spec.js
@@ -0,0 +1,102 @@
+// @ts-check
+// Test 2 of 2 — exercises the rest of Playwright 1.59's debugging surface:
+// live tracing, ariaSnapshot, console-message filtering, and the
+// async-dispose pattern. Fails intentionally.
+import { expect, test } from '@playwright/test';
+
+// Disable the config's auto-tracing for this file so we can own
+// tracing.start()/stop() ourselves and exercise the new `live: true` option.
+// test.use({ trace }) must be at file scope — nesting it in a describe fails.
+test.use({ trace: 'off' });
+
+test.describe('Playwright 1.59 — live trace, aria snapshot, console filter', () => {
+
+ test('aria snapshot + live trace + console filter (fails intentionally)', async ({ browser }, testInfo) => {
+ const tracePath = testInfo.outputPath('live-run.zip');
+ const videoDir = testInfo.outputPath('video');
+
+ // Spin up our own context so we fully own its tracing and video
+ // lifecycle. recordVideo on a manually-created context is the only way
+ // to get a video artifact here (the auto-video fixture only applies to
+ // the default `page` fixture).
+ const context = await browser.newContext({ recordVideo: { dir: videoDir } });
+ const page = await context.newPage();
+
+ // ---- live tracing (1.59) ---------------------------------------------
+ // With `live: true`, trace chunks are flushed to disk continuously. You
+ // can open them in real time from another terminal:
+ // npx playwright show-trace --live
+ // Useful when a long-running test hangs — you can see what it's doing
+ // right now without waiting for stop().
+ await context.tracing.start({
+ name: 'live-run',
+ title: 'aria snapshot run',
+ screenshots: true,
+ snapshots: true,
+ sources: true,
+ live: true,
+ });
+
+ // ---- async-dispose pattern (1.59) ------------------------------------
+ // In a TS project you'd write:
+ // await using cdp = await context.newCDPSession(page);
+ // and Symbol.asyncDispose would call cdp.detach() at block exit. This
+ // plain-JS file's parser doesn't accept the syntax, so we do the same
+ // cleanup manually via try/finally — the underlying disposal hook is
+ // identical.
+ const cdp = await context.newCDPSession(page);
+ await cdp.send('Network.enable');
+
+ try {
+ await page.goto('/');
+
+ // ---- ariaSnapshot (1.59) -------------------------------------------
+ // Serialize the accessibility tree as a YAML-ish string. Easy to diff
+ // across runs and cheap to feed to an LLM for a semantic diff. In 1.59,
+ // `mode` accepts 'default' (human-readable) or 'ai' (token-efficient
+ // for LLMs).
+ const snapshot = await page.locator('body').ariaSnapshot({ mode: 'ai' });
+ console.log('--- ARIA SNAPSHOT (first 400 chars) ---');
+ console.log(snapshot.slice(0, 400));
+
+ // Emit console output from the page so we have something to filter on.
+ await page.evaluate(() => {
+ console.log('hello from the page');
+ console.warn('a benign warning');
+ console.error('INTENDED_ERROR: nothing actually broke');
+ });
+
+ // ---- buffered console messages (1.59) ------------------------------
+ // 1.59 buffers console messages on the page, so you can pull them
+ // retroactively — no up-front page.on('console') listener needed. The
+ // `filter` option is a string: 'all' (everything since the page
+ // opened) or 'since-navigation' (only since the last top-level nav).
+ // Then you narrow by type() in JS. Companion APIs:
+ // page.clearConsoleMessages(), page.pageErrors(),
+ // page.clearPageErrors(), consoleMessage.timestamp().
+ const allMessages = await page.consoleMessages({ filter: 'since-navigation' });
+ const errors = allMessages.filter(m => m.type() === 'error');
+
+ // Intentional failure — we asked for zero errors, we have one.
+ // The saved trace can then be inspected from the CLI with the new
+ // agent-friendly commands (1.59):
+ // npx playwright trace actions --grep "expect"
+ // npx playwright trace action
+ // npx playwright trace snapshot --name after
+ expect(errors, `got ${errors.length} console error(s)`).toHaveLength(0);
+ } finally {
+ // Stop + attach in finally so the trace survives intentional failures.
+ // attach() surfaces the artifacts in the HTML reporter under this test.
+ await context.tracing.stop({ path: tracePath });
+ await cdp.detach();
+ const videoFile = await page.video()?.path();
+ await context.close();
+
+ await testInfo.attach('live-run.zip', { path: tracePath, contentType: 'application/zip' });
+ if (videoFile) {
+ await testInfo.attach('video.webm', { path: videoFile, contentType: 'video/webm' });
+ }
+ }
+ });
+
+});
diff --git a/tests/debug-features.spec.js b/tests/debug-features.spec.js
new file mode 100755
index 0000000..a083fce
--- /dev/null
+++ b/tests/debug-features.spec.js
@@ -0,0 +1,90 @@
+// @ts-check
+// Test 1 of 2 — exercises Playwright 1.59's new page.screencast API.
+// Fails intentionally so the reporter retains video + trace artifacts.
+import { expect, test } from '@playwright/test';
+
+test.describe('Playwright 1.59 — screencast API', () => {
+
+ // ---------------------------------------------------------------------------
+ // 1.59 introduces page.screencast as a unified capture interface. Unlike
+ // the context-level `recordVideo` option (set-and-forget), screencast is
+ // imperative: you call start/stop inside the test, can layer action
+ // annotations, chapter titles, and custom HTML overlays onto the recording,
+ // and the output ends up as a test attachment in the HTML reporter.
+ //
+ // Relation to videos: screencast *replaces* recordVideo for any case where
+ // you want control over what's captured. The emitted .webm is exactly
+ // what the `video` attachment points to.
+ //
+ // Relation to traces: every screencast.start / showChapter / showActions /
+ // showOverlay call is a first-class action in the trace timeline. Open
+ // the trace and you'll see each chapter switch lined up next to the
+ // DOM snapshot at that moment — you can scrub video and trace in lockstep.
+ // ---------------------------------------------------------------------------
+ test('screencast walkthrough of the store (fails intentionally)', async ({ page }, testInfo) => {
+ const videoPath = testInfo.outputPath('walkthrough.webm');
+
+ // start() begins encoding frames into a .webm.
+ await page.screencast.start({ path: videoPath });
+
+ // Overlay a badge every time Playwright performs an action (click, fill,
+ // hover…). This is the "agentic video receipt" feature — reviewers see
+ // why the cursor moved where it did. position + fontSize configurable.
+ await page.screencast.showActions({ position: 'top-right', fontSize: 14 });
+
+ // Chapters render a titled section for `duration` ms, giving the video a
+ // narrative structure that a reviewer (or LLM) can navigate.
+ await page.screencast.showChapter('Open storefront', {
+ description: 'Navigate to the products landing page',
+ duration: 1200,
+ });
+
+ await page.goto('/');
+ await page.waitForLoadState('domcontentloaded');
+
+ await page.screencast.showChapter('Inspect layout', {
+ description: 'Check the logo and hero copy are present',
+ duration: 1000,
+ });
+
+ // A few selector-agnostic interactions so the screencast has real frames
+ // and showActions() has actions to annotate before we hit the failure.
+ await page.locator('body').hover();
+ await page.mouse.wheel(0, 400);
+ await page.waitForTimeout(500);
+ await page.mouse.wheel(0, 400);
+ await page.waitForTimeout(500);
+
+ await page.screencast.showChapter('Scan products', {
+ description: 'Scroll the grid end-to-end',
+ duration: 1000,
+ });
+
+ await page.keyboard.press('End');
+ await page.waitForTimeout(800);
+ await page.keyboard.press('Home');
+ await page.waitForTimeout(500);
+
+ // Arbitrary HTML overlay — good for stamping build IDs, test names, etc.
+ await page.screencast.showOverlay(
+ `
+ test run — ${new Date().toISOString()}
+
`,
+ { position: 'bottom-left', duration: 2000 }
+ );
+
+ await page.screencast.showChapter('Final title check', {
+ description: 'Assert the page title (intentionally wrong)',
+ duration: 800,
+ });
+
+ // Intentional failure — the real title is "TestDino | Demo Store". The
+ // failure triggers retain-on-failure for both trace and video, so the
+ // reporter ends up with the screencast.webm AND a trace.zip whose
+ // timeline contains every screencast.* action above.
+ await expect(page).toHaveTitle(/Unicorns/);
+
+ await page.screencast.stop();
+ });
+
+});
diff --git a/tests/delete-api.spec.js b/tests/delete-api.spec.js
old mode 100644
new mode 100755
diff --git a/tests/get-users.spec.js b/tests/get-users.spec.js
old mode 100644
new mode 100755
diff --git a/tests/login.spec.js b/tests/login.spec.js
old mode 100644
new mode 100755
diff --git a/tests/navigation.spec.js b/tests/navigation.spec.js
old mode 100644
new mode 100755
diff --git a/tests/orders.spec.js b/tests/orders.spec.js
old mode 100644
new mode 100755
diff --git a/tests/post-api.spec.js b/tests/post-api.spec.js
old mode 100644
new mode 100755
diff --git a/tests/product.spec.js b/tests/product.spec.js
old mode 100644
new mode 100755
diff --git a/tests/updateUser.spec.js b/tests/updateUser.spec.js
old mode 100644
new mode 100755
diff --git a/tests/visual.spec.js b/tests/visual.spec.js
old mode 100644
new mode 100755
diff --git a/tests/visual.spec.js-snapshots/github-login-changed-chromium-darwin.png b/tests/visual.spec.js-snapshots/github-login-changed-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/tests/visual.spec.js-snapshots/github-login-chromium-darwin.png b/tests/visual.spec.js-snapshots/github-login-chromium-darwin.png
old mode 100644
new mode 100755
diff --git a/vendor/testdino-playwright-2.0.0.tgz b/vendor/testdino-playwright-2.0.0.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..009ecd92d862509e5fc8b76d953f6073bdbeac4e
GIT binary patch
literal 233597
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