diff --git a/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts b/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts index e03e6b1753d2..9318b076e998 100644 --- a/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/data_grid/focus/m_focus.ts @@ -2,7 +2,7 @@ import { equalByValue } from '@js/core/utils/common'; import { compileGetter } from '@js/core/utils/data'; import { Deferred } from '@js/core/utils/deferred'; import type { DataController } from '@ts/grids/grid_core/data_controller/data_controller'; -import { focusModule } from '@ts/grids/grid_core/focus/m_focus'; +import { focusModule } from '@ts/grids/grid_core/focus/focus_module'; import type { ModuleType } from '@ts/grids/grid_core/m_types'; import type { GroupingDataControllerExtension, GroupingDataSourceAdapter } from '../grouping/m_grouping'; diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts index 6c98e370ae1f..7019fe596338 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_controller/data_controller.ts @@ -4,7 +4,6 @@ import { logger } from '@js/core/utils/console'; import type { DeferredObj } from '@js/core/utils/deferred'; import { Deferred, when } from '@js/core/utils/deferred'; import { isDefined } from '@js/core/utils/type'; -import type { StoreChange } from '@js/data/store'; import errors from '@js/ui/widget/ui.errors'; import { findChanges } from '@ts/core/utils/m_array_compare'; import { fromPromise } from '@ts/core/utils/m_deferred'; @@ -110,8 +109,6 @@ export class DataController extends modules.Controller { public pageChanged!: Callback<[number?]>; - public pushed!: Callback<[StoreChange[]]>; - public changed!: Callback<[DataChange]>; public loadingChanged!: Callback<[boolean, string?]>; @@ -129,8 +126,6 @@ export class DataController extends modules.Controller { private loadErrorHandlerProxy!: (e: Error | string) => void; - private dataPushedHandlerProxy!: (changes: StoreChange[]) => void; - private dataChangedHandlerProxy!: (e?: ChangedEvent) => void; public init(): void { @@ -144,7 +139,6 @@ export class DataController extends modules.Controller { this._currentOperationTypes = null; this.dataChangedHandlerProxy = this.dataChangedHandler.bind(this); this.loadErrorHandlerProxy = this.loadErrorHandler.bind(this); - this.dataPushedHandlerProxy = this.dataPushedHandler.bind(this); this._columnsController.columnsChanged.add(this.columnsChangedHandler.bind(this)); @@ -181,7 +175,7 @@ export class DataController extends modules.Controller { } protected callbackNames(): string[] { - return ['changed', 'loadingChanged', 'dataErrorOccurred', 'pageChanged', 'dataSourceChanged', 'pushed', 'rowIndicesChanged']; + return ['changed', 'loadingChanged', 'dataErrorOccurred', 'pageChanged', 'dataSourceChanged', 'rowIndicesChanged']; } protected callbackFlags(name?: string): CallbackFlags | undefined { @@ -608,10 +602,6 @@ export class DataController extends modules.Controller { this.dataErrorOccurred.fire(e); } - protected dataPushedHandler(changes: StoreChange[]): void { - this.pushed.fire(changes); - } - public fireError(...args: unknown[]): void { this.dataErrorOccurred.fire(errors.Error(...args)); } @@ -1302,7 +1292,6 @@ export class DataController extends modules.Controller { dataSourceAdapter.loadError.add(this.loadErrorHandlerProxy); dataSourceAdapter.customizeStoreLoadOptions.add(this.customizeStoreLoadOptionsHandler); dataSourceAdapter.changing.add(this.changingHandler); - dataSourceAdapter.pushed.add(this.dataPushedHandlerProxy); } private unsubscribeFromDataSource(dataSourceAdapter: DataSourceAdapter): void { @@ -1311,7 +1300,6 @@ export class DataController extends modules.Controller { dataSourceAdapter.loadError.remove(this.loadErrorHandlerProxy); dataSourceAdapter.customizeStoreLoadOptions.remove(this.customizeStoreLoadOptionsHandler); dataSourceAdapter.changing.remove(this.changingHandler); - dataSourceAdapter.pushed.remove(this.dataPushedHandlerProxy); } private setDataSource(dataSource: DataSource): void { @@ -1628,10 +1616,6 @@ export class DataController extends modules.Controller { return this._dataSource?.reload(reload, changesOnly) as DeferredObj; } - public push(changes: StoreChange[], fromStore = false): void { - this._dataSource?.push(changes, fromStore); - } - private itemsCount(): number { return (this._dataSource ? this._dataSource.itemsCount() : 0); } diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source/__tests__/data_source_controller.test.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source/__tests__/data_source_controller.test.ts index d64d70ec46ab..eb6460c17abc 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source/__tests__/data_source_controller.test.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source/__tests__/data_source_controller.test.ts @@ -5,6 +5,9 @@ import { jest, } from '@jest/globals'; import { DataSource as DataSourceClass } from '@js/common/data/data_source/data_source'; +import type { Callback } from '@js/core/utils/callbacks'; +import Callbacks from '@js/core/utils/callbacks'; +import type { StoreChange } from '@js/data/store'; import type Store from '@ts/data/abstract_store'; import type { StoreKey } from '@ts/data/abstract_store'; import type { DataSource } from '@ts/data/data_source/data_source'; @@ -24,6 +27,8 @@ interface AdapterStub { getDataIndexGetter: jest.Mock<() => (data: RawItemData) => number>; dispose: jest.Mock<(isShared?: boolean) => void>; init: jest.Mock<(dataSource: DataSource) => void>; + push: jest.Mock<(changes: StoreChange[], fromStore: boolean) => void>; + pushed: Callback<[StoreChange[]]>; } interface ProviderStub { @@ -40,6 +45,8 @@ const createAdapterStub = (marker: string): AdapterStub => ({ getDataIndexGetter: jest.fn(() => (): number => 0), dispose: jest.fn(), init: jest.fn(), + push: jest.fn(), + pushed: Callbacks(), }); const asAdapter = (stub: AdapterStub): DataSourceAdapter => stub as unknown as DataSourceAdapter; @@ -87,6 +94,8 @@ const asProvider = ( const SOURCE = { marker: 'source' } as unknown as DataSource; +const CHANGES: StoreChange[] = [{ type: 'remove', key: 1 }]; + const withProvider = (adapter: AdapterStub): { controller: TestDataSourceController; component: InternalGrid; @@ -258,6 +267,7 @@ describe('DataSourceController', () => { controller.key(); controller.remoteOperations(); controller.getDataIndexGetter(); + controller.push(CHANGES); controller.disposeAdapter(); expect(getController).not.toHaveBeenCalled(); @@ -490,4 +500,63 @@ describe('DataSourceController', () => { expect(getController).not.toHaveBeenCalled(); }); }); + + describe('the pushed callback', () => { + it('re-fires what the adapter pushed', () => { + const { controller, adapter } = withAdapter(); + const handler = jest.fn<(changes: StoreChange[]) => void>(); + + controller.pushed.add(handler); + adapter.pushed.fire(CHANGES); + + expect(handler).toHaveBeenCalledTimes(1); + expect(handler).toHaveBeenCalledWith(CHANGES); + }); + + it('goes quiet once the adapter is disposed', () => { + const { controller, adapter } = withAdapter(); + const handler = jest.fn<(changes: StoreChange[]) => void>(); + + controller.pushed.add(handler); + controller.disposeAdapter(); + adapter.pushed.fire(CHANGES); + + expect(handler).not.toHaveBeenCalled(); + }); + + it('follows the adapter that replaced the previous one', () => { + const { controller, provider } = withAdapter(); + const second = createAdapterStub('second'); + const handler = jest.fn<(changes: StoreChange[]) => void>(); + + provider.nextAdapter = second; + controller.createAdapter(SOURCE); + controller.pushed.add(handler); + second.pushed.fire(CHANGES); + + expect(handler).toHaveBeenCalledTimes(1); + }); + }); + + describe('push', () => { + it('delegates to the adapter, defaulting fromStore to false', () => { + const { controller, adapter } = withAdapter(); + + controller.push(CHANGES); + + expect(adapter.push).toHaveBeenCalledWith(CHANGES, false); + }); + + it('passes fromStore through', () => { + const { controller, adapter } = withAdapter(); + + controller.push(CHANGES, true); + + expect(adapter.push).toHaveBeenCalledWith(CHANGES, true); + }); + + it('does nothing when there is no adapter', () => { + expect(() => createController().push(CHANGES)).not.toThrow(); + }); + }); }); diff --git a/packages/devextreme/js/__internal/grids/grid_core/data_source/data_source_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/data_source/data_source_controller.ts index 7868bde16226..f689aeab045b 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/data_source/data_source_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/data_source/data_source_controller.ts @@ -1,6 +1,8 @@ import { DataSource as DataSourceClass } from '@js/common/data/data_source/data_source'; import { normalizeDataSourceOptions } from '@js/common/data/data_source/utils'; +import type { Callback } from '@js/core/utils/callbacks'; import { extend } from '@js/core/utils/extend'; +import type { StoreChange } from '@js/data/store'; import type Store from '@ts/data/abstract_store'; import type { StoreKey } from '@ts/data/abstract_store'; import type { DataSource } from '@ts/data/data_source/data_source'; @@ -20,6 +22,10 @@ export class DataSourceController< private isShared = false; + public pushed!: Callback<[StoreChange[]]>; + + private readonly dataPushedHandlerProxy = this.dataPushedHandler.bind(this); + /** * @extended: DataGrid's and TreeList's data_source_controller */ @@ -27,6 +33,10 @@ export class DataSourceController< throw new Error('Method not implemented.'); } + protected callbackNames(): string[] { + return ['pushed']; + } + public publicMethods(): string[] { return ['getDataSource', 'keyOf']; } @@ -77,8 +87,11 @@ export class DataSourceController< const adapter = this.getAdapterProvider().create(this.component); adapter.init(dataSource); + this.adapter = adapter; + adapter.pushed.add(this.dataPushedHandlerProxy); + return adapter; } @@ -91,14 +104,26 @@ export class DataSourceController< } public disposeAdapter(): void { + this.adapter?.pushed.remove(this.dataPushedHandlerProxy); this.adapter?.dispose(this.isShared); this.adapter = null; } + /** + * @extended: focus + */ + protected dataPushedHandler(changes: StoreChange[]): void { + this.pushed.fire(changes); + } + public store(): Store | undefined { return this.adapter?.store(); } + public push(changes: StoreChange[], fromStore = false): void { + this.adapter?.push(changes, fromStore); + } + /** * The key the component identifies rows by. Not interchangeable with `store()?.key()` (TreeList) * Callers that need what the store itself can identify a row by have to ask the store. diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts index 9d25d2a22197..bdf0473b3fb6 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts @@ -1877,7 +1877,7 @@ class EditingControllerImpl extends modules.ViewController { const isFullRefresh = refreshMode !== 'reshape' && refreshMode !== 'repaint'; if (!isFullRefresh) { - dataController.push(dataChanges); + this.dataSourceController.push(dataChanges); } when(dataController.refresh({ diff --git a/packages/devextreme/js/__internal/grids/grid_core/focus/extenders/__tests__/focus_data_source_controller.integration.test.ts b/packages/devextreme/js/__internal/grids/grid_core/focus/extenders/__tests__/focus_data_source_controller.integration.test.ts new file mode 100644 index 000000000000..8c3510eebd06 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/focus/extenders/__tests__/focus_data_source_controller.integration.test.ts @@ -0,0 +1,80 @@ +import { + afterEach, beforeEach, describe, expect, it, +} from '@jest/globals'; +import { + afterTest, beforeTest, createDataGrid, flushAsync, +} from '@ts/grids/grid_core/__tests__/__mock__/helpers/utils'; + +describe('Focus data source controller', () => { + beforeEach(beforeTest); + afterEach(afterTest); + + describe("when a push empties the grid and a pushed subscriber's own change cycle runs first", () => { + it('still resets the focused row', async () => { + const { instance } = await createDataGrid({ + dataSource: { + store: { + type: 'array', + key: 'id', + data: [ + { id: 1, name: 'Item 1' }, + { id: 2, name: 'Item 2' }, + ], + }, + reshapeOnPush: true, + pushAggregationTimeout: 0, + }, + focusedRowEnabled: true, + focusedRowKey: 1, + selection: { mode: 'multiple' }, + selectedRowKeys: [1], + columns: ['id', 'name'], + }); + + instance.getDataSource().store().push([ + { type: 'remove', key: 1 }, + { type: 'remove', key: 2 }, + ]); + await flushAsync(); + + expect(instance.getVisibleRows()).toHaveLength(0); + expect(instance.getSelectedRowKeys()).toEqual([]); + expect(instance.option('focusedRowKey')).toBeNull(); + expect(instance.option('focusedRowIndex')).toBe(-1); + }); + }); + + describe('when an unrelated change empties the grid after an earlier push was handled', () => { + it('keeps the focused row, because one push forces exactly one update', async () => { + const { instance } = await createDataGrid({ + dataSource: { + store: { + type: 'array', + key: 'id', + data: [ + { id: 1, name: 'Item 1' }, + { id: 2, name: 'Item 2' }, + { id: 3, name: 'Item 3' }, + ], + }, + reshapeOnPush: true, + pushAggregationTimeout: 0, + }, + focusedRowEnabled: true, + focusedRowKey: 2, + columns: ['id', 'name'], + }); + + instance.getDataSource().store().push([ + { type: 'update', key: 3, data: { id: 3, name: 'Item 3 renamed' } }, + ]); + await flushAsync(); + + instance.filter(['name', '=', 'nothing matches']); + await flushAsync(); + + expect(instance.getVisibleRows()).toHaveLength(0); + expect(instance.option('focusedRowKey')).toBe(2); + }); + }); +}); diff --git a/packages/devextreme/js/__internal/grids/grid_core/focus/extenders/focus_data_source_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/focus/extenders/focus_data_source_controller.ts new file mode 100644 index 000000000000..587e4f1a3f95 --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/focus/extenders/focus_data_source_controller.ts @@ -0,0 +1,32 @@ +import { isDefined } from '@js/core/utils/type'; +import type { StoreChange } from '@js/data/store'; +import type { DataSourceController } from '@ts/grids/grid_core/data_source/data_source_controller'; +import type { ModuleType } from '@ts/grids/grid_core/m_types'; + +export interface FocusDataSourceControllerExtension { + consumeDataPushed: () => boolean; +} + +export const focusDataSourceControllerExtender = ( + Base: ModuleType, +): ModuleType< + DataSourceController & FocusDataSourceControllerExtension +> => class FocusDataSourceControllerExtender extends Base { + private isDataPushed = false; + + public consumeDataPushed(): boolean { + const wasDataPushed = this.isDataPushed; + + this.isDataPushed = false; + + return wasDataPushed; + } + + protected dataPushedHandler(changes: StoreChange[]): void { + super.dataPushedHandler(changes); + + const focusedRowKey = this.option('focusedRowKey'); + + this.isDataPushed = isDefined(focusedRowKey) && !!changes.length; + } +}; diff --git a/packages/devextreme/js/__internal/grids/grid_core/focus/focus_module.ts b/packages/devextreme/js/__internal/grids/grid_core/focus/focus_module.ts new file mode 100644 index 000000000000..b247b7eef03d --- /dev/null +++ b/packages/devextreme/js/__internal/grids/grid_core/focus/focus_module.ts @@ -0,0 +1,44 @@ +import type { InternalGridOptions } from '@ts/grids/grid_core/m_types'; + +import { + focusDataSourceControllerExtender, +} from './extenders/focus_data_source_controller'; +import { + columns, + editing, + FocusController, + focusDataControllerExtender, + focusEditorFactoryViewControllerExtender, + keyboardNavigation, + rowsView, +} from './m_focus'; + +type FocusDefaultProperties = 'focusedRowEnabled' | 'autoNavigateToFocusedRow' | 'focusedRowKey' | 'focusedRowIndex' | 'focusedColumnIndex'; + +export const focusModule = { + defaultOptions(): Pick { + return { + focusedRowEnabled: false, + autoNavigateToFocusedRow: true, + focusedRowKey: null, + focusedRowIndex: -1, + focusedColumnIndex: -1, + }; + }, + controllers: { + focus: FocusController, + }, + extenders: { + controllers: { + keyboardNavigation, + editorFactory: focusEditorFactoryViewControllerExtender, + columns, + data: focusDataControllerExtender, + dataSource: focusDataSourceControllerExtender, + editing, + }, + views: { + rowsView, + }, + }, +}; diff --git a/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts b/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts index 91bc8a1cc790..cc5fb7d74f52 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/focus/m_focus.ts @@ -4,7 +4,6 @@ import { equalByValue } from '@js/core/utils/common'; import { Deferred, type DeferredObj, when } from '@js/core/utils/deferred'; import { each } from '@js/core/utils/iterator'; import { isBoolean, isDefined } from '@js/core/utils/type'; -import type { StoreChange } from '@js/data/store'; import type { DataSourceController } from '@ts/grids/grid_core/data_source/data_source_controller'; import type { Key } from '@ts/grids/new/grid_core/data_controller/types'; @@ -19,6 +18,7 @@ import type { ModuleType } from '../m_types'; import gridCoreUtils from '../m_utils'; import type { RowsView } from '../views/m_rows_view'; import type { VirtualScrollingDataControllerExtension } from '../virtual_scrolling/index'; +import type { FocusDataSourceControllerExtension } from './extenders/focus_data_source_controller'; import { UiGridCoreFocusUtils } from './m_focus_utils'; const ROW_FOCUSED_CLASS = 'dx-row-focused'; @@ -446,7 +446,7 @@ export class FocusController extends core.ViewController { } } -const keyboardNavigation = (Base: ModuleType) => class FocusKeyboardNavigationExtender extends Base { +export const keyboardNavigation = (Base: ModuleType) => class FocusKeyboardNavigationExtender extends Base { public init() { const rowIndex = this.option('focusedRowIndex'); const columnIndex = this.option('focusedColumnIndex'); @@ -505,7 +505,7 @@ const keyboardNavigation = (Base: ModuleType) => c } }; -const focusEditorFactoryViewControllerExtender = ( +export const focusEditorFactoryViewControllerExtender = ( Base: ModuleType, ) => class FocusEditorFactoryExtender extends Base { protected keyboardNavigationController!: KeyboardNavigationController; @@ -536,7 +536,7 @@ const focusEditorFactoryViewControllerExtender = ( } }; -const columns = (Base: ModuleType) => class FocusColumnsExtender extends Base { +export const columns = (Base: ModuleType) => class FocusColumnsExtender extends Base { protected focusController!: FocusController; protected dataSourceController!: DataSourceController; @@ -573,10 +573,11 @@ const columns = (Base: ModuleType) => class FocusColumnsExten } }; -const focusDataControllerExtender = ( +export const focusDataControllerExtender = ( Base: ModuleType>, ) => class FocusDataControllerExtender extends Base { - private _isDataPushed = false; + protected declare dataSourceController: DataSourceController + & FocusDataSourceControllerExtension; private _lastRenderingPageIndex?: number; @@ -602,9 +603,7 @@ const focusDataControllerExtender = ( protected _fireChanged(e) { super._fireChanged(e); - const forceUpdateFocusedRow = this._isDataPushed; - - this._isDataPushed = false; + const forceUpdateFocusedRow = this.dataSourceController.consumeDataPushed(); if (this.option('focusedRowEnabled') && this._dataSource) { const isPartialUpdate = e.changeType === 'update' && e.repaintChangesOnly; @@ -644,14 +643,6 @@ const focusDataControllerExtender = ( } } - protected dataPushedHandler(changes: StoreChange[]): void { - super.dataPushedHandler(changes); - - const focusedRowKey = this.option('focusedRowKey'); - - this._isDataPushed = isDefined(focusedRowKey) && !!changes.length; - } - private _updatePageIndexes() { const prevRenderingPageIndex = this._lastRenderingPageIndex || 0; const renderingPageIndex = this._rowsScrollController ? this._rowsScrollController.pageIndex() : 0; @@ -899,7 +890,7 @@ const focusDataControllerExtender = ( } }; -const editing = (Base: ModuleType) => class FocusEditingControllerExtender extends Base { +export const editing = (Base: ModuleType) => class FocusEditingControllerExtender extends Base { protected _deleteRowCore(rowIndex) { // @ts-expect-error const deferred = super._deleteRowCore.apply(this, arguments); @@ -916,7 +907,7 @@ const editing = (Base: ModuleType) => class FocusEditingContr } }; -const rowsView = (Base: ModuleType) => class RowsViewFocusController extends Base { +export const rowsView = (Base: ModuleType) => class RowsViewFocusController extends Base { private _scrollToFocusOnResize: any; protected _createRow(row) { @@ -1061,41 +1052,3 @@ const rowsView = (Base: ModuleType) => class RowsViewFocusController e return d.resolve(); } }; - -export const focusModule = { - defaultOptions() { - return { - focusedRowEnabled: false, - - autoNavigateToFocusedRow: true, - - focusedRowKey: null, - - focusedRowIndex: -1, - - focusedColumnIndex: -1, - }; - }, - - controllers: { - focus: FocusController, - }, - - extenders: { - controllers: { - keyboardNavigation, - - editorFactory: focusEditorFactoryViewControllerExtender, - - columns, - - data: focusDataControllerExtender, - - editing, - }, - - views: { - rowsView, - }, - }, -}; diff --git a/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts b/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts index c3b0f1b197ad..b702b8cdba9c 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/selection/m_selection.ts @@ -159,7 +159,7 @@ export class SelectionController extends modules.Controller { if (!this._dataPushedHandler) { this._dataPushedHandler = this._handleDataPushed.bind(this); - this._dataController.pushed.add(this._dataPushedHandler); + this.dataSourceController.pushed.add(this._dataPushedHandler); } } diff --git a/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts b/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts index dcd46912a52f..d8163f931d51 100644 --- a/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts +++ b/packages/devextreme/js/__internal/grids/tree_list/m_focus.ts @@ -1,5 +1,5 @@ import { Deferred } from '@js/core/utils/deferred'; -import { focusModule } from '@ts/grids/grid_core/focus/m_focus'; +import { focusModule } from '@ts/grids/grid_core/focus/focus_module'; import type { DataController } from '../grid_core/data_controller/data_controller'; import type { ModuleType } from '../grid_core/m_types'; diff --git a/packages/devextreme/testing/helpers/gridBaseMocks.js b/packages/devextreme/testing/helpers/gridBaseMocks.js index 36b48f913316..9936e9c5d12d 100644 --- a/packages/devextreme/testing/helpers/gridBaseMocks.js +++ b/packages/devextreme/testing/helpers/gridBaseMocks.js @@ -60,6 +60,9 @@ module.exports = function($, gridCore, columnResizingReordering, domUtils, commo store: function() { return options.store; }, + push: function() { + }, + pushed: $.Callbacks(), load: function(loadOptions) { return itemsStore().load(loadOptions); }, @@ -300,7 +303,6 @@ module.exports = function($, gridCore, columnResizingReordering, domUtils, commo dataErrorOccurred: $.Callbacks('stopOnFalse'), pageChanged: $.Callbacks(), dataSourceChanged: $.Callbacks(), - pushed: $.Callbacks(), rowIndicesChanged: $.Callbacks(), fireError: function() { }, loadViewport: commonUtils.noop, diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataController.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataController.tests.js index f018d1e4c3f9..5831f6a67770 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataController.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataController.tests.js @@ -213,7 +213,7 @@ QUnit.module('Initialization', { beforeEach: setupModule, afterEach: teardownMod ]; const dataSource = createDataSource(array, { key: 'id' }); - this.dataController.pushed.add(pushedSpy); + this.dataSourceController.pushed.add(pushedSpy); // assert assert.strictEqual(pushedSpy.callCount, 0, 'the pushed callback was not called'); @@ -239,7 +239,7 @@ QUnit.module('Initialization', { beforeEach: setupModule, afterEach: teardownMod ]; let dataSource = createDataSource(array, { key: 'id' }); - this.dataController.dataPushedHandlerProxy = dataPushedHandlerSpy; + this.dataSourceController.dataPushedHandlerProxy = dataPushedHandlerSpy; this.dataController.setDataSource(dataSource); dataSource = this.dataSourceController.getAdapter(); dataSource.load();