Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
10 changes: 5 additions & 5 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 = async (container: Selector): Promise<boolean> => {
const scrollWidth = await container.scrollWidth;
const clientWidth = await container.clientWidth;
return scrollWidth > clientWidth;
};
export const hasHorizontalScroll = ClientFunction((containerSelector) => {
const container = containerSelector();

return container.scrollWidth > container.clientWidth;
});
4 changes: 2 additions & 2 deletions e2e/testcafe-devextreme/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getCurrentTheme } from './helpers/themeUtils';

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

const wait = async (
timeout: number,
Expand Down Expand Up @@ -89,7 +89,7 @@ function setShadowDom(args: ParsedArgs): void {
function expandBrowserAlias(browser: string): string {
switch (browser) {
case 'chrome:devextreme-shr2':
return 'chrome:headless --no-sandbox --disable-dev-shm-usage --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';
return 'chrome:headless --no-sandbox --disable-dev-shm-usage --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,KeyboardFocusableScrollers --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning';
case 'chrome:docker':
return 'chromium:headless --no-sandbox --disable-gpu --window-size=1200,800';
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,12 @@ test('Accessibility: Scrollable should have focusable element when navigate out

test('Accessibility: Scrollable should have focusable when fixed on the right side columns are focused', async (t) => {
const dataGrid = new DataGrid('#container');
const targetCell = dataGrid.getFixedDataCell(0, COLUMNS_LENGTH - 1);

// focus through headers
await pressKey(t, 'tab', COLUMNS_LENGTH);

// focus through data row till last cell (which is fixed)
await pressKey(t, 'tab', COLUMNS_LENGTH);
await t.click(targetCell.element);

await t
.expect(dataGrid.getFixedDataCell(0, COLUMNS_LENGTH - 1).isFocused)
.expect(targetCell.element.focused)
.ok();

await a11yCheck(t);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,53 @@
import { Selector } from 'testcafe';
import CardView from 'devextreme-testcafe-models/cardView';
import url from '../../../helpers/getPageUrl';
import { createWidget } from '../../../helpers/createWidget';
import { getCardFieldCaptions } from '../helpers/cardUtils';

const COLUMN_CHOOSER_DND_TIMEOUT = 3000;
const SORTABLE_DRAGGING_SELECTOR = '.dx-sortable-dragging';

fixture`CardView - ColumnChooser.Functional`
.page(url(__dirname, '../../container.html'));

const waitForDragEnd = async (t: TestController, cardView: CardView): Promise<void> => {
await t
.expect(Selector(SORTABLE_DRAGGING_SELECTOR).exists)
.notOk({ timeout: COLUMN_CHOOSER_DND_TIMEOUT })
.expect(cardView.isReady())
.ok({ timeout: COLUMN_CHOOSER_DND_TIMEOUT });
};

const dragHeaderColumnToColumnChooser = async (
t: TestController,
cardView: CardView,
columnIndex: number,
): Promise<void> => {
await t.dragToElement(
cardView.getHeaderPanel().getHeaderItem(columnIndex).element,
cardView.getColumnChooser().content,
{
speed: 0.5,
},
);
await waitForDragEnd(t, cardView);
};

const dragColumnChooserColumnToHeaderPanel = async (
t: TestController,
cardView: CardView,
columnIndex: number,
): Promise<void> => {
await t.dragToElement(
cardView.getColumnChooser().getColumn(columnIndex),
cardView.getHeaderPanel().element,
{
speed: 0.5,
},
);
await waitForDragEnd(t, cardView);
};

function testsFactory(testModel: {
name: string;
hideFirstColumn: (t: TestController, cardView: CardView) => Promise<void>;
Expand Down Expand Up @@ -99,16 +141,10 @@ testsFactory({
},
},
async hideFirstColumn(t: TestController, cardView: CardView) {
await t.dragToElement(
cardView.getHeaderPanel().getHeaderItem(0).element,
cardView.getColumnChooser().content,
);
await dragHeaderColumnToColumnChooser(t, cardView, 0);
},
async showFirstColumn(t: TestController, cardView: CardView) {
await t.dragToElement(
cardView.getColumnChooser().getColumn(0),
cardView.getHeaderPanel().element,
);
await dragColumnChooserColumnToHeaderPanel(t, cardView, 0);
},
async assertFirstColumnVisible(t: TestController, cardView: CardView) {
await t.expect(
Expand Down Expand Up @@ -222,18 +258,12 @@ test('cards should update when column is hidden via column chooser (dragAndDrop

await cardView.apiShowColumnChooser();

await t.dragToElement(
cardView.getHeaderPanel().getHeaderItem(0).element,
cardView.getColumnChooser().content,
);
await dragHeaderColumnToColumnChooser(t, cardView, 0);

const captionsAfterHide = await getCardFieldCaptions(t, cardView, 2);
await t.expect(captionsAfterHide).eql(['B', 'C']);

await t.dragToElement(
cardView.getColumnChooser().getColumn(0),
cardView.getHeaderPanel().element,
);
await dragColumnChooserColumnToHeaderPanel(t, cardView, 0);

const captionsAfterShow = await getCardFieldCaptions(t, cardView, 3);
await t.expect(captionsAfterShow).eql(['A', 'B', 'C']);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,16 +315,12 @@ test('cards should update when columns are reordered (T1324855)', async (t) => {

const headerPanel = cardView.getHeaderPanel();
const firstHeader = headerPanel.getHeaderItem(0).element;
const secondHeader = headerPanel.getHeaderItem(1).element;

await t.dragToElement(firstHeader, secondHeader, {
destinationOffsetX: -5,
destinationOffsetY: -20,
speed: 0.5,
});
await dragToHeaderPanel(t, cardView, firstHeader, 2);

// Wait for headers to update after drag
await t.expect(cardView.getHeaders().getHeaderItemNth(0).element.innerText).notEql('A');
await t
.expect(cardView.getHeaders().getHeaderItemNth(0).element.innerText)
.notEql('A', { timeout: 3000 });

const headerCaptions: string[] = [];
const headersCount = await cardView.getHeaders().getHeaderItemsElements().count;
Expand Down
37 changes: 25 additions & 12 deletions e2e/testcafe-devextreme/tests/cardView/columnSortable/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ClientFunction } from 'testcafe';
import { ClientFunction, Selector } from 'testcafe';
import CardView from 'devextreme-testcafe-models/cardView';
import TreeView from 'devextreme-testcafe-models/treeView';

const DRAG_ASSERTION_TIMEOUT = 3000;
const HEADER_DROP_OFFSET_Y = 5;

export const SELECTORS = {
dragging: '.dx-sortable-dragging',
treeView: '.dx-cardview-column-chooser .dx-treeview',
Expand Down Expand Up @@ -80,19 +83,31 @@ export const dragToHeaderPanel = async (
await t.dragToElement(
columnElement,
insertBeforeColumn,
{ destinationOffsetX: +5, destinationOffsetY: -20, speed: 0.5 },
{
destinationOffsetX: 5,
destinationOffsetY: HEADER_DROP_OFFSET_Y,
speed: 0.5,
},
);
} else {
const insertAfterColumn = headers.getHeaderItemNth(columnsNum - 1).element;

await t.dragToElement(
columnElement,
insertAfterColumn,
{ destinationOffsetX: -5, destinationOffsetY: -20, speed: 0.5 },
{
destinationOffsetX: -5,
destinationOffsetY: HEADER_DROP_OFFSET_Y,
speed: 0.5,
},
);
}

await t.wait(300);
await t
.expect(Selector(SELECTORS.dragging).exists)
.notOk({ timeout: DRAG_ASSERTION_TIMEOUT })
.expect(cardView.isReady())
.ok({ timeout: DRAG_ASSERTION_TIMEOUT });
};

export const dragToColumnChooser = async (
Expand Down Expand Up @@ -124,7 +139,7 @@ export const expectColumns = async (
expectedColumns: number[],
source: 'headerPanel' | 'columnChooser' = 'headerPanel',
): Promise<void> => {
const actualColumns: string[] = [];
const adjustedExpectedColumns = expectedColumns.map((columnIndex) => `Column ${columnIndex}`);

for (let i = 0; i < expectedColumns.length; i += 1) {
// eslint-disable-next-line @typescript-eslint/init-declarations
Expand All @@ -137,12 +152,10 @@ export const expectColumns = async (
column = treeView.getNodeItem(i);
}

if (await column?.exists) {
actualColumns.push(await column.innerText);
}
await t
.expect(column.exists)
.ok({ timeout: DRAG_ASSERTION_TIMEOUT })
.expect(column.innerText)
.eql(adjustedExpectedColumns[i], { timeout: DRAG_ASSERTION_TIMEOUT });
}

const adjustedExpectedColumns = expectedColumns.map((columnIndex) => `Column ${columnIndex}`);

await t.expect(actualColumns).eql(adjustedExpectedColumns);
};
10 changes: 8 additions & 2 deletions e2e/testcafe-devextreme/tests/cardView/helpers/cardUtils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import CardView from 'devextreme-testcafe-models/cardView';

const FIELD_CAPTION_SELECTOR = '.dx-cardview-field-caption';
const CARD_FIELD_CAPTION_TIMEOUT = 3000;

const getCardFieldCaptions = async (
t: TestController,
cardView: CardView,
expectedCount: number,
cardIndex = 0,
): Promise<string[]> => {
const card = cardView.getCard(cardIndex);
const captions = await card.getCaptions();

await t.expect(captions.length).eql(expectedCount);
await t
.expect(card.element.find(FIELD_CAPTION_SELECTOR).count)
.eql(expectedCount, { timeout: CARD_FIELD_CAPTION_TIMEOUT });

const captions = await card.getCaptions();

return captions;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { createWidget } from '../../../../helpers/createWidget';
fixture.disablePageReloads`Editing.Functional`
.page(url(__dirname, '../../../container.html'));

const FOCUS_ASSERTION_TIMEOUT = 3000;

const getGridConfig = (config): Record<string, unknown> => {
const defaultConfig = {
errorRowEnabled: true,
Expand Down Expand Up @@ -66,7 +68,9 @@ test('DataGrid - The "Cannot read properties of undefined error" occurs when usi
.typeText(dataGrid.getDataCell(0, 0).element, 'new_value')
.pressKey('enter tab tab');
await resolveOnSavingDeferred();
await t.expect(dataGrid.getDataCell(2, 0).isFocused).ok();
await t
.expect(dataGrid.isReady()).ok({ timeout: FOCUS_ASSERTION_TIMEOUT })
.expect(dataGrid.getDataCell(2, 0).isFocused).ok({ timeout: FOCUS_ASSERTION_TIMEOUT });
}).before(async () => {
await ClientFunction(() => {
(window as any).deferred = $.Deferred();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ test('Don\'t calculate additional filter when filtering column list is empty', a
// arrange
const dataGrid = new DataGrid(GRID_CONTAINER);
await t.expect(dataGrid.isReady()).ok();
const consoleMessages = await t.getBrowserConsoleMessages();

// act
await dataGrid.option({
Expand All @@ -37,8 +36,10 @@ test('Don\'t calculate additional filter when filtering column list is empty', a
});

// assert
const consoleMessages = await t.getBrowserConsoleMessages();

await t
.expect(consoleMessages.error.every((msg) => !msg.includes('E1047')))
.expect((consoleMessages?.error ?? []).every((msg) => !msg.includes('E1047')))
.ok();
}).before(async () => createWidget('dxDataGrid', {
keyExpr: 'id',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ClientFunction } from 'testcafe';
import DataGrid from 'devextreme-testcafe-models/dataGrid';
import { createWidget } from '../../../../../helpers/createWidget';
import url from '../../../../../helpers/getPageUrl';
Expand Down Expand Up @@ -337,24 +338,18 @@ test('It should fire correct events on page change', async (t) => {

test('It should fire row changed event and change page if focusedRowKey on another page', async (t) => {
const expectedRowFocusChanged: FocusRowChangedData[] = [[1]];
const getRowFocusChanged = ClientFunction(() => {
const extendedWindow = window as WindowCallbackExtended;

const dataGrid = new DataGrid(GRID_SELECTOR);

await t.wait(100);

const [
,
,
,
rowFocusChanged,
] = await collectEventsCallbackResults();
return extendedWindow.clientTesting!.data.rowFocusChanged;
});

const cellText = await dataGrid.getDataCell(3, 0).element().innerText;
const dataGrid = new DataGrid(GRID_SELECTOR);

await t
.expect(rowFocusChanged)
.expect(getRowFocusChanged())
.eql(expectedRowFocusChanged)
.expect(cellText)
.expect(dataGrid.getDataCell(3, 0).element.innerText)
.eql('dataA_3');
}).before(async () => {
await initCallbackTesting();
Expand Down
Loading
Loading