Skip to content

Commit 00c525d

Browse files
Merge branch '25_2' into 25_2_demos_vue_ts_scheduler
2 parents ae8e4e8 + 0c417f3 commit 00c525d

File tree

364 files changed

+3201
-1285
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

364 files changed

+3201
-1285
lines changed

apps/demos/utils/visual-tests/matrix-test-helper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ const SKIPPED_TESTS = {
241241
FileUploader: ['CustomDropzone']
242242
},
243243
React: {
244+
Common: ['PopupAndNotificationsOverview'],
244245
Scheduler: [
245246
{ demo: 'ContextMenu', themes: [THEME.fluent] },
246247
],

e2e/testcafe-devextreme/helpers/clearPage.js

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable spellcheck/spell-checker */
2+
import { ClientFunction } from 'testcafe';
3+
import {
4+
removeStylesheetRulesFromPage,
5+
} from './domUtils';
6+
7+
export async function clearTestPage(testController: TestController): Promise<void> {
8+
const shadowDom = process.env.shadowDom === 'true';
9+
10+
const clearTestPageFn = ClientFunction(() => {
11+
const widgetSelector = '.dx-widget';
12+
const $elements = $(widgetSelector)
13+
.filter((_, element) => $(element).parents(widgetSelector).length === 0);
14+
$elements.each((_, element) => {
15+
const $widgetElement = $(element);
16+
const widgetNames = $widgetElement.data().dxComponents;
17+
widgetNames?.forEach((name) => {
18+
if ($widgetElement.hasClass('dx-widget')) {
19+
// @ts-expect-error ts-erroe
20+
$widgetElement[name]?.('dispose');
21+
}
22+
});
23+
$widgetElement.empty();
24+
});
25+
26+
const body = document.querySelector('body');
27+
if (body) {
28+
body.innerHTML = '';
29+
30+
body.className = 'dx-surface';
31+
}
32+
33+
const temp = document.createElement('div');
34+
temp.innerHTML = `
35+
<div id="parentContainer" role="main">
36+
<h1 style="position: fixed; left: 0; top: 0; clip: rect(1px, 1px, 1px, 1px);">Test header</h1>
37+
<div id="container"></div>
38+
<div id="otherContainer"></div>
39+
</div>
40+
`;
41+
42+
body?.prepend(temp.firstElementChild!);
43+
}, {
44+
dependencies: {
45+
shadowDom,
46+
},
47+
});
48+
49+
await clearTestPageFn.with({ boundTestRun: testController })();
50+
await removeStylesheetRulesFromPage.with({ boundTestRun: testController })();
51+
}
52+
53+
export async function loadAxeCore(t: TestController): Promise<void> {
54+
await t.eval(() => new Promise<void>((resolve, reject) => {
55+
// @ts-expect-error ts-error
56+
if (window.axe) {
57+
resolve();
58+
return;
59+
}
60+
61+
const script = document.createElement('script');
62+
script.src = '../../../node_modules/axe-core/axe.min.js';
63+
// @ts-expect-error ts-error
64+
script.onload = resolve;
65+
script.onerror = reject;
66+
document.head.appendChild(script);
67+
}));
68+
}

e2e/testcafe-devextreme/runner.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
/* eslint-disable spellcheck/spell-checker */
12
import createTestCafe, { ClientFunction } from 'testcafe';
23
import * as fs from 'fs';
34
import * as process from 'process';
45
import parseArgs from 'minimist';
56
import { globSync } from 'glob';
67
import { DEFAULT_BROWSER_SIZE } from './helpers/const';
7-
import * as testPageUtils from './helpers/clearPage';
8+
import {
9+
clearTestPage,
10+
loadAxeCore,
11+
} from './helpers/testPageUtils';
812
import 'nconf';
913

1014
interface ParsedArgs {
@@ -251,8 +255,20 @@ createTestCafe(TESTCAFE_CONFIG)
251255
test: {
252256
before: async (t: TestController) => {
253257
if (!componentFolder.includes('accessibility')) {
258+
await ClientFunction(() => {
259+
if (document.activeElement && document.activeElement !== document.body) {
260+
(document.activeElement as HTMLElement).blur();
261+
}
262+
263+
window.getSelection()?.removeAllRanges();
264+
}).with({ boundTestRun: t })();
265+
266+
await t.hover('html');
267+
254268
const [width, height] = DEFAULT_BROWSER_SIZE;
255269
await t.resizeWindow(width, height);
270+
} else {
271+
await loadAxeCore(t);
256272
}
257273

258274
if (args.shadowDom) {
@@ -269,7 +285,7 @@ createTestCafe(TESTCAFE_CONFIG)
269285
}
270286
},
271287
after: async (t: TestController) => {
272-
await testPageUtils.clearTestPage(t);
288+
await clearTestPage(t);
273289
},
274290
},
275291
},
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import CardView from 'devextreme-testcafe-models/cardView';
2+
import url from '../../../helpers/getPageUrl';
3+
import { createWidget } from '../../../helpers/createWidget';
4+
import { a11yCheck } from '../../../helpers/accessibility/utils';
5+
6+
fixture.disablePageReloads`CardView - ColumnChooser`
7+
.page(url(__dirname, '../../container.html'));
8+
9+
const CARD_VIEW_SELECTOR = '#container';
10+
11+
test('column chooser in \'select\' mode', async (t) => {
12+
const cardView = new CardView(CARD_VIEW_SELECTOR);
13+
14+
await cardView.apiShowColumnChooser();
15+
16+
await a11yCheck(t, {}, CARD_VIEW_SELECTOR);
17+
}).before(async () => createWidget('dxCardView', {
18+
columnChooser: {
19+
enabled: true,
20+
mode: 'select',
21+
height: 400,
22+
width: 400,
23+
search: {
24+
enabled: true,
25+
},
26+
selection: {
27+
allowSelectAll: true,
28+
},
29+
},
30+
columns: [
31+
{ dataField: 'Column 1', visible: false },
32+
{ dataField: 'Column 2', allowHiding: false },
33+
{ dataField: 'Column 3', showInColumnChooser: false },
34+
{ dataField: 'Column 4' },
35+
],
36+
}));
37+
38+
test('column chooser in \'dragAndDrop\' mode', async (t) => {
39+
const cardView = new CardView(CARD_VIEW_SELECTOR);
40+
41+
await cardView.apiShowColumnChooser();
42+
43+
const a11yCheckConfig = {
44+
rules: { 'color-contrast': { enabled: false } },
45+
};
46+
await a11yCheck(t, a11yCheckConfig, CARD_VIEW_SELECTOR);
47+
}).before(async () => createWidget('dxCardView', {
48+
columnChooser: {
49+
enabled: true,
50+
mode: 'dragAndDrop',
51+
height: 400,
52+
width: 400,
53+
search: {
54+
enabled: true,
55+
},
56+
},
57+
columns: [
58+
{ dataField: 'Column 1', visible: false },
59+
{ dataField: 'Column 2', visible: false, allowHiding: false },
60+
{ dataField: 'Column 3', visible: false, showInColumnChooser: false },
61+
{ dataField: 'Column 4', visible: false },
62+
],
63+
}));
64+
65+
test('cardView with opened columnChooser', async (t) => {
66+
const cardView = new CardView(CARD_VIEW_SELECTOR);
67+
68+
await cardView.apiShowColumnChooser();
69+
70+
await a11yCheck(t, {}, CARD_VIEW_SELECTOR);
71+
}).before(async () => createWidget('dxCardView', {
72+
dataSource: Array.from({ length: 50 }, (_, i) => ({ value: `value_${i}` })),
73+
columnChooser: {
74+
enabled: true,
75+
},
76+
columns: [
77+
{ dataField: 'value' },
78+
],
79+
}));
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import CardView from 'devextreme-testcafe-models/cardView';
2+
import { createWidget } from '../../../helpers/createWidget';
3+
import url from '../../../helpers/getPageUrl';
4+
import { getColumnItem, triggerDragEnd, triggerDragStart } from '../../cardView/columnSortable/utils';
5+
import { a11yCheck } from '../../../helpers/accessibility/utils';
6+
7+
fixture.disablePageReloads`CardView - ColumnSortable`
8+
.page(url(__dirname, '../../container.html'));
9+
10+
const CARD_VIEW_SELECTOR = '#container';
11+
12+
test('headerPanel dragging column when it has sorting and headerFilter', async (t) => {
13+
const cardView = new CardView(CARD_VIEW_SELECTOR);
14+
const columnElement = cardView.getHeaders().getHeaderItemNth(0).element;
15+
16+
await triggerDragStart(columnElement);
17+
18+
const a11yCheckConfig = {
19+
rules: { 'color-contrast': { enabled: false } },
20+
};
21+
await a11yCheck(t, a11yCheckConfig, CARD_VIEW_SELECTOR);
22+
}).before(async () => createWidget('dxCardView', {
23+
allowColumnReordering: true,
24+
columnChooser: {
25+
enabled: true,
26+
},
27+
headerFilter: {
28+
visible: true,
29+
},
30+
columns: [{
31+
dataField: 'test',
32+
allowReordering: true,
33+
sortOrder: 'asc',
34+
}],
35+
}));
36+
37+
test('dropzone appear in headerPanel when drag from columnChooser a column', async (t) => {
38+
const cardView = new CardView(CARD_VIEW_SELECTOR);
39+
const columnElement = getColumnItem(cardView, 0, 'columnChooser');
40+
41+
await cardView.apiShowColumnChooser();
42+
43+
await triggerDragStart(columnElement);
44+
await t.wait(500); // wait for dropzone animation to finish
45+
46+
await triggerDragEnd(columnElement);
47+
await t.wait(500); // wait for dropzone animation to finish
48+
49+
const a11yCheckConfig = {
50+
rules: { 'color-contrast': { enabled: false } },
51+
};
52+
await a11yCheck(t, a11yCheckConfig, CARD_VIEW_SELECTOR);
53+
}).before(async () => createWidget('dxCardView', {
54+
allowColumnReordering: true,
55+
columnChooser: {
56+
enabled: true,
57+
},
58+
height: 600,
59+
columns: [
60+
{ dataField: 'Column 1', visible: false },
61+
],
62+
}));
63+
64+
test('dropzone appears in headerPanel when drag from columnChooser a column with allowReordering: false', async (t) => {
65+
const cardView = new CardView(CARD_VIEW_SELECTOR);
66+
const columnElement = getColumnItem(cardView, 0, 'columnChooser');
67+
68+
await cardView.apiShowColumnChooser();
69+
70+
await triggerDragStart(columnElement);
71+
await t.wait(500); // wait for dropzone animation to finish
72+
73+
await triggerDragEnd(columnElement);
74+
await t.wait(500); // wait for dropzone animation to finish
75+
76+
await a11yCheck(t, {}, CARD_VIEW_SELECTOR);
77+
}).before(async () => createWidget('dxCardView', {
78+
allowColumnReordering: true,
79+
columnChooser: {
80+
enabled: true,
81+
},
82+
height: 600,
83+
columns: [
84+
{ dataField: 'Column 1' },
85+
{ dataField: 'Column 2', visible: false, allowReordering: false },
86+
],
87+
}));
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import url from '../../../helpers/getPageUrl';
2+
import { createWidget } from '../../../helpers/createWidget';
3+
import { a11yCheck } from '../../../helpers/accessibility/utils';
4+
5+
fixture.disablePageReloads`CardView - Cover`
6+
.page(url(__dirname, '../container.html'));
7+
8+
const CARD_VIEW_SELECTOR = '#container';
9+
10+
test('default render', async (t) => {
11+
await a11yCheck(t, {}, CARD_VIEW_SELECTOR);
12+
}).before(async () => createWidget('dxCardView', {
13+
width: 1000,
14+
height: 600,
15+
columns: ['Customer', 'Order Date'],
16+
cardCover: {
17+
imageExpr: (data) => data.Picture && `https://js.devexpress.com/jQuery/Demos/WidgetsGallery/JSDemos/${data.Picture}`,
18+
altExpr: 'FirstName',
19+
},
20+
dataSource: [{
21+
ID: 1,
22+
FirstName: 'John',
23+
LastName: 'Heart',
24+
Prefix: 'Mr.',
25+
Position: 'CEO',
26+
Picture: 'images/employees/01.png',
27+
BirthDate: '1964/03/16',
28+
HireDate: '1995/01/15',
29+
Notes: 'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003. When not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.',
30+
Address: '351 S Hill St.',
31+
}, {
32+
ID: 2,
33+
FirstName: 'Olivia',
34+
LastName: 'Peyton',
35+
Prefix: 'Mrs.',
36+
Position: 'Sales Assistant',
37+
BirthDate: '1981/06/03',
38+
HireDate: '2012/05/14',
39+
Notes: 'Olivia loves to sell. She has been selling DevAV products since 2012. Olivia was homecoming queen in high school. She is expecting her first child in 6 months. Good Luck Olivia.',
40+
Address: '807 W Paseo Del Mar',
41+
}, {
42+
ID: 3,
43+
FirstName: 'Robert',
44+
LastName: 'Reagan',
45+
Prefix: 'Mr.',
46+
Position: 'CMO',
47+
Picture: 'images/employees/03.png',
48+
BirthDate: '1974/09/07',
49+
HireDate: '2002/11/08',
50+
Notes: 'Robert was recently voted the CMO of the year by CMO Magazine. He is a proud member of the DevAV Management Team. Robert is a championship BBQ chef, so when you get the chance ask him for his secret recipe.',
51+
Address: '4 Westmoreland Pl.',
52+
}],
53+
}));

0 commit comments

Comments
 (0)