Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
59df683
CI: test stability of tests
EugeniyKiyashko Jun 11, 2026
373887f
fix tests
EugeniyKiyashko Jun 12, 2026
a2e66bf
fix qunit tests
EugeniyKiyashko Jun 12, 2026
7806d26
update
EugeniyKiyashko Jun 15, 2026
3dd3742
update
EugeniyKiyashko Jun 15, 2026
4f437db
update
EugeniyKiyashko Jun 15, 2026
1e8296a
skip 3 tests
EugeniyKiyashko Jun 16, 2026
cad3874
fix
EugeniyKiyashko Jun 17, 2026
470ddab
fix
EugeniyKiyashko Jun 18, 2026
c945b97
fix
EugeniyKiyashko Jun 18, 2026
2685b9c
fix
EugeniyKiyashko Jun 18, 2026
5dd3b3f
skip
EugeniyKiyashko Jun 19, 2026
13d133a
CI: test stability of tests
EugeniyKiyashko Jun 11, 2026
5565b8f
fix tests
EugeniyKiyashko Jun 12, 2026
3d251f8
fix qunit tests
EugeniyKiyashko Jun 12, 2026
ba4baad
update
EugeniyKiyashko Jun 15, 2026
1dca080
update
EugeniyKiyashko Jun 15, 2026
eee016d
update
EugeniyKiyashko Jun 15, 2026
5eb1546
skip 3 tests
EugeniyKiyashko Jun 16, 2026
0cbfa9f
fix
EugeniyKiyashko Jun 17, 2026
856460c
fix
EugeniyKiyashko Jun 18, 2026
f0ba3b7
fix
EugeniyKiyashko Jun 18, 2026
c3604b0
fix
EugeniyKiyashko Jun 18, 2026
e4df2ad
skip
EugeniyKiyashko Jun 19, 2026
9e9f504
Merge branch '26_1_improve_unstable_workflow' of https://github.com/E…
EugeniyKiyashko Jun 19, 2026
7aab943
skip
EugeniyKiyashko Jun 19, 2026
e28ae21
Merge branch '26_1' into 26_1_improve_unstable_workflow
EugeniyKiyashko Jun 19, 2026
57faab1
skip
EugeniyKiyashko Jun 22, 2026
b250500
fix
EugeniyKiyashko Jun 22, 2026
bbf87eb
skip
EugeniyKiyashko Jun 22, 2026
70d08c4
skip
EugeniyKiyashko Jun 22, 2026
0b2ffd4
retry unstable
EugeniyKiyashko Jun 22, 2026
ce9b163
Merge branch '26_1' into 26_1_improve_unstable_workflow
EugeniyKiyashko Jun 22, 2026
04b832e
skip unstable
EugeniyKiyashko Jun 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run-testcafe-on-gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
working-directory: devextreme/apps/demos
env:
CHANGEDFILEINFOSPATH: changed-files.json
BROWSERS: chrome:headless --window-size=1200,800 --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl="swiftshader" --disable-features=PaintHolding --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning
BROWSERS: chrome:headless --window-size=1200,800 --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl="swiftshader" --disable-features=PaintHolding,KeyboardFocusableScrollers --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning
#DEBUG: hammerhead:*,testcafe:*
CONCURRENCY: 4
TCQUARANTINE: true
Expand Down
95 changes: 93 additions & 2 deletions .github/workflows/testcafe_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ jobs:
if: ${{ !matrix.ARGS.styleDependent || needs.check-should-run.outputs.styles-changed == 'true' }}
env:
NODE_OPTIONS: --max-old-space-size=8192
RUN_LABEL: ${{ matrix.ARGS.name }}
run: |
if [ "${{ matrix.ARGS.theme }}" != "" ]; then
THEME="--theme ${{ matrix.ARGS.theme }}"
Expand All @@ -203,7 +204,12 @@ jobs:
[ "${{ matrix.ARGS.concurrency }}" != "" ] && CONCURRENCY="--concurrency ${{ matrix.ARGS.concurrency }}"
[ "${{ matrix.ARGS.platform }}" != "" ] && PLATFORM="--platform ${{ matrix.ARGS.platform }}"
[ "${{ matrix.ARGS.cache }}" == "true" ] && CACHE="--cache true"
all_args="--browsers=chrome:devextreme-shr2 --componentFolder ${{ matrix.ARGS.componentFolder }} $CONCURRENCY $INDICES $PLATFORM $THEME $CACHE"
TZVAL="${{ matrix.ARGS.timezone }}"
[ -z "$TZVAL" ] && TZVAL="GMT"
# A job stays green if it has no more than --deferThreshold failures:
# those tests are recorded and handed to the dedicated "retry-unstable"
# job. More failures than that fail the job as a real regression.
all_args="--browsers=chrome:devextreme-shr2 --componentFolder ${{ matrix.ARGS.componentFolder }} $CONCURRENCY $INDICES $PLATFORM $THEME $CACHE --deferThreshold 3 --timezone $TZVAL"
echo "$all_args"
pnpm run test $all_args

Expand All @@ -227,6 +233,91 @@ jobs:
path: ${{ github.workspace }}/e2e/testcafe-devextreme/artifacts/failedtests/**/*
if-no-files-found: ignore

- name: Upload failed test list
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: failed-list-${{ env.JOB_NAME }}
path: ${{ github.workspace }}/e2e/testcafe-devextreme/artifacts/failed-tests/**/*
if-no-files-found: ignore

retry-unstable:
name: Retry unstable tests
runs-on: devextreme-shr2
needs: [check-should-run, build, testcafe]
if: ${{ always() && needs.check-should-run.outputs.should-run == 'true' }}
timeout-minutes: 30

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

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

- name: Download failed test lists
uses: actions/download-artifact@v8
continue-on-error: true
with:
path: ${{ github.workspace }}/e2e/testcafe-devextreme/failed-lists
pattern: failed-list-*

- name: Decide retry strategy
id: decide
working-directory: ./e2e/testcafe-devextreme
run: node retry-unstable.mjs --mode decide --dir ./failed-lists --out ./retry-plan.json

- uses: pnpm/action-setup@v6
if: ${{ steps.decide.outputs.action == 'retry' }}
with:
run_install: false

- name: Get pnpm store directory
if: ${{ steps.decide.outputs.action == 'retry' }}
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- uses: actions/cache/restore@v5
if: ${{ steps.decide.outputs.action == 'retry' }}
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
if: ${{ steps.decide.outputs.action == 'retry' }}
run: pnpm install --frozen-lockfile

- name: Download build artifacts
if: ${{ steps.decide.outputs.action == 'retry' }}
uses: actions/download-artifact@v8
with:
name: devextreme-artifacts
path: ./packages/devextreme

- name: Unpack build artifacts
if: ${{ steps.decide.outputs.action == 'retry' }}
working-directory: ./packages/devextreme
run: 7z x artifacts.zip -aoa

- name: Setup Chrome
if: ${{ steps.decide.outputs.action == 'retry' }}
uses: ./.github/actions/setup-chrome
with:
chrome-version: '149.0.7827.114'

- name: Retry potentially-unstable tests
if: ${{ steps.decide.outputs.action == 'retry' }}
working-directory: ./e2e/testcafe-devextreme
env:
NODE_OPTIONS: --max-old-space-size=8192
run: node retry-unstable.mjs --mode retry --out ./retry-plan.json --attempts 2

merge-artifacts:
runs-on: devextreme-shr2
needs: testcafe
Expand All @@ -252,7 +343,7 @@ jobs:
notify:
runs-on: devextreme-shr2
name: Send notifications
needs: [build, testcafe]
needs: [build, testcafe, retry-unstable]
if: github.event_name != 'pull_request' && contains(needs.*.result, 'failure')

steps:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/visual-tests-demos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ jobs:
- name: Set Chrome flags
id: chrome-flags
run: |
BASE_FLAGS="chrome:headless --window-size=1200,800 --disable-gpu --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding --js-flags=--random-seed=2147483647"
BASE_FLAGS="chrome:headless --window-size=1200,800 --disable-gpu --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding,KeyboardFocusableScrollers --js-flags=--random-seed=2147483647"

# For Material theme, enable better font rendering to avoid instability
if [[ "${{ matrix.THEME }}" != *"material"* ]]; then
Expand Down Expand Up @@ -902,7 +902,7 @@ jobs:
working-directory: apps/demos
env:
NODE_OPTIONS: --max-old-space-size=8192
BROWSERS: chrome:headless --window-size=1200,800 --disable-gpu --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning
BROWSERS: chrome:headless --window-size=1200,800 --disable-gpu --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding,KeyboardFocusableScrollers --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning
# DEBUG: hammerhead:*,testcafe:*
CONCURRENCY: ${{ steps.set-concurrency.outputs.concurrency }}
TCQUARANTINE: true
Expand Down Expand Up @@ -1029,7 +1029,7 @@ jobs:
working-directory: apps/demos
env:
CHANGEDFILEINFOSPATH: changed-files.json
BROWSERS: chrome:headless --window-size=1200,800 --disable-gpu --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning
BROWSERS: chrome:headless --window-size=1200,800 --disable-gpu --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding,KeyboardFocusableScrollers --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning
# DEBUG: hammerhead:*,testcafe:*
CONCURRENCY: 1
TCQUARANTINE: true
Expand Down
4 changes: 2 additions & 2 deletions apps/demos/utils/visual-tests/testcafe-runner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import createTestCafe, { ClientFunction } from 'testcafe';
import fs from 'fs';

const LAUNCH_RETRY_ATTEMPTS = 3;
const LAUNCH_RETRY_ATTEMPTS = 0;
const LAUNCH_RETRY_TIMEOUT = 10000;

const wait = async (
Expand Down Expand Up @@ -96,7 +96,7 @@ async function main() {

const failedCount = await retry(() => runner
.reporter(reporters)
.browsers(process.env.BROWSERS || 'chrome --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning')
.browsers(process.env.BROWSERS || 'chrome --no-sandbox --disable-dev-shm-usage --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl=swiftshader --disable-features=PaintHolding,KeyboardFocusableScrollers --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning')
.concurrency(concurrency || 1)
.run({
quarantineMode: getQuarantineMode(),
Expand Down
6 changes: 3 additions & 3 deletions e2e/testcafe-devextreme/helpers/domUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ export const addFocusableElementBefore = ClientFunction((
return button.id;
});

export const hasHorizontalScroll = ClientFunction((selector) => {
const element = selector();
export const hasHorizontalScroll = ClientFunction((containerSelector) => {
const container = containerSelector();

return element.scrollWidth > element.clientWidth;
return container.scrollWidth > container.clientWidth;
});
Loading
Loading