Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
974931a
Playwright POC - migrate TestCafe E2E tests to Playwright
aleksei-semikozov Mar 22, 2026
a74ebdf
Playwright POC - improved scheduler test conversions from AI agents
aleksei-semikozov Mar 22, 2026
ca58243
Playwright POC - agent-improved test conversions
aleksei-semikozov Mar 22, 2026
214f5fc
Playwright POC - editors, navigation, common test improvements
aleksei-semikozov Mar 22, 2026
f4a3f37
Playwright POC - timezone and viewOffset test improvements
aleksei-semikozov Mar 22, 2026
0e3e343
Playwright POC - scheduler layout test improvements
aleksei-semikozov Mar 22, 2026
5eaba67
Playwright POC - dataGrid test improvements
aleksei-semikozov Mar 22, 2026
a4e0d83
Playwright POC - dragDrop, keyboard, cellsSelection improvements
aleksei-semikozov Mar 22, 2026
c763df9
Playwright POC - remaining scheduler tests (virtualScrolling, resize,…
aleksei-semikozov Mar 22, 2026
246bede
Fix CI: exclude playwright files from lint/tsconfig, remove duplicate…
aleksei-semikozov Mar 22, 2026
3a903d8
Fix TS lint: remove unused path import from playwright.config.ts
aleksei-semikozov Mar 22, 2026
5b03e91
Fix Playwright install: use PLAYWRIGHT_BROWSERS_PATH for non-root runner
aleksei-semikozov Mar 22, 2026
8e0c882
Playwright POC - two-pass test: generate baselines then compare
aleksei-semikozov Mar 22, 2026
d758e9a
Playwright POC - fix screenshot naming to match TestCafe baselines, t…
aleksei-semikozov Mar 24, 2026
335c6ce
Playwright POC - narrow CI to scheduler/common/month only
aleksei-semikozov Mar 24, 2026
4c1a9d7
Playwright POC - fix: use npx instead of pnpx to avoid duplicate @pla…
aleksei-semikozov Mar 24, 2026
311cb59
Playwright POC - remove merge-results job (not needed with single mat…
aleksei-semikozov Mar 24, 2026
e73f0a5
Playwright POC - sanitize artifact name to avoid NTFS char issues
aleksei-semikozov Mar 24, 2026
a9f4bd2
Playwright POC - fix TestCafe syntax leftovers across all components
aleksei-semikozov Mar 24, 2026
8a248de
Playwright POC - fix syntax errors in scheduler tests (common.spec.ts…
aleksei-semikozov Mar 24, 2026
bd88ab5
Playwright POC - expand CI to all scheduler tests (common, timezones,…
aleksei-semikozov Mar 24, 2026
00dc864
Playwright POC - add Scheduler page object (port from TestCafe model)
aleksei-semikozov Mar 24, 2026
76fa95a
Playwright POC - fix all syntax errors across dataGrid, editors, navi…
aleksei-semikozov Mar 24, 2026
6c43521
Playwright POC - remove duplicated etalons, read from TestCafe tests/…
aleksei-semikozov Mar 24, 2026
8dc9b7e
Playwright POC - remove baseline generation pass, use TestCafe etalon…
aleksei-semikozov Mar 24, 2026
ebd9ae1
Playwright POC - page objects, accessibility helper, unskip tests acr…
aleksei-semikozov Mar 24, 2026
fa81c1e
Playwright POC - unskip all remaining tests, complete page object cov…
aleksei-semikozov Mar 24, 2026
1e22ac0
Playwright POC - unskip final 32 tests, zero unconditional skips
aleksei-semikozov Mar 25, 2026
ac04a62
Playwright POC - blur focus before screenshots, hide caret and scroll…
aleksei-semikozov Mar 25, 2026
5bdb330
Playwright POC - fix full-page screenshot for tests without element, …
aleksei-semikozov Mar 25, 2026
e7a87a0
Playwright POC - fix createWidget to support callbacks via string ser…
aleksei-semikozov Mar 25, 2026
8276bae
Playwright POC - add scrollbar-width:none, keep viewport at 1200x800
aleksei-semikozov Mar 25, 2026
57218c2
Playwright POC - fix CI: set -o pipefail so test failures are not mas…
aleksei-semikozov Mar 25, 2026
94e36ee
Playwright POC - viewport 1185 to match TestCafe element widths, thre…
aleksei-semikozov Mar 25, 2026
aadcea1
Playwright POC - revert viewport to 1200 (CI etalons are at 1200/1184…
aleksei-semikozov Mar 25, 2026
006476c
Playwright POC - viewport 1185 (matches TestCafe CI etalons at 1169px…
aleksei-semikozov Mar 25, 2026
23e0943
Playwright POC - gitignore playwright-results, playwright-report, pw-…
aleksei-semikozov Mar 25, 2026
f596ab0
Playwright - fix scheduler tests (timezones timezone emulation, viewO…
aleksei-semikozov Mar 26, 2026
00acd22
Playwright - fix all scopes, expand CI to all components
aleksei-semikozov Mar 26, 2026
f8cbab8
Playwright - add canary tests to verify CI catches failures
aleksei-semikozov Mar 26, 2026
7f6e4f8
Playwright - fix editors tests (htmlEditor dialogs, dropDownButton, d…
aleksei-semikozov Mar 26, 2026
f57fb52
Playwright - fix navigation tests (scrollable, tabPanel, helpers)
aleksei-semikozov Mar 26, 2026
6346c3e
Merge remote-tracking branch 'upstream/26_1' into playwright-poc
aleksei-semikozov Mar 26, 2026
f64bbe6
Playwright - update pnpm-lock.yaml for playwright dependencies
aleksei-semikozov Mar 26, 2026
d95165b
Playwright - dynamic viewport correction for cross-platform content w…
aleksei-semikozov Mar 26, 2026
cc91f35
Playwright - improve viewport correction with resize event for CI
aleksei-semikozov Mar 26, 2026
4a11d96
Playwright - diagnostic test: log viewport/scrollbar dimensions on CI
aleksei-semikozov Mar 26, 2026
a5ef744
Playwright - fix CI path (remove trailing slash for single file)
aleksei-semikozov Mar 26, 2026
6ac91b6
Playwright - viewport 1200 in config, restore full CI matrix, remove …
aleksei-semikozov Mar 26, 2026
448d12e
Playwright - fix screenshot clip: use offsetWidth instead of scrollWi…
aleksei-semikozov Mar 26, 2026
1afebde
Playwright - CSS scrollbar 15px to match TestCafe headless Chrome, re…
aleksei-semikozov Mar 26, 2026
400c439
Revert "Playwright - CSS scrollbar 15px to match TestCafe headless Ch…
aleksei-semikozov Mar 26, 2026
d528849
Playwright - CSS scrollbar 15px only on overflow (no forced scroll), …
aleksei-semikozov Mar 26, 2026
98189a3
Playwright - scrollbar-gutter stable to match TestCafe always-visible…
aleksei-semikozov Mar 26, 2026
d2af373
Revert "Playwright - scrollbar-gutter stable to match TestCafe always…
aleksei-semikozov Mar 26, 2026
232d9a1
Playwright - viewport 1185 for viewOffset, fix getLocatorScrollClip f…
aleksei-semikozov Mar 26, 2026
fbfff27
Playwright - Phase 1: sync test names for editors, navigation, common
aleksei-semikozov Mar 26, 2026
627a684
Playwright - Phase 2: sync scheduler/common test names (26 added, 19 …
aleksei-semikozov Mar 26, 2026
12ba6b1
Playwright - Phase 4: sync cardView/accessibility test names (5 renamed)
aleksei-semikozov Mar 26, 2026
ad5a077
Playwright - Phase 3: sync dataGrid test names (8 renamed, 925 TC tes…
aleksei-semikozov Mar 26, 2026
18aaebb
Playwright - add 26 missing scheduler/timezones tests
aleksei-semikozov Mar 26, 2026
5d6682c
Playwright - add 11 missing cardView visual tests
aleksei-semikozov Mar 26, 2026
862e8f4
Playwright - add 11 dataGrid tests, fix skipped tests (accessibility,…
aleksei-semikozov Mar 26, 2026
2bdcd86
Playwright - dataGrid wave 2: +57 tests (filtering, grouping, editing…
aleksei-semikozov Mar 26, 2026
67f54fd
Playwright - cardView wave 2: +51 tests (keyboard nav, selection, sea…
aleksei-semikozov Mar 26, 2026
578e34d
Playwright - dataGrid wave 3: +46 tests (keyboard nav, virtualColumns…
aleksei-semikozov Mar 26, 2026
338d90e
Playwright - cardView wave 3: +53 tests (events, contextMenu, filterP…
aleksei-semikozov Mar 26, 2026
1234e06
Playwright - dataGrid wave 4: +38 tests (focus, fixedColumns, columnR…
aleksei-semikozov Mar 26, 2026
b6ce871
Playwright - accessibility: +55 axe test configurations (scheduler, d…
aleksei-semikozov Mar 26, 2026
d946425
Playwright - dataGrid wave 5: +33 tests (editing functional, validati…
aleksei-semikozov Mar 26, 2026
85ac857
Playwright - dataGrid wave 6: +35 tests (keyboard nav functional, edi…
aleksei-semikozov Mar 27, 2026
1ff4ee4
Playwright - dataGrid wave 7: +28 tests (editing focus, focused row, …
aleksei-semikozov Mar 27, 2026
31133d1
Playwright - wave 8: un-skip ~30 treeList/pivotGrid tests (TC API → P…
aleksei-semikozov Mar 27, 2026
47728ab
Playwright - dataGrid wave 8: +21 editing tests (events, initNewRow, …
aleksei-semikozov Mar 27, 2026
d0ffc9c
Playwright - accessibility wave 2: +107 test configurations across 21…
aleksei-semikozov Mar 27, 2026
46610a1
Playwright - cardView wave 4: +22 tests (selection, filterPanel, head…
aleksei-semikozov Mar 27, 2026
e7c475c
Playwright - dataGrid wave 9: +17 tests (scrolling, virtualColumns)
aleksei-semikozov Mar 27, 2026
f8229b9
Playwright - cardView wave 5: +23 tests (editing visual/functional, s…
aleksei-semikozov Mar 27, 2026
6989fe9
Playwright - dataGrid wave 10: +21 tests (masterDetail KB nav, virtua…
aleksei-semikozov Mar 27, 2026
493e89b
Playwright - dataGrid wave 11: +14 tests (exportButton, columnResizin…
aleksei-semikozov Mar 27, 2026
d74b065
Playwright - dataGrid wave 12: +10 tests (stickyReordering, focusOver…
aleksei-semikozov Mar 27, 2026
bb98d2c
Playwright - cardView wave 6: +24 tests (sorting keyboard, events, no…
aleksei-semikozov Mar 27, 2026
20e8ea7
Playwright - navigation: fix 24 tests (menu keyboard, scrollable visi…
aleksei-semikozov Mar 27, 2026
b69f331
Playwright - dataGrid wave 13: +14 keyboard nav tests
aleksei-semikozov Mar 27, 2026
9e37111
Playwright - dataGrid wave 14: +15 tests, fix duplicate test titles (…
aleksei-semikozov Mar 27, 2026
1a6c8da
Playwright - common: re-skip 23 wave-8 treeList/pivotGrid tests faili…
aleksei-semikozov Mar 27, 2026
4734924
Playwright - dataGrid wave 15: +17 tests (selection, scrolling, editi…
aleksei-semikozov Mar 27, 2026
a4193cf
Playwright - dataGrid wave 16: +30 tests (async validation, editing, …
aleksei-semikozov Mar 27, 2026
56af492
Playwright - fix duplicate test titles in scrolling and selection
aleksei-semikozov Mar 27, 2026
77e96a3
Playwright - dataGrid wave 17: +15 tests (keyboard nav editCellTempla…
aleksei-semikozov Mar 27, 2026
b3c9ee1
Playwright - dataGrid wave 18: +15 tests (group column reordering, KB…
aleksei-semikozov Mar 27, 2026
afad0c3
Playwright - dataGrid wave 19: +15 KB nav tests + DataGridCommandCell…
aleksei-semikozov Mar 27, 2026
b6e7390
Playwright - wave 20: +49 tests (41 accessibility configs + 8 cardVie…
aleksei-semikozov Mar 27, 2026
6e077cf
Playwright - dataGrid wave 21: +12 tests (stateStoring, pager, scroll…
aleksei-semikozov Mar 27, 2026
e81cddc
Playwright - wave 22: +50 accessibility configs (scheduler, dataGrid,…
aleksei-semikozov Mar 27, 2026
7bf6b01
Playwright - wave 23: +64 accessibility tests across 21 specs
aleksei-semikozov Mar 27, 2026
9725dce
Playwright - wave 24: +149 accessibility tests across 46 specs
aleksei-semikozov Mar 27, 2026
b23c026
Playwright - wave 25: +1335 tests (accessibility matrix generator + 1…
aleksei-semikozov Mar 27, 2026
d8bd072
Playwright - collapse viewOffset forEach: 537 → 25 tests (1:1 with Te…
aleksei-semikozov Mar 27, 2026
636eaa3
Playwright - collapse forEach: timezones 79→36, common form/customiza…
aleksei-semikozov Mar 27, 2026
5354a32
Playwright - fix viewOffset timeout, remove debug/canary files, cleanup
aleksei-semikozov Mar 27, 2026
d70c77d
Playwright - increase CI timeout to 45min, shard accessibility into 2
aleksei-semikozov Mar 27, 2026
ee50502
Playwright - html padding-right 15px to simulate TestCafe scrollbar (…
aleksei-semikozov Mar 27, 2026
6b39b6b
Revert "Playwright - html padding-right 15px to simulate TestCafe scr…
aleksei-semikozov Mar 27, 2026
261842e
Playwright - dynamic padding-right 15px only on overflow pages (simul…
aleksei-semikozov Mar 27, 2026
98685e9
Playwright - skip dynamic padding for non-1200 viewports (fixes viewO…
aleksei-semikozov Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
177 changes: 177 additions & 0 deletions .github/workflows/playwright_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
name: Playwright tests (POC)

concurrency:
group: wf-${{github.event.pull_request.number || github.sha}}-playwright
cancel-in-progress: true

on:
pull_request:
workflow_dispatch:
inputs:
repeat_count:
description: 'Number of times to run tests (for stability check)'
required: false
default: '1'
type: string

env:
NX_SKIP_NX_CACHE: ${{ contains(github.event.pull_request.labels.*.name, 'skip-cache') && 'true' || 'false' }}

jobs:
build:
name: Build DevExtreme
runs-on: devextreme-shr2
timeout-minutes: 15

steps:
- name: Get sources
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- uses: pnpm/action-setup@v4
with:
run_install: false

- name: Get pnpm store directory
shell: bash
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-cache

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build
shell: bash
env:
NODE_OPTIONS: --max-old-space-size=8192
run: |
pnpx nx build devextreme-scss
pnpx nx build devextreme -c testing

- name: Zip artifacts
working-directory: ./packages/devextreme
run: 7z a -tzip -mx3 -mmt2 artifacts.zip artifacts ../devextreme-scss/scss/bundles

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: devextreme-artifacts
path: ./packages/devextreme/artifacts.zip
retention-days: 1

playwright:
name: ${{ matrix.ARGS.name }}
needs: build
strategy:
fail-fast: false
matrix:
ARGS: [
{ componentFolder: "scheduler/common", name: "scheduler / common (1/3)", shard: "1/3" },
{ componentFolder: "scheduler/common", name: "scheduler / common (2/3)", shard: "2/3" },
{ componentFolder: "scheduler/common", name: "scheduler / common (3/3)", shard: "3/3" },
{ componentFolder: "scheduler/timezones", name: "scheduler / timezones" },
{ componentFolder: "scheduler/viewOffset", name: "scheduler / viewOffset", project: "chromium-1185" },
{ componentFolder: "dataGrid/common", name: "dataGrid / common (1/2)", shard: "1/2" },
{ componentFolder: "dataGrid/common", name: "dataGrid / common (2/2)", shard: "2/2" },
{ componentFolder: "dataGrid/sticky", name: "dataGrid / sticky" },
{ componentFolder: "common", name: "common (1/2)", shard: "1/2" },
{ componentFolder: "common", name: "common (2/2)", shard: "2/2" },
{ componentFolder: "editors", name: "editors (1/2)", shard: "1/2" },
{ componentFolder: "editors", name: "editors (2/2)", shard: "2/2" },
{ componentFolder: "navigation", name: "navigation" },
{ componentFolder: "cardView", name: "cardView" },
{ componentFolder: "accessibility", name: "accessibility (1/2)", shard: "1/2" },
{ componentFolder: "accessibility", name: "accessibility (2/2)", shard: "2/2" },
]
runs-on: devextreme-shr2
timeout-minutes: 45

steps:
- name: Get sources
uses: actions/checkout@v4

- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: devextreme-artifacts
path: ./packages/devextreme

- name: Unpack artifacts
working-directory: ./packages/devextreme
run: 7z x artifacts.zip -aoa

- uses: pnpm/action-setup@v4
with:
run_install: false

- name: Get pnpm store directory
shell: bash
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- uses: actions/cache/restore@v4
name: Restore pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-cache

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Install Playwright browsers
working-directory: ./e2e/testcafe-devextreme
run: npx playwright install chromium

- name: Run Playwright tests
working-directory: ./e2e/testcafe-devextreme
env:
NODE_OPTIONS: --max-old-space-size=8192
THEME: fluent.blue.light
run: |
REPEAT_COUNT="${{ github.event.inputs.repeat_count || '1' }}"
SHARD_ARG=""
if [ "${{ matrix.ARGS.shard }}" != "" ]; then
SHARD_ARG="--shard=${{ matrix.ARGS.shard }}"
fi
PROJECT="${{ matrix.ARGS.project || 'chromium' }}"
PROJECT_ARG="--project=$PROJECT"

set -o pipefail
for i in $(seq 1 $REPEAT_COUNT); do
echo "=== Run $i / $REPEAT_COUNT ==="
npx playwright test \
--config playwright.config.ts \
playwright-tests/${{ matrix.ARGS.componentFolder }} \
$SHARD_ARG \
$PROJECT_ARG \
--reporter=list \
2>&1 | tee -a playwright-output-run-$i.log
echo ""
done

- name: Sanitize job name
if: always()
run: echo "JOB_NAME=$(echo "${{ matrix.ARGS.name }}" | tr '/' '-' | tr ' ' '-')" >> $GITHUB_ENV

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-results-${{ env.JOB_NAME }}
path: |
e2e/testcafe-devextreme/playwright-results/
e2e/testcafe-devextreme/playwright-output-*.log
e2e/testcafe-devextreme/test-results/
if-no-files-found: ignore
80 changes: 80 additions & 0 deletions FINISH_REVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Playwright Migration — Final Review Checklist

## Goal
Every Playwright test must have a 1:1 correspondence with TestCafe:
- Same test name
- Same test count per file
- Same behavior tested

## Key Rules

### 1. forEach Tests Must Match TestCafe Structure
TestCafe allows duplicate test names inside forEach loops:
```typescript
// TestCafe: 5 iterations = 5 tests with SAME name "Usual appointments render"
[0, 735, 1440, -735, -1440].forEach((offset) => {
test('Usual appointments render', async (t) => { ... });
});
```

Playwright does NOT allow duplicate test names. Solution: **keep forEach inside ONE test**:
```typescript
// CORRECT: 1 test with 5 iterations inside (matches TC count)
test('Usual appointments render', async ({ page }) => {
for (const offset of [0, 735, 1440, -735, -1440]) {
await clearTestPage(page);
// ... test with this offset
}
});
```

**WRONG** (creates extra tests):
```typescript
// WRONG: 5 separate tests with different names
test('Usual appointments render (offset: 0)', ...)
test('Usual appointments render (offset: 735)', ...)
```

### 2. Test Names Must Be Identical
- Copy test name from TestCafe exactly
- No ticket numbers added/removed unless TC has them
- No parameterization suffixes unless TC has them

### 3. No Extra Screenshots / No Missing Screenshots
- All etalons are from TestCafe CI
- Playwright must not generate new etalons
- Playwright must not delete any etalons

### 4. Verification Steps

For each component folder:
1. Run TestCafe test names from CI: check TEST_NAMES_COMPARISON.md
2. Run `npx playwright test --list --project=chromium playwright-tests/<component>/`
3. Compare counts and names
4. If PW has more tests — check for forEach expansion (collapse them)
5. If PW has fewer — check for missing tests (add them)

### 5. CI Must Pass
- `common (1/2)` and `common (2/2)` — must be SUCCESS
- `scheduler/viewOffset` — must be SUCCESS
- Other jobs — screenshot pixel differences expected (macOS vs Ubuntu rendering)

## Known Issues

### forEach Expansion (needs collapsing)
These components have expanded forEach that need to be collapsed:
- `scheduler/viewOffset/` — TC: ~28 tests, PW: ~537 (massive expansion)
- `scheduler/timezones/` — TC: ~36 tests, PW: ~105
- `scheduler/common/` — various files with expanded forEach
- `accessibility/*.matrix.spec.ts` — matrix expansion (OK — mirrors TC testAccessibility pattern)

### Screenshot Dimension Mismatches (CI vs Local)
- TestCafe headless Chrome has 15px scrollbar, Playwright headless has 0px
- ViewOffset uses viewport 1185 (project chromium-1185) to match TC etalons
- Other components use viewport 1200 + `::-webkit-scrollbar` CSS
- Some tests fail on CI but pass locally due to font rendering differences

### Accessibility Matrix Tests
TC uses `testAccessibility()` which generates N tests per option combination at runtime.
PW uses `testAccessibilityMatrix()` helper that does the same.
These are expected to have different counts but same coverage.
Loading
Loading