From 0753b2910e1c7c2e8e721176a3abf59e3ff3ed97 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 13:17:02 +0400 Subject: [PATCH 01/10] DataGrid - Testcafe tests - row dragging: unskip tests --- .../tests/dataGrid/common/rowDragging.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts index 4b223aae8cf1..ae15b840d010 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts @@ -468,7 +468,7 @@ test('Headers should not be hidden during auto scrolling when virtual scrollling }); // T1078513 -test.meta({ unstable: true })('Footer should not be hidden during auto scrolling when virtual scrollling is specified', async (t) => { +test('Footer should not be hidden during auto scrolling when virtual scrollling is specified', async (t) => { const dataGrid = new DataGrid('#container'); await t.drag(dataGrid.getDataRow(0).getDragCommand(), 0, 90, { speed: 0.1 }); @@ -570,7 +570,7 @@ test('The draggable element should be displayed correctly after horizontal scrol }); }); -test.meta({ unstable: true })('Dragging with scrolling should be prevented by e.cancel (T1179555)', async (t) => { +test('Dragging with scrolling should be prevented by e.cancel (T1179555)', async (t) => { const dataGrid = new DataGrid('#container'); await dataGrid.scrollBy(t, { top: 10000 }); @@ -661,7 +661,7 @@ test('The placeholder should have correct position after dragging the row to the })); // T1126013 -test.meta({ unstable: true })('toIndex should not be corrected when source item gets removed from DOM', async (t) => { +test('toIndex should not be corrected when source item gets removed from DOM', async (t) => { const fromIndex = 2; const toIndex = 4; @@ -787,7 +787,7 @@ test('Item should appear in a correct spot when dragging to a different page wit }); // T1179218 -test.meta({ unstable: true })('Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"', async (t) => { +test('Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"', async (t) => { const dataGrid = new DataGrid('#container'); const { takeScreenshot, compareResults } = createScreenshotsComparer(t); From d3fd317c1ad47be31669bdae9e65e2e219ffd806 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 14:39:39 +0400 Subject: [PATCH 02/10] Fix the 'Dragging with scrolling should be prevented by e.cancel (T1179555)' test --- e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts index ae15b840d010..32ac456b36ed 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts @@ -578,7 +578,7 @@ test('Dragging with scrolling should be prevented by e.cancel (T1179555)', async await MouseUpEvents.disable(MouseAction.dragToOffset); - await t.drag(dataGrid.getDataRow(98).getDragCommand(), 0, -180, { speed: 0.1 }); + await t.drag(dataGrid.getDataRow(98).getDragCommand(), 0, -160, { speed: 0.1 }); await t.expect(Selector('.dx-sortable-placeholder').visible).notOk(); From bfb87f01d0a1a12e1fc850e215c690f9b8771684 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 14:52:37 +0400 Subject: [PATCH 03/10] Fix the 'Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"' test --- e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts index 32ac456b36ed..dfde5ac40069 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts @@ -799,7 +799,10 @@ test('Rows should appear correctly during dragging when virtual scrolling is ena await t.wait(2000); // drag the row up - await dataGrid.moveRow(0, 30, 75); + await dataGrid.moveRow(0, 30, 100); + + // waiting for autoscrolling + await t.wait(1000); await testScreenshot(t, takeScreenshot, 'T1179218-virtual-scrolling-dragging-row.png', { element: dataGrid.element }); await t From 2bf075985610e882051996343495f72347e176df Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 15:45:01 +0400 Subject: [PATCH 04/10] Update etalon. And move the rowDragging tests to a separate folder. --- ...lling-dragging-row (fluent.blue.light).png | Bin 9662 -> 0 bytes ...lling-dragging-row (fluent.blue.light).png | Bin 0 -> 9677 bytes .../functional.ts} | 51 ++---------------- .../dataGrid/common/rowDragging/visual.ts | 47 ++++++++++++++++ 4 files changed, 52 insertions(+), 46 deletions(-) delete mode 100644 e2e/testcafe-devextreme/tests/dataGrid/common/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png create mode 100644 e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png rename e2e/testcafe-devextreme/tests/dataGrid/common/{rowDragging.ts => rowDragging/functional.ts} (93%) create mode 100644 e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png deleted file mode 100644 index bb19c96644929f3a7ad410f88c87450888ec306a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9662 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 ah<|wev*^p+opj{fd*ASQo%!04kNyE~7uZJt diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png new file mode 100644 index 0000000000000000000000000000000000000000..baf9c156a35de46eff37fd34d0a767ec22e7524c GIT binary patch literal 9677 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 O?Y?n7UTJggum1(Z0l(S+ literal 0 HcmV?d00001 diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts similarity index 93% rename from e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts rename to e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts index dfde5ac40069..f7f73a03290b 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts @@ -1,12 +1,10 @@ /* eslint-disable @typescript-eslint/no-misused-promises */ import { ClientFunction, Selector } from 'testcafe'; -import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; import DataGrid, { CLASS as DataGridClassNames } from 'devextreme-testcafe-models/dataGrid'; import { ClassNames } from 'devextreme-testcafe-models/dataGrid/classNames'; -import { MouseUpEvents, MouseAction } from '../../../helpers/mouseUpEvents'; -import url from '../../../helpers/getPageUrl'; -import { createWidget } from '../../../helpers/createWidget'; -import { testScreenshot } from '../../../helpers/themeUtils'; +import { MouseUpEvents, MouseAction } from '../../../../helpers/mouseUpEvents'; +import url from '../../../../helpers/getPageUrl'; +import { createWidget } from '../../../../helpers/createWidget'; const CLASS = { ...DataGridClassNames, ...ClassNames }; @@ -55,8 +53,8 @@ const generateData = (rowCount, columnCount): Record[] => { return items; }; -fixture`Row dragging` - .page(url(__dirname, '../../container.html')); +fixture`Row dragging.Functional` + .page(url(__dirname, '../../../container.html')); // T903351 test('The placeholder should appear when a cross-component dragging rows after scrolling the window', async (t) => { @@ -785,42 +783,3 @@ test('Item should appear in a correct spot when dragging to a different page wit showBorders: true, }); }); - -// T1179218 -test('Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"', async (t) => { - const dataGrid = new DataGrid('#container'); - const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - - // drag the row down - await dataGrid.moveRow(0, 30, 150, true); - await dataGrid.moveRow(0, 30, 350); - - // waiting for autoscrolling - await t.wait(2000); - - // drag the row up - await dataGrid.moveRow(0, 30, 100); - - // waiting for autoscrolling - await t.wait(1000); - - await testScreenshot(t, takeScreenshot, 'T1179218-virtual-scrolling-dragging-row.png', { element: dataGrid.element }); - await t - .expect(compareResults.isValid()) - .ok(compareResults.errorMessages()); -}).before(async (t) => { - await t.maximizeWindow(); - return createWidget('dxDataGrid', { - height: 440, - keyExpr: 'id', - scrolling: { - mode: 'virtual', - }, - dataSource: [...new Array(100)].fill(null).map((_, index) => ({ id: index })), - columns: ['id'], - rowDragging: { - allowReordering: true, - dropFeedbackMode: 'push', - }, - }); -}); diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts new file mode 100644 index 000000000000..0d0a3e10d7d7 --- /dev/null +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts @@ -0,0 +1,47 @@ +import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; +import DataGrid from 'devextreme-testcafe-models/dataGrid'; +import url from '../../../../helpers/getPageUrl'; +import { createWidget } from '../../../../helpers/createWidget'; +import { testScreenshot } from '../../../../helpers/themeUtils'; + +fixture`Row dragging.Visual` + .page(url(__dirname, '../../../container.html')); + +// T1179218 +test('Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"', async (t) => { + const dataGrid = new DataGrid('#container'); + const { takeScreenshot, compareResults } = createScreenshotsComparer(t); + + // drag the row down + await dataGrid.moveRow(0, 30, 150, true); + await dataGrid.moveRow(0, 30, 350); + + // waiting for autoscrolling + await t.wait(2000); + + // drag the row up + await dataGrid.moveRow(0, 30, 100); + + // waiting for autoscrolling + await t.wait(1000); + + await testScreenshot(t, takeScreenshot, 'T1179218-virtual-scrolling-dragging-row.png', { element: dataGrid.element }); + await t + .expect(compareResults.isValid()) + .ok(compareResults.errorMessages()); +}).before(async (t) => { + await t.maximizeWindow(); + return createWidget('dxDataGrid', { + height: 440, + keyExpr: 'id', + scrolling: { + mode: 'virtual', + }, + dataSource: [...new Array(100)].fill(null).map((_, index) => ({ id: index })), + columns: ['id'], + rowDragging: { + allowReordering: true, + dropFeedbackMode: 'push', + }, + }); +}); From b85c82c2e4e7900e8e938522708d15eb24104be8 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 16:26:46 +0400 Subject: [PATCH 05/10] add mask --- ...ing-dragging-row (fluent.blue.light)_mask.png | Bin 0 -> 4170 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light)_mask.png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light)_mask.png b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light)_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..a9dbd8fb5dc780ba3ae96cb2d442e6e568275cba GIT binary patch literal 4170 zcmeAS@N?(olHy`uVBq!ia0y~yU@u@`VBEpM1{B#MUbd8hK|s*c#WAFU@$Es!JOM`r z<_$hu{{R1UV6Ir>gl!8q)xPs*1S$oB2d7OT33&;i_ zXyD|9Fc^fTpbRw=C}Y$hNI(qgFq*gL#T;R1gxOt#GLRzt^Q2-wsOXOv>c{>w)$jM9 z#(&tUuD|O$EM4^v;^bKIiFZ!%C;fMOq1oa`7WFg1yc%YB$ozRvQrDX8C!fVCP%TceQB9t~`0 psvGT$Kmua4!v;+dBfe8>&tSM)sbbac@J>*Oc)I$ztaD0e0st;bmBj!6 literal 0 HcmV?d00001 From a3c908f5814b9386b67abc67905e3a7554f4388d Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 16:27:15 +0400 Subject: [PATCH 06/10] Fix typo --- .../tests/dataGrid/common/rowDragging/functional.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts index f7f73a03290b..3a00398211c5 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts @@ -466,7 +466,7 @@ test('Headers should not be hidden during auto scrolling when virtual scrollling }); // T1078513 -test('Footer should not be hidden during auto scrolling when virtual scrollling is specified', async (t) => { +test('Footer should not be hidden during auto scrolling when virtual scrolling is specified', async (t) => { const dataGrid = new DataGrid('#container'); await t.drag(dataGrid.getDataRow(0).getDragCommand(), 0, 90, { speed: 0.1 }); From 738ad14fdeb915c1c4d70cc40d5c097ab4a8c7fc Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Tue, 27 Jan 2026 21:32:42 +0400 Subject: [PATCH 07/10] small refactoring --- .../dataGrid/common/rowDragging/functional.ts | 13 ++++++++++++- .../tests/dataGrid/common/rowDragging/visual.ts | 14 ++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts index 3a00398211c5..8bfedc40e9e6 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts @@ -5,6 +5,7 @@ import { ClassNames } from 'devextreme-testcafe-models/dataGrid/classNames'; import { MouseUpEvents, MouseAction } from '../../../../helpers/mouseUpEvents'; import url from '../../../../helpers/getPageUrl'; import { createWidget } from '../../../../helpers/createWidget'; +import { getThemeName } from '../../../../helpers/themeUtils'; const CLASS = { ...DataGridClassNames, ...ClassNames }; @@ -570,13 +571,23 @@ test('The draggable element should be displayed correctly after horizontal scrol test('Dragging with scrolling should be prevented by e.cancel (T1179555)', async (t) => { const dataGrid = new DataGrid('#container'); + const scrollTopOffsetByTheme = { + generic: -180, + fluent: -160, + material: -160, + }; await dataGrid.scrollBy(t, { top: 10000 }); await t.expect(dataGrid.isReady()).ok(); await MouseUpEvents.disable(MouseAction.dragToOffset); - await t.drag(dataGrid.getDataRow(98).getDragCommand(), 0, -160, { speed: 0.1 }); + await t.drag( + dataGrid.getDataRow(98).getDragCommand(), + 0, + scrollTopOffsetByTheme[getThemeName()], + { speed: 0.1 }, + ); await t.expect(Selector('.dx-sortable-placeholder').visible).notOk(); diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts index 0d0a3e10d7d7..3b6638322621 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts @@ -2,7 +2,7 @@ import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; import DataGrid from 'devextreme-testcafe-models/dataGrid'; import url from '../../../../helpers/getPageUrl'; import { createWidget } from '../../../../helpers/createWidget'; -import { testScreenshot } from '../../../../helpers/themeUtils'; +import { getThemeName, testScreenshot } from '../../../../helpers/themeUtils'; fixture`Row dragging.Visual` .page(url(__dirname, '../../../container.html')); @@ -11,16 +11,22 @@ fixture`Row dragging.Visual` test('Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"', async (t) => { const dataGrid = new DataGrid('#container'); const { takeScreenshot, compareResults } = createScreenshotsComparer(t); + const themeName = getThemeName(); + const scrollTopOffsetsByTheme = { + generic: [150, 350, 75], + fluent: [150, 350, 100], + material: [150, 350, 100], + }; // drag the row down - await dataGrid.moveRow(0, 30, 150, true); - await dataGrid.moveRow(0, 30, 350); + await dataGrid.moveRow(0, 30, scrollTopOffsetsByTheme[themeName][0], true); + await dataGrid.moveRow(0, 30, scrollTopOffsetsByTheme[themeName][1]); // waiting for autoscrolling await t.wait(2000); // drag the row up - await dataGrid.moveRow(0, 30, 100); + await dataGrid.moveRow(0, 30, scrollTopOffsetsByTheme[themeName][2]); // waiting for autoscrolling await t.wait(1000); From 712609c10337137bad876adf433dc9f1c428e545 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Thu, 29 Jan 2026 23:47:46 +0400 Subject: [PATCH 08/10] Rewrite the 'toIndex should not be corrected when source item gets removed from DOM' test --- .../dataGrid/common/rowDragging/functional.ts | 85 ++++++++++++------- .../dataGrid/helpers/rowDraggingHelpers.ts | 68 +++++++++++++++ 2 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts index 8bfedc40e9e6..baef6362e7df 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts @@ -6,6 +6,7 @@ import { MouseUpEvents, MouseAction } from '../../../../helpers/mouseUpEvents'; import url from '../../../../helpers/getPageUrl'; import { createWidget } from '../../../../helpers/createWidget'; import { getThemeName } from '../../../../helpers/themeUtils'; +import { isScrollAtEnd, getOffsetToTriggerUpwardAutoScroll } from '../../helpers/rowDraggingHelpers'; const CLASS = { ...DataGridClassNames, ...ClassNames }; @@ -671,51 +672,77 @@ test('The placeholder should have correct position after dragging the row to the // T1126013 test('toIndex should not be corrected when source item gets removed from DOM', async (t) => { - const fromIndex = 2; - const toIndex = 4; - + // arrange const dataGrid = new DataGrid('#container'); + const AUTOSCROLL_WAIT_TIME = 2000; + const AUTOSCROLL_SPEED_FACTOR = 0.5; + + await t.expect(dataGrid.isReady()).ok(); + + // act - scroll to the bottom to make the last row visible await dataGrid.scrollTo(t, { y: 3000 }); - const sourceKey = await ClientFunction((grid, idx) => { - const instance: any = grid.getInstance(); - const visibleRows = instance.getVisibleRows(); - return visibleRows[idx]?.key; - }, { dependencies: {} })(dataGrid, fromIndex); + // assert + await t + .expect(dataGrid.getDataRow(49).getDataCell(1).element.textContent) + .eql('50-1') + .expect(isScrollAtEnd('vertical')) + .ok(); - const initialIndices = await ClientFunction((grid) => { - const instance: any = grid.getInstance(); - return instance.getVisibleRows().map((r: any) => r.key); - })(dataGrid); - const sourceInitialIndex = initialIndices.indexOf(sourceKey); + let visibleRows = await dataGrid.apiGetVisibleRows(); + const draggableRow = visibleRows[1]; - await dataGrid.moveRow(fromIndex, 0, 50, true); - await dataGrid.moveRow(fromIndex, 0, -20); - await dataGrid.moveRow(toIndex, 0, 5); + // Calculate offsetY to trigger upward autoscroll when dragging the row. + // Using speedFactor 0.5 to ensure medium scrolling speed. + const scrollOffsetForFastAutoScroll = await getOffsetToTriggerUpwardAutoScroll( + draggableRow.rowIndex, + AUTOSCROLL_SPEED_FACTOR, + ); - await ClientFunction((grid) => { - const instance = grid.getInstance(); - $(instance.element()).trigger($.Event('dxpointerup')); - })(dataGrid); + // act - drag a row up the grid to start auto-scrolling. + await dataGrid.moveRow(draggableRow.rowIndex, 0, 150, true); + await dataGrid.moveRow(draggableRow.rowIndex, 0, 100); + await dataGrid.moveRow(draggableRow.rowIndex, 0, scrollOffsetForFastAutoScroll); + + // Waiting for autoscrolling + await t.wait(AUTOSCROLL_WAIT_TIME); + + // assert + visibleRows = await dataGrid.apiGetVisibleRows(); + + await t + .expect(dataGrid.getDataRow(0).getDataCell(1).element.textContent) + .eql('1-1') + .expect(dataGrid.getScrollTop()) + .eql(0); - const finalIndex = await ClientFunction((grid, key) => { - const instance: any = grid.getInstance(); - const visibleRows = instance.getVisibleRows(); - return visibleRows.findIndex((r: any) => r.key === key); - })(dataGrid, sourceKey); + // act - drag and drop the row to the third position (after row 2-1). + const rowHeight = await dataGrid.getDataRow(0).element.offsetHeight; - const expectedFinalIndex = (toIndex - 1) - (sourceInitialIndex < toIndex ? 1 : 0); + await dataGrid.moveRow(draggableRow.rowIndex, 0, rowHeight / 2); + await dataGrid.dropRow(); - await t.expect(finalIndex) - .eql(expectedFinalIndex, `Dragged row key ${sourceKey} expected at ${expectedFinalIndex} but ended up at index ${finalIndex}`); + // assert + await t.expect(dataGrid.isReady()).ok(); + + visibleRows = await dataGrid.apiGetVisibleRows(); + + await t + .expect(visibleRows[0].key) + .eql('1-1') + .expect(visibleRows[1].key) + .eql('2-1') + .expect(visibleRows[2].key) + .eql(draggableRow.key); }).before(async (t) => { await t.maximizeWindow(); const items = generateData(50, 1); return createWidget('dxDataGrid', { - height: 250, + height: 260, keyExpr: 'field1', scrolling: { mode: 'virtual', + useNative: false, }, paging: { pageSize: 4, diff --git a/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts b/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts new file mode 100644 index 000000000000..a2f9fe819f60 --- /dev/null +++ b/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts @@ -0,0 +1,68 @@ +import { ClientFunction } from 'testcafe'; + +export const isScrollAtEnd = ClientFunction((orientation: 'vertical' | 'horizontal' = 'vertical') => { + const element = $('.dx-datagrid-rowsview .dx-scrollable-container')[0]; + + if (!element) { + return false; + } + + const scrollSize = element[orientation === 'vertical' ? 'scrollHeight' : 'scrollWidth']; + const scrollPosition = element[orientation === 'vertical' ? 'scrollTop' : 'scrollLeft']; + const clientSize = element[orientation === 'vertical' ? 'clientHeight' : 'clientWidth']; + + return scrollPosition + clientSize >= scrollSize - 1; +}); + +/** + * Calculates Y-offset for dragging a row to the top of the grid with upward autoscroll. + * Autoscroll triggers when the cursor is within scrollSensitivity (default 60px) + * from the top edge of the container. + * Autoscroll speed is calculated by formula: + * Math.ceil(((sensitivity - distance) / sensitivity) ** 2 * maxSpeed) + * + * @param rowIndex - index of the row being dragged + * @param speedFactor - speed factor from 0 to 1 (default 0.5): + * - 0 = minimum speed (cursor at scrollSensitivity boundary) + * - 0.5 = medium speed (cursor halfway to the edge) + * - 1 = maximum speed (cursor at the container edge) + * @returns Y-offset relative to the current row position to trigger upward autoscroll + */ +export const getOffsetToTriggerUpwardAutoScroll = ClientFunction( + (rowIndex: number, speedFactor = 0.5): number => { + const gridInstance = $('#container').data('dxDataGrid'); + const $row = $(gridInstance.getRowElement(rowIndex)); + const $scrollContainer = $('.dx-datagrid-rowsview .dx-scrollable-container'); + + if (!$row.length || !$scrollContainer.length) { + return 0; + } + + const rowOffset = $row.offset(); + const containerOffset = $scrollContainer.offset(); + + if (!rowOffset || !containerOffset) { + return 0; + } + + // scrollSensitivity is 60px by default + // To trigger autoscroll, the row must be dragged so that + // the cursor is within scrollSensitivity from the top edge of the container + const scrollSensitivity = gridInstance.option('rowDragging.scrollSensitivity') ?? 60; + + // Clamp speedFactor to [0, 1] range + const normalizedSpeedFactor = Math.max(0, Math.min(1, speedFactor)); + + // Calculate distance from the top edge of the container: + // - speedFactor = 0: distance = scrollSensitivity (minimum speed) + // - speedFactor = 0.5: distance = scrollSensitivity / 2 (medium speed) + // - speedFactor = 1: distance = 0 (maximum speed, cursor at the edge) + const distance = scrollSensitivity * (1 - normalizedSpeedFactor); + + // Target Y-coordinate + const targetY = containerOffset.top + distance; + + // Return offset relative to the current row position + return Math.round(targetY - rowOffset.top); + }, +); From c468388f5eb2f338687f9667699dccdda094da9c Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Fri, 30 Jan 2026 00:54:31 +0400 Subject: [PATCH 09/10] test refactoring --- .../helpers/mouseUpEvents.ts | 34 +++++++++++++ .../dataGrid/common/rowDragging/functional.ts | 49 +++++++++++-------- .../dataGrid/common/rowDragging/visual.ts | 29 ++++++----- .../dataGrid/helpers/rowDraggingHelpers.ts | 32 +++++++----- packages/testcafe-models/dataGrid/index.ts | 17 +++++++ 5 files changed, 118 insertions(+), 43 deletions(-) diff --git a/e2e/testcafe-devextreme/helpers/mouseUpEvents.ts b/e2e/testcafe-devextreme/helpers/mouseUpEvents.ts index 0dd1fc5efd24..3aa25a42a093 100644 --- a/e2e/testcafe-devextreme/helpers/mouseUpEvents.ts +++ b/e2e/testcafe-devextreme/helpers/mouseUpEvents.ts @@ -32,3 +32,37 @@ export const MouseUpEvents = { disable: disableMouseUpEvent, enable: enableMouseUpEvent, }; + +/** + * Performs a drag operation on a row with MouseUpEvents temporarily disabled. + * This is useful for autoscroll tests where we need to keep the row in drag state. + * + * @param t - TestController instance + * @param element - Selector for the element to drag + * @param options - drag options + * @param options.offsetX - X-offset for the drag operation + * @param options.offsetY - Y-offset for the drag operation + * @param options.speed - speed of the drag operation (default is 0.1) + */ +export const dragWithDisabledMouseUp = async ( + t: TestController, + element: Selector, + { + offsetX, + offsetY, + speed = 0.1, + }: { + offsetX: number; + offsetY: number; + speed?: number; + }, +): Promise => { + await MouseUpEvents.disable(MouseAction.dragToOffset); + await t.drag( + element, + offsetX, + offsetY, + { speed }, + ); + await MouseUpEvents.enable(MouseAction.dragToOffset); +}; diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts index baef6362e7df..219fdba12b32 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/functional.ts @@ -2,11 +2,10 @@ import { ClientFunction, Selector } from 'testcafe'; import DataGrid, { CLASS as DataGridClassNames } from 'devextreme-testcafe-models/dataGrid'; import { ClassNames } from 'devextreme-testcafe-models/dataGrid/classNames'; -import { MouseUpEvents, MouseAction } from '../../../../helpers/mouseUpEvents'; +import { dragWithDisabledMouseUp } from '../../../../helpers/mouseUpEvents'; import url from '../../../../helpers/getPageUrl'; import { createWidget } from '../../../../helpers/createWidget'; -import { getThemeName } from '../../../../helpers/themeUtils'; -import { isScrollAtEnd, getOffsetToTriggerUpwardAutoScroll } from '../../helpers/rowDraggingHelpers'; +import { isScrollAtEnd, getOffsetToTriggerAutoScroll } from '../../helpers/rowDraggingHelpers'; const CLASS = { ...DataGridClassNames, ...ClassNames }; @@ -572,27 +571,39 @@ test('The draggable element should be displayed correctly after horizontal scrol test('Dragging with scrolling should be prevented by e.cancel (T1179555)', async (t) => { const dataGrid = new DataGrid('#container'); - const scrollTopOffsetByTheme = { - generic: -180, - fluent: -160, - material: -160, - }; - await dataGrid.scrollBy(t, { top: 10000 }); await t.expect(dataGrid.isReady()).ok(); - await MouseUpEvents.disable(MouseAction.dragToOffset); + await dataGrid.scrollBy(t, { top: 10000 }); + + await t + .expect(dataGrid.getDataRow(99).getDataCell(1).element.textContent) + .eql('99') + .expect(isScrollAtEnd('vertical')) + .ok(); + + const visibleRows = await dataGrid.apiGetVisibleRows(); + const scrollTopOffsetByTheme = await getOffsetToTriggerAutoScroll( + visibleRows.length - 2, + 1, + ); - await t.drag( + await dragWithDisabledMouseUp( + t, dataGrid.getDataRow(98).getDragCommand(), - 0, - scrollTopOffsetByTheme[getThemeName()], - { speed: 0.1 }, + { offsetX: 0, offsetY: scrollTopOffsetByTheme, speed: 0.8 }, ); - await t.expect(Selector('.dx-sortable-placeholder').visible).notOk(); + // Wait for autoscrolling + await t.wait(2000); - await MouseUpEvents.enable(MouseAction.dragToOffset); + await t + .expect(dataGrid.getDataRow(0).getDataCell(1).element.textContent) + .eql('0') + .expect(dataGrid.getScrollTop()) + .eql(0); + + await t.expect(Selector('.dx-sortable-placeholder').visible).notOk(); }).before(async (t) => { await t.maximizeWindow(); return createWidget('dxDataGrid', { @@ -694,7 +705,7 @@ test('toIndex should not be corrected when source item gets removed from DOM', a // Calculate offsetY to trigger upward autoscroll when dragging the row. // Using speedFactor 0.5 to ensure medium scrolling speed. - const scrollOffsetForFastAutoScroll = await getOffsetToTriggerUpwardAutoScroll( + const scrollOffsetForFastAutoScroll = await getOffsetToTriggerAutoScroll( draggableRow.rowIndex, AUTOSCROLL_SPEED_FACTOR, ); @@ -742,10 +753,6 @@ test('toIndex should not be corrected when source item gets removed from DOM', a keyExpr: 'field1', scrolling: { mode: 'virtual', - useNative: false, - }, - paging: { - pageSize: 4, }, dataSource: items, rowDragging: { diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts index 3b6638322621..dc96f8ca76c1 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/visual.ts @@ -2,7 +2,8 @@ import { createScreenshotsComparer } from 'devextreme-screenshot-comparer'; import DataGrid from 'devextreme-testcafe-models/dataGrid'; import url from '../../../../helpers/getPageUrl'; import { createWidget } from '../../../../helpers/createWidget'; -import { getThemeName, testScreenshot } from '../../../../helpers/themeUtils'; +import { testScreenshot } from '../../../../helpers/themeUtils'; +import { getOffsetToTriggerAutoScroll, isScrollAtEnd } from '../../helpers/rowDraggingHelpers'; fixture`Row dragging.Visual` .page(url(__dirname, '../../../container.html')); @@ -11,25 +12,31 @@ fixture`Row dragging.Visual` test('Rows should appear correctly during dragging when virtual scrolling is enabled and rowDragging.dropFeedbackMode = "push"', async (t) => { const dataGrid = new DataGrid('#container'); const { takeScreenshot, compareResults } = createScreenshotsComparer(t); - const themeName = getThemeName(); - const scrollTopOffsetsByTheme = { - generic: [150, 350, 75], - fluent: [150, 350, 100], - material: [150, 350, 100], - }; // drag the row down - await dataGrid.moveRow(0, 30, scrollTopOffsetsByTheme[themeName][0], true); - await dataGrid.moveRow(0, 30, scrollTopOffsetsByTheme[themeName][1]); + await dataGrid.moveRow(0, 30, 150, true); + await dataGrid.moveRow(0, 30, await getOffsetToTriggerAutoScroll(0, 1, 'down')); // waiting for autoscrolling await t.wait(2000); + await t + .expect(dataGrid.getDataRow(99).getDataCell(1).element.textContent) + .eql('99') + .expect(isScrollAtEnd('vertical')) + .ok(); + // drag the row up - await dataGrid.moveRow(0, 30, scrollTopOffsetsByTheme[themeName][2]); + await dataGrid.moveRow(0, 30, await getOffsetToTriggerAutoScroll(0, 1)); // waiting for autoscrolling - await t.wait(1000); + await t.wait(2000); + + await t + .expect(dataGrid.getDataRow(0).getDataCell(1).element.textContent) + .eql('0') + .expect(dataGrid.getScrollTop()) + .eql(0); await testScreenshot(t, takeScreenshot, 'T1179218-virtual-scrolling-dragging-row.png', { element: dataGrid.element }); await t diff --git a/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts b/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts index a2f9fe819f60..a57db5a328e9 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/helpers/rowDraggingHelpers.ts @@ -11,13 +11,13 @@ export const isScrollAtEnd = ClientFunction((orientation: 'vertical' | 'horizont const scrollPosition = element[orientation === 'vertical' ? 'scrollTop' : 'scrollLeft']; const clientSize = element[orientation === 'vertical' ? 'clientHeight' : 'clientWidth']; - return scrollPosition + clientSize >= scrollSize - 1; + return Math.round(scrollPosition + clientSize) >= scrollSize - 1; }); /** - * Calculates Y-offset for dragging a row to the top of the grid with upward autoscroll. + * Calculates offsetY for dragging a row to trigger autoscroll. * Autoscroll triggers when the cursor is within scrollSensitivity (default 60px) - * from the top edge of the container. + * from the edge of the container. * Autoscroll speed is calculated by formula: * Math.ceil(((sensitivity - distance) / sensitivity) ** 2 * maxSpeed) * @@ -26,10 +26,13 @@ export const isScrollAtEnd = ClientFunction((orientation: 'vertical' | 'horizont * - 0 = minimum speed (cursor at scrollSensitivity boundary) * - 0.5 = medium speed (cursor halfway to the edge) * - 1 = maximum speed (cursor at the container edge) - * @returns Y-offset relative to the current row position to trigger upward autoscroll + * @param direction - autoscroll direction (default 'up'): + * - 'up' = upward autoscroll (drag towards top edge) + * - 'down' = downward autoscroll (drag towards bottom edge) + * @returns offsetY relative to the current row position to trigger autoscroll */ -export const getOffsetToTriggerUpwardAutoScroll = ClientFunction( - (rowIndex: number, speedFactor = 0.5): number => { +export const getOffsetToTriggerAutoScroll = ClientFunction( + (rowIndex: number, speedFactor = 0.5, direction: 'up' | 'down' = 'up'): number => { const gridInstance = $('#container').data('dxDataGrid'); const $row = $(gridInstance.getRowElement(rowIndex)); const $scrollContainer = $('.dx-datagrid-rowsview .dx-scrollable-container'); @@ -47,22 +50,29 @@ export const getOffsetToTriggerUpwardAutoScroll = ClientFunction( // scrollSensitivity is 60px by default // To trigger autoscroll, the row must be dragged so that - // the cursor is within scrollSensitivity from the top edge of the container + // the cursor is within scrollSensitivity from the edge of the container const scrollSensitivity = gridInstance.option('rowDragging.scrollSensitivity') ?? 60; // Clamp speedFactor to [0, 1] range const normalizedSpeedFactor = Math.max(0, Math.min(1, speedFactor)); - // Calculate distance from the top edge of the container: + // Calculate distance from the edge of the container: // - speedFactor = 0: distance = scrollSensitivity (minimum speed) // - speedFactor = 0.5: distance = scrollSensitivity / 2 (medium speed) // - speedFactor = 1: distance = 0 (maximum speed, cursor at the edge) const distance = scrollSensitivity * (1 - normalizedSpeedFactor); - // Target Y-coordinate - const targetY = containerOffset.top + distance; + if (direction === 'up') { + // Target Y-coordinate for upward autoscroll + const targetY = containerOffset.top + distance + 1; + + return Math.round(targetY - rowOffset.top); + } + + // Target Y-coordinate for downward autoscroll + const containerHeight = $scrollContainer.height() ?? 0; + const targetY = containerOffset.top + containerHeight - distance - 1; - // Return offset relative to the current row position return Math.round(targetY - rowOffset.top); }, ); diff --git a/packages/testcafe-models/dataGrid/index.ts b/packages/testcafe-models/dataGrid/index.ts index 0b85751dc5f6..16bb9ef78898 100644 --- a/packages/testcafe-models/dataGrid/index.ts +++ b/packages/testcafe-models/dataGrid/index.ts @@ -76,6 +76,7 @@ export const CLASS = { toast: 'dx-toast-wrapper', dragHeader: 'drag-header', aiPromptEditor: 'dx-ai-prompt-editor', + sortableDragging: 'dx-sortable-dragging', }; const E2E_ATTRIBUTES = { @@ -570,6 +571,7 @@ export default class DataGrid extends GridCore { data: r.data, dataIndex: r.dataIndex, rowType: r.rowType, + rowIndex: r.rowIndex, })); }, { dependencies: { getInstance } })(); } @@ -759,6 +761,21 @@ export default class DataGrid extends GridCore { )(); } + dropRow(): Promise { + return ClientFunction((sortableDraggingClass) => { + const $dragElement = $(`.${sortableDraggingClass}`); + const dragOffset = $dragElement.offset(); + + triggerPointerUp($dragElement, dragOffset.left, dragOffset.top); + }, + { + dependencies: { + triggerPointerUp, + }, + }, + )(CLASS.sortableDragging); + } + resizeHeader(columnIndex: number, offset: number, needToTriggerPointerUp = true): Promise { const { getInstance } = this; From 87caf102220b6977da4a2cea9e1ee61fe47d8b34 Mon Sep 17 00:00:00 2001 From: Alyar <> Date: Fri, 30 Jan 2026 01:12:18 +0400 Subject: [PATCH 10/10] Update etalon --- ...lling-dragging-row (fluent.blue.light).png | Bin 9677 -> 9631 bytes ...-dragging-row (fluent.blue.light)_mask.png | Bin 4170 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light)_mask.png diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light).png index baf9c156a35de46eff37fd34d0a767ec22e7524c..f4ec46b97a53c04609e44f935e8c73efa50b0f91 100644 GIT binary patch literal 9631 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 O?Y?n7UTJggum1(Z0l(S+ diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light)_mask.png b/e2e/testcafe-devextreme/tests/dataGrid/common/rowDragging/etalons/T1179218-virtual-scrolling-dragging-row (fluent.blue.light)_mask.png deleted file mode 100644 index a9dbd8fb5dc780ba3ae96cb2d442e6e568275cba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4170 zcmeAS@N?(olHy`uVBq!ia0y~yU@u@`VBEpM1{B#MUbd8hK|s*c#WAFU@$Es!JOM`r z<_$hu{{R1UV6Ir>gl!8q)xPs*1S$oB2d7OT33&;i_ zXyD|9Fc^fTpbRw=C}Y$hNI(qgFq*gL#T;R1gxOt#GLRzt^Q2-wsOXOv>c{>w)$jM9 z#(&tUuD|O$EM4^v;^bKIiFZ!%C;fMOq1oa`7WFg1yc%YB$ozRvQrDX8C!fVCP%TceQB9t~`0 psvGT$Kmua4!v;+dBfe8>&tSM)sbbac@J>*Oc)I$ztaD0e0st;bmBj!6