Skip to content

Commit 775da04

Browse files
committed
tests(CI): configure testcafe runner and pipelines
1 parent 41e1aa9 commit 775da04

11 files changed

+246
-173
lines changed

.github/actions/run-qunit-tests/action.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ runs:
5454
if: ${{ inputs.browser == 'chrome' }}
5555
uses: ./.github/actions/setup-chrome
5656
with:
57-
chrome-version: '121.0.6167.184'
57+
chrome-version: '133.0.6943.53'
5858

5959
- name: Setup Firefox profile
6060
if: ${{ inputs.browser == 'firefox' }}

.github/actions/setup-chrome/action.yml

+3-10
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,10 @@ runs:
3131
if [ -n "$CHROME_VERSION" ]; then
3232
sudo apt-get update
3333
sudo apt-get -y install libu2f-udev
34-
35-
mkdir google-chrome-setup
36-
pushd google-chrome-setup
37-
npm init -y
38-
npm set //npm.pkg.github.com/:_authToken="${{ github.token }}"
39-
npm i @devexpress/devextreme-google-chrome-image@1.0.0 --registry=https://npm.pkg.github.com
40-
sudo dpkg -i node_modules/@devexpress/devextreme-google-chrome-image/google-chrome-stable_121.0.6167.184-1_amd64.deb
34+
curl -L "https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROME_VERSION}-1_amd64.deb" > /tmp/chrome.deb
35+
sudo dpkg -i /tmp/chrome.deb
36+
unlink /tmp/chrome.deb
4137
google-chrome-stable --version
42-
popd
43-
44-
rm -rf google-chrome-setup
4538
else
4639
echo "Skip Chrome upgrade"
4740
fi

.github/workflows/demos_visual_tests.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373

7474
runs-on: ubuntu-22.04
7575
name: ${{ matrix.CONSTEL }}-${{ matrix.STRATEGY }}-${{ matrix.THEME }}
76-
timeout-minutes: 30
76+
timeout-minutes: 180
7777

7878
steps:
7979
- name: Get sources
@@ -82,7 +82,7 @@ jobs:
8282
- name: Setup Chrome
8383
uses: ./.github/actions/setup-chrome
8484
with:
85-
chrome-version: '121.0.6167.184'
85+
chrome-version: '133.0.6943.53'
8686

8787
- name: Use Node.js
8888
uses: actions/setup-node@v4

.github/workflows/demos_visual_tests_frameworks.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ jobs:
364364
- name: Setup Chrome
365365
uses: ./.github/actions/setup-chrome
366366
with:
367-
chrome-version: '121.0.6167.184'
367+
chrome-version: '133.0.6943.53'
368368

369369
- name: Use Node.js
370370
uses: actions/setup-node@v4

.github/workflows/playgrounds_tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
- name: Setup Chrome
9393
uses: ./.github/actions/setup-chrome
9494
with:
95-
chrome-version: '121.0.6167.184'
95+
chrome-version: '133.0.6943.53'
9696

9797
- name: Use Node.js
9898
uses: actions/setup-node@v4

.github/workflows/run-testcafe-on-gh-pages.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
- name: Setup Chrome
5555
uses: ./devextreme/.github/actions/setup-chrome
5656
with:
57-
chrome-version: '121.0.6167.184'
57+
chrome-version: '133.0.6943.53'
5858

5959
- uses: pnpm/action-setup@v3
6060
with:

.github/workflows/testcafe_tests.yml

+39-29
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,13 @@ jobs:
7979
fail-fast: false
8080
matrix:
8181
ARGS: [
82-
{ componentFolder: "accessibility", name: "accessibility (1/5)", indices: "1/5" },
83-
{ componentFolder: "accessibility", name: "accessibility (2/5)", indices: "2/5" },
84-
{ componentFolder: "accessibility", name: "accessibility (3/5)", indices: "3/5" },
85-
{ componentFolder: "accessibility", name: "accessibility (4/5)", indices: "4/5" },
86-
{ componentFolder: "accessibility", name: "accessibility (5/5)", indices: "5/5" },
82+
{ componentFolder: "accessibility", name: "accessibility (1/7)", indices: "1/7" },
83+
{ componentFolder: "accessibility", name: "accessibility (2/7)", indices: "2/7" },
84+
{ componentFolder: "accessibility", name: "accessibility (3/7)", indices: "3/7" },
85+
{ componentFolder: "accessibility", name: "accessibility (4/7)", indices: "4/7" },
86+
{ componentFolder: "accessibility", name: "accessibility (5/7)", indices: "5/7" },
87+
{ componentFolder: "accessibility", name: "accessibility (6/7)", indices: "6/7" },
88+
{ componentFolder: "accessibility", name: "accessibility (7/7)", indices: "7/7" },
8789
{ componentFolder: "accessibility", name: "accessibility - material (1/7)", theme: "material.blue.light", indices: "1/7" },
8890
{ componentFolder: "accessibility", name: "accessibility - material (2/7)", theme: "material.blue.light", indices: "2/7" },
8991
{ componentFolder: "accessibility", name: "accessibility - material (3/7)", theme: "material.blue.light", indices: "3/7" },
@@ -105,35 +107,42 @@ jobs:
105107
{ componentFolder: "chat", name: "chat - material", theme: 'material.blue.light' },
106108
{ componentFolder: "chat", name: "chat - fluent", theme: 'fluent.blue.light' },
107109
{ componentFolder: "treeList", name: "treeList", concurrency: 1 },
108-
{ componentFolder: "dataGrid", name: "dataGrid (1/5)", indices: "1/5" },
109-
{ componentFolder: "dataGrid", name: "dataGrid (2/5)", indices: "2/5" },
110-
{ componentFolder: "dataGrid", name: "dataGrid (3/5)", indices: "3/5" },
111-
{ componentFolder: "dataGrid", name: "dataGrid (4/5)", indices: "4/5" },
112-
{ componentFolder: "dataGrid", name: "dataGrid (5/5)", indices: "5/5" },
110+
{ componentFolder: "dataGrid/common", name: "dataGrid / common (1/5)", indices: "1/5" },
111+
{ componentFolder: "dataGrid/common", name: "dataGrid / common (2/5)", indices: "2/5" },
112+
{ componentFolder: "dataGrid/common", name: "dataGrid / common (3/5)", indices: "3/5" },
113+
{ componentFolder: "dataGrid/common", name: "dataGrid / common (4/5)", indices: "4/5" },
114+
{ componentFolder: "dataGrid/common", name: "dataGrid / common (5/5)", indices: "5/5" },
115+
{ componentFolder: "dataGrid/stickyColumns", name: "dataGrid / sticky (1/3)", indices: "1/3" },
116+
{ componentFolder: "dataGrid/stickyColumns", name: "dataGrid / sticky (2/3)", indices: "2/3" },
117+
{ componentFolder: "dataGrid/stickyColumns", name: "dataGrid / sticky (3/3)", indices: "3/3" },
113118
{ componentFolder: "pivotGrid", name: "pivotGrid", concurrency: 1 },
114119
{ componentFolder: "pivotGrid", name: "pivotGrid - material", theme: 'material.blue.light', concurrency: 1 },
115120
{ componentFolder: "pivotGrid", name: "pivotGrid - fluent", theme: 'fluent.blue.light', concurrency: 1 },
116-
{ componentFolder: "scheduler", name: "scheduler (1/5)", indices: "1/5" },
117-
{ componentFolder: "scheduler", name: "scheduler (2/5)", indices: "2/5" },
118-
{ componentFolder: "scheduler", name: "scheduler (3/5)", indices: "3/5" },
119-
{ componentFolder: "scheduler", name: "scheduler (4/5)", indices: "4/5" },
120-
{ componentFolder: "scheduler", name: "scheduler (5/5)", indices: "5/5" },
121-
{ componentFolder: "scheduler/timezones", name: "scheduler (Europe/Berlin)", timezone: "Europe/Berlin" },
122-
{ componentFolder: "scheduler/timezones", name: "scheduler (America/Los_Angeles)", timezone: "America/Los_Angeles" },
121+
{ componentFolder: "scheduler/common", name: "scheduler / common (1/6)", indices: "1/6" },
122+
{ componentFolder: "scheduler/common", name: "scheduler / common (2/6)", indices: "2/6" },
123+
{ componentFolder: "scheduler/common", name: "scheduler / common (3/6)", indices: "3/6" },
124+
{ componentFolder: "scheduler/common", name: "scheduler / common (4/6)", indices: "4/6" },
125+
{ componentFolder: "scheduler/common", name: "scheduler / common (5/6)", indices: "5/6" },
126+
{ componentFolder: "scheduler/common", name: "scheduler / common (6/6)", indices: "6/6" },
127+
{ componentFolder: "scheduler/viewOffset/common", name: "scheduler / offset" },
128+
{ componentFolder: "scheduler/viewOffset/markup", name: "scheduler / offset markups" },
129+
{ componentFolder: "scheduler/timezones", name: "scheduler / timezones (Europe/Berlin)", timezone: "Europe/Berlin" },
130+
{ componentFolder: "scheduler/timezones", name: "scheduler / timezones (America/Los_Angeles)", timezone: "America/Los_Angeles" },
123131
{ componentFolder: "form", name: "form (1/2)", indices: "1/2" },
124132
{ componentFolder: "form", name: "form (2/2)", indices: "2/2" },
125-
{ componentFolder: "form", name: "form - material (1/4)", theme: 'material.blue.light', indices: "1/4" },
126-
{ componentFolder: "form", name: "form - material (2/4)", theme: 'material.blue.light', indices: "2/4" },
127-
{ componentFolder: "form", name: "form - material (3/4)", theme: 'material.blue.light', indices: "3/4" },
128-
{ componentFolder: "form", name: "form - material (4/4)", theme: 'material.blue.light', indices: "4/4" },
133+
{ componentFolder: "form", name: "form - material (1/2)", theme: 'material.blue.light', indices: "1/2" },
134+
{ componentFolder: "form", name: "form - material (2/2)", theme: 'material.blue.light', indices: "2/2" },
129135
{ componentFolder: "form", name: "form - fluent (1/2)", theme: 'fluent.blue.light', indices: "1/2" },
130136
{ componentFolder: "form", name: "form - fluent (2/2)", theme: 'fluent.blue.light', indices: "2/2" },
131-
{ componentFolder: "editors", name: "editors (1/2)", indices: "1/2" },
132-
{ componentFolder: "editors", name: "editors (2/2)", indices: "2/2" },
133-
{ componentFolder: "editors", name: "editors - material (1/2)", theme: 'material.blue.light', indices: "1/2" },
134-
{ componentFolder: "editors", name: "editors - material (2/2)", theme: 'material.blue.light', indices: "2/2" },
135-
{ componentFolder: "editors", name: "editors - fluent (1/2)", theme: 'fluent.blue.light', indices: "1/2" },
136-
{ componentFolder: "editors", name: "editors - fluent (2/2)", theme: 'fluent.blue.light', indices: "2/2" },
137+
{ componentFolder: "editors", name: "editors (1/3)", indices: "1/3" },
138+
{ componentFolder: "editors", name: "editors (2/3)", indices: "2/3" },
139+
{ componentFolder: "editors", name: "editors (3/3)", indices: "3/3" },
140+
{ componentFolder: "editors", name: "editors - material (1/3)", indices: "1/3", theme: 'material.blue.light' },
141+
{ componentFolder: "editors", name: "editors - material (2/3)", indices: "2/3", theme: 'material.blue.light' },
142+
{ componentFolder: "editors", name: "editors - material (3/3)", indices: "3/3", theme: 'material.blue.light' },
143+
{ componentFolder: "editors", name: "editors - fluent (1/3)", indices: "1/3", theme: 'fluent.blue.light' },
144+
{ componentFolder: "editors", name: "editors - fluent (2/3)", indices: "2/3", theme: 'fluent.blue.light' },
145+
{ componentFolder: "editors", name: "editors - fluent (3/3)", indices: "3/3", theme: 'fluent.blue.light' },
137146
{ componentFolder: "htmlEditor", name: "htmlEditor", concurrency: 1 },
138147
{ componentFolder: "htmlEditor", name: "htmlEditor - material", theme: 'material.blue.light', concurrency: 1 },
139148
{ componentFolder: "htmlEditor", name: "htmlEditor - fluent", theme: 'fluent.blue.light', concurrency: 1 },
@@ -147,7 +156,8 @@ jobs:
147156
{ componentFolder: "filterBuilder", name: "filterBuilder - material", theme: 'material.blue.light' },
148157
{ componentFolder: "filterBuilder", name: "filterBuilder - fluent", theme: 'fluent.blue.light' },
149158
{ componentFolder: "pagination", name: "pagination" },
150-
{ componentFolder: "pagination", name: "pagination - material", theme: 'material.blue.light' },
159+
# TODO Chrome133: skipped during chrome update
160+
# { componentFolder: "pagination", name: "pagination - material", theme: 'material.blue.light' },
151161
{ componentFolder: "pagination", name: "pagination - fluent", theme: 'fluent.blue.light' },
152162
{ componentFolder: "gantt", name: "gantt" },
153163
]
@@ -176,7 +186,7 @@ jobs:
176186
- name: Setup Chrome
177187
uses: ./.github/actions/setup-chrome
178188
with:
179-
chrome-version: '121.0.6167.184'
189+
chrome-version: '133.0.6943.53'
180190

181191
- name: Use Node.js
182192
uses: actions/setup-node@v4

.github/workflows/wrapper_tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Setup Chrome
2525
uses: ./.github/actions/setup-chrome
2626
with:
27-
chrome-version: '121.0.6167.184'
27+
chrome-version: '133.0.6943.53'
2828

2929
- name: Use Node.js
3030
uses: actions/setup-node@v4

e2e/testcafe-devextreme/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"devextreme": "workspace:~",
1515
"devextreme-screenshot-comparer": "2.0.17",
1616
"devextreme-testcafe-models": "workspace:*",
17+
"glob": "10.4.5",
1718
"minimist": "1.2.8",
1819
"mockdate": "3.0.5",
1920
"nconf": "0.12.1",

e2e/testcafe-devextreme/runner.js

+42-17
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ const createTestCafe = require('testcafe');
55
const fs = require('fs');
66
const process = require('process');
77
const parseArgs = require('minimist');
8+
const { globSync } = require('glob');
89
const testPageUtils = require('./helpers/clearPage');
910
require('nconf').argv();
1011

11-
const changeTheme = async(themeName) => createTestCafe.ClientFunction(() => new Promise((resolve) => {
12+
const changeTheme = async(t, themeName) => createTestCafe.ClientFunction(() => new Promise((resolve) => {
1213
// eslint-disable-next-line no-undef
1314
window.DevExpress.ui.themes.ready(resolve);
1415
// eslint-disable-next-line no-undef
1516
window.DevExpress.ui.themes.current(themeName);
1617
}),
17-
{ dependencies: { themeName } })();
18+
{ dependencies: { themeName } }).with({ boundTestRun: t })();
1819

19-
const addShadowRootTree = async function() {
20+
const addShadowRootTree = async(t) => {
2021
await createTestCafe.ClientFunction(() => {
2122
const root = document.querySelector('#parentContainer');
2223
const childNodes = root.childNodes;
@@ -29,7 +30,7 @@ const addShadowRootTree = async function() {
2930
shadowContainer.append.apply(shadowContainer, Array.from(childNodes));
3031

3132
root.shadowRoot.appendChild(shadowContainer);
32-
})();
33+
}).with({ boundTestRun: t })();
3334
};
3435

3536
let testCafe;
@@ -62,8 +63,8 @@ createTestCafe({
6263
const browsers = args.browsers
6364
.split(' ')
6465
.map((browser) => expandBrowserAlias(browser, args.componentFolder.trim()));
65-
// eslint-disable-next-line no-console
66-
console.log('Browsers:', browsers);
66+
67+
console.info('Browsers:', browsers);
6768

6869
const runner = testCafe.createRunner()
6970
.browsers(browsers)
@@ -78,17 +79,38 @@ createTestCafe({
7879

7980
runner.concurrency(args.concurrency || 3);
8081

82+
const split = (array, chunkCount) => {
83+
const fixturesInChunkCount = Math.ceil(array.length / chunkCount);
84+
const [...arr] = array;
85+
const res = [];
86+
87+
while(arr.length) {
88+
res.push(arr.splice(0, fixturesInChunkCount));
89+
}
90+
91+
return res;
92+
};
93+
8194
const filters = [];
95+
8296
if(indices) {
8397
const [current, total] = indices.split(/_|of|\\|\//ig).map(x => +x);
84-
let testIndex = 0;
85-
filters.push(() => {
86-
const result = (testIndex % total) === (current - 1);
87-
testIndex += 1;
88-
return result;
89-
98+
const fixtures = globSync([`./tests/${componentFolder}/*.ts`]);
99+
const fixtureChunks = split(fixtures, total);
100+
const targetFixtureChunk = fixtureChunks[current - 1] ?? [];
101+
102+
console.info(' === test run config ===');
103+
console.info(` > indices: current = ${current} | total = ${total}`);
104+
console.info(' > glob: ', [`./tests/${componentFolder}/*.ts`]);
105+
console.info(' > all fixtures: ', fixtureChunks);
106+
console.info(' > fixtures: ', targetFixtureChunk, '\n');
107+
108+
filters.push((testName, fixtureName, fixturePath) => {
109+
// TODO: improve performance
110+
return targetFixtureChunk.some((path) => fixturePath.includes(path));
90111
});
91112
}
113+
92114
if(testName) {
93115
filters.push(name => name === testName);
94116
}
@@ -112,18 +134,21 @@ createTestCafe({
112134
}
113135

114136
const runOptions = {
115-
quarantineMode: { successThreshold: 1, attemptLimit: 5 },
137+
quarantineMode: { successThreshold: 1, attemptLimit: 10 },
116138
};
117139

118140
runOptions.hooks = {
119141
test: {
120-
before: async() => {
142+
before: async(t) => {
143+
// TODO: Move to a single const (look at restoreBrowserSize helper module)
144+
await t.resizeWindow(1200, 800);
145+
121146
if(args.shadowDom) {
122-
await addShadowRootTree();
147+
await addShadowRootTree(t);
123148
}
124149

125150
if(args.theme) {
126-
await changeTheme(args.theme);
151+
await changeTheme(t, args.theme);
127152
}
128153
},
129154
after: async() => {
@@ -158,7 +183,7 @@ function setShadowDom(args) {
158183
function expandBrowserAlias(browser, componentFolder) {
159184
switch(browser) {
160185
case 'chrome:devextreme-shr2':
161-
return 'chrome:headless --disable-gpu --window-size=1200,800';
186+
return 'chrome:headless --no-sandbox --disable-gpu --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';
162187
case 'chrome:docker':
163188
return 'chromium:headless --no-sandbox --disable-gpu --window-size=1200,800';
164189
}

0 commit comments

Comments
 (0)