Skip to content

Commit 9c7ab4c

Browse files
authored
[TESTS] T1330038: TypeError - DataGrid does not accept groupInterval as an array (#34064)
1 parent 8d1e789 commit 9c7ab4c

10 files changed

Lines changed: 490 additions & 54 deletions

File tree

packages/devextreme/js/__internal/filter_builder/__tests__/__mock__/model/filter_builder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';
2-
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view';
2+
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view/tree_view';
33

44
const CLASSES = {
55
filterBuilder: 'dx-filterbuilder',

packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/model/column_chooser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';
2-
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view';
2+
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view/tree_view';
33

44
export class ColumnChooserModel extends PopupModel {
55
private readonly columnChooserListClass: string;

packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/model/grid_core.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ColumnChooserModel } from './column_chooser';
1515
import { ConfirmationDialogModel } from './confirmation_dialog';
1616
import { EditFormModel } from './edit_form';
1717
import { FilterPanelModel } from './filter_panel';
18+
import { HeaderFilterModel } from './header_filter';
1819
import { DataRowModel } from './row/data_row';
1920
import { FilterRowModel } from './row/filter_row';
2021
import { GroupRowModel } from './row/group_row';
@@ -81,6 +82,12 @@ export abstract class GridCoreModel<TInstance = GridBase | CardView> {
8182
return $headerCell.find(headerFilterSelector);
8283
}
8384

85+
public openHeaderFilter(columnIndex: number): HeaderFilterModel {
86+
(this.getHeaderCellFilter(columnIndex).get(0) as HTMLElement).click();
87+
88+
return new HeaderFilterModel();
89+
}
90+
8491
public getDataRows(): NodeListOf<HTMLElement> {
8592
return this.root.querySelectorAll(`.${SELECTORS.dataRowClass}`);
8693
}

packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/model/header_filter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { PopupModel } from '@ts/ui/__tests__/__mock__/model/popup';
2+
import { TreeViewModel } from '@ts/ui/__tests__/__mock__/model/tree_view/tree_view';
23

34
const CLASSES = {
45
headerFilterMenu: 'dx-header-filter-menu',
56
listItemContent: 'dx-list-item-content',
7+
treeView: 'dx-treeview',
68
};
79

810
const SELECTORS = {
@@ -15,6 +17,12 @@ export class HeaderFilterModel extends PopupModel {
1517
return popup?.querySelector(SELECTORS.okButton) as HTMLElement;
1618
}
1719

20+
public getTreeView(): TreeViewModel {
21+
const popup = this.getPopupWrapper();
22+
const treeViewElement = popup?.querySelector(`.${CLASSES.treeView}`) as HTMLElement;
23+
return new TreeViewModel(treeViewElement);
24+
}
25+
1826
public getListItems(): HTMLElement[] {
1927
const popup = this.getPopupWrapper();
2028
const listItems = popup?.querySelectorAll(`.${CLASSES.listItemContent}`);
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import {
2+
afterEach, beforeEach, describe, expect, it,
3+
} from '@jest/globals';
4+
5+
import {
6+
afterTest, beforeTest, createDataGrid, flushAsync,
7+
} from '../../__tests__/__mock__/helpers/utils';
8+
9+
describe('headerFilter.groupInterval as array - tree popup', () => {
10+
beforeEach(beforeTest);
11+
afterEach(afterTest);
12+
13+
describe('number[] - automatic numeric buckets', () => {
14+
it('builds a tree of nested buckets and filters by the selected one', async () => {
15+
const { instance, component } = await createDataGrid({
16+
dataSource: [
17+
{ id: 1, price: 5 },
18+
{ id: 2, price: 15 },
19+
{ id: 3, price: 115 },
20+
],
21+
headerFilter: { visible: true },
22+
columns: [
23+
{
24+
dataField: 'price',
25+
dataType: 'number',
26+
headerFilter: { groupInterval: [100, 10] },
27+
},
28+
],
29+
});
30+
31+
const headerFilter = component.openHeaderFilter(0);
32+
33+
await flushAsync();
34+
await flushAsync();
35+
const treeView = headerFilter.getTreeView();
36+
treeView.expandAll();
37+
38+
expect(treeView.getStructure()).toEqual([
39+
{
40+
text: '0 - 100',
41+
children: [
42+
{ text: '0 - 10', children: [] },
43+
{ text: '10 - 20', children: [] },
44+
],
45+
},
46+
{
47+
text: '100 - 200',
48+
children: [{ text: '110 - 120', children: [] }],
49+
},
50+
]);
51+
52+
treeView.selectItemByText('0 - 100');
53+
await flushAsync();
54+
headerFilter.getOKButton().click();
55+
await flushAsync();
56+
57+
expect([...(instance.getCombinedFilter(true) as unknown[])]).toEqual([
58+
['price', '>=', 0], 'and', ['price', '<', 100],
59+
]);
60+
expect(instance.getVisibleRows().map((row) => row.data.price)).toEqual([5, 15]);
61+
});
62+
});
63+
64+
describe('string[] - hierarchical dataSource', () => {
65+
const createGrid = (): ReturnType<typeof createDataGrid> => createDataGrid({
66+
dataSource: [
67+
{
68+
id: 1, city: 'Munich', state: 'Bavaria', country: 'Germany',
69+
},
70+
{
71+
id: 2, city: 'Nuremberg', state: 'Bavaria', country: 'Germany',
72+
},
73+
{
74+
id: 3, city: 'Berlin', state: 'Berlin', country: 'Germany',
75+
},
76+
{
77+
id: 4, city: 'Lyon', state: 'Rhone', country: 'France',
78+
},
79+
],
80+
headerFilter: { visible: true },
81+
columns: [
82+
{
83+
dataField: 'city',
84+
dataType: 'string',
85+
headerFilter: {
86+
groupInterval: ['country', 'state', 'city'],
87+
dataSource: [
88+
{
89+
text: 'Germany',
90+
value: 'Germany',
91+
items: [
92+
{
93+
text: 'Bavaria',
94+
value: 'Bavaria',
95+
items: [
96+
{ text: 'Munich', value: 'Munich' },
97+
{ text: 'Nuremberg', value: 'Nuremberg' },
98+
],
99+
},
100+
{ text: 'Berlin', value: 'Berlin', items: [{ text: 'Berlin', value: 'Berlin' }] },
101+
],
102+
},
103+
{
104+
text: 'France',
105+
value: 'France',
106+
items: [{ text: 'Rhone', value: 'Rhone', items: [{ text: 'Lyon', value: 'Lyon' }] }],
107+
},
108+
],
109+
},
110+
calculateFilterExpression(filterValue, selectedFilterOperation, target) {
111+
if (target === 'headerFilter' && filterValue) {
112+
const operation = selectedFilterOperation ?? '=';
113+
return [
114+
[['country', operation, filterValue], 'or', ['state', operation, filterValue]],
115+
'or',
116+
['city', operation, filterValue],
117+
];
118+
}
119+
120+
return this.defaultCalculateFilterExpression?.(
121+
filterValue,
122+
selectedFilterOperation,
123+
target,
124+
) ?? '';
125+
},
126+
},
127+
{ dataField: 'country', dataType: 'string' },
128+
],
129+
});
130+
131+
it('builds the hierarchy tree from the dataSource', async () => {
132+
const { component } = await createGrid();
133+
134+
const headerFilter = component.openHeaderFilter(0);
135+
136+
await flushAsync();
137+
await flushAsync();
138+
const treeView = headerFilter.getTreeView();
139+
treeView.expandAll();
140+
141+
expect(treeView.getStructure()).toEqual([
142+
{
143+
text: 'Germany',
144+
children: [
145+
{
146+
text: 'Bavaria',
147+
children: [
148+
{ text: 'Munich', children: [] },
149+
{ text: 'Nuremberg', children: [] },
150+
],
151+
},
152+
{ text: 'Berlin', children: [{ text: 'Berlin', children: [] }] },
153+
],
154+
},
155+
{
156+
text: 'France',
157+
children: [{ text: 'Rhone', children: [{ text: 'Lyon', children: [] }] }],
158+
},
159+
]);
160+
});
161+
162+
it.each([
163+
{ node: 'Germany', cities: ['Munich', 'Nuremberg', 'Berlin'] },
164+
{ node: 'Bavaria', cities: ['Munich', 'Nuremberg'] },
165+
{ node: 'Munich', cities: ['Munich'] },
166+
])('filters by the selected "$node" node', async ({ node, cities }) => {
167+
const { instance, component } = await createGrid();
168+
169+
const headerFilter = component.openHeaderFilter(0);
170+
171+
await flushAsync();
172+
await flushAsync();
173+
const treeView = headerFilter.getTreeView();
174+
treeView.expandAll();
175+
treeView.selectItemByText(node);
176+
await flushAsync();
177+
headerFilter.getOKButton().click();
178+
await flushAsync();
179+
180+
expect([...(instance.getCombinedFilter(true) as unknown[])]).toEqual([
181+
[['country', '=', node], 'or', ['state', '=', node]],
182+
'or',
183+
['city', '=', node],
184+
]);
185+
expect(instance.getVisibleRows().map((row) => row.data.city)).toEqual(cities);
186+
});
187+
});
188+
});

0 commit comments

Comments
 (0)