Skip to content

Commit bebe8f1

Browse files
SelectBox skips pages after reloading data (T1274576) (DevExpress#28933)
1 parent 9cb35af commit bebe8f1

File tree

5 files changed

+175
-32
lines changed

5 files changed

+175
-32
lines changed

e2e/testcafe-devextreme/tests/editors/selectBox/common.ts

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { Selector } from 'testcafe';
1+
import { ClientFunction, Selector } from 'testcafe';
22
import { createScreenshotsComparer } from 'devextreme-screenshot-comparer';
33
import SelectBox from 'devextreme-testcafe-models/selectBox';
44
import { testScreenshot } from '../../../helpers/themeUtils';
55
import { appendElementTo, setStyleAttribute } from '../../../helpers/domUtils';
66
import url from '../../../helpers/getPageUrl';
77
import { createWidget } from '../../../helpers/createWidget';
8+
import { changeTheme } from '../../../helpers/changeTheme';
89

910
fixture.disablePageReloads`SelectBox placeholder`
1011
.page(url(__dirname, '../../container.html'));
@@ -28,3 +29,96 @@ test('Placeholder is visible after items option change when value is not chosen
2829
placeholder: 'Choose a value',
2930
}, '#selectBox');
3031
});
32+
33+
test('Pages should be loaded consistently after closing the dropdown popup and filtering the data (T1274576)', async (t) => {
34+
const selectBox = new SelectBox('#selectBox');
35+
36+
await selectBox.option('opened', true);
37+
38+
const list = await selectBox.getList();
39+
const items = list.getItems();
40+
41+
await t.expect(items.count)
42+
.eql(12)
43+
.expect(items.nth(0).textContent)
44+
.eql('item 1')
45+
.expect(items.nth(11).textContent)
46+
.eql('item 12');
47+
48+
const scrollingDistance = 50;
49+
await list.scrollTo(scrollingDistance);
50+
await t.wait(500);
51+
52+
await t.click(Selector('body'));
53+
54+
const { getInstance } = selectBox;
55+
56+
await ClientFunction(
57+
() => {
58+
const dataSource = (getInstance() as any).getDataSource();
59+
dataSource.filter(['anotherId', '=', 2]);
60+
dataSource.load();
61+
},
62+
{ dependencies: { getInstance } },
63+
)();
64+
await t.wait(500);
65+
66+
await selectBox.option('opened', true);
67+
68+
await t.wait(500);
69+
70+
await t.expect(items.count)
71+
.eql(12)
72+
.expect(items.nth(0).textContent)
73+
.eql('item 2')
74+
.expect(items.nth(11).textContent)
75+
.eql('item 24');
76+
}).before(async () => {
77+
await changeTheme(`${process.env.theme}.compact`);
78+
await appendElementTo('#container', 'div', 'selectBox');
79+
await setStyleAttribute(Selector('#container'), 'box-sizing: border-box; width: 300px; height: 100px; padding: 8px;');
80+
81+
return createWidget('dxSelectBox', () => {
82+
const data: { id: number; text: string; anotherId: number }[] = [];
83+
84+
for (let index = 0; index < 100; index += 1) {
85+
data.push({
86+
id: index + 1,
87+
text: `item ${index + 1}`,
88+
anotherId: index % 2 === 0 ? 1 : 2,
89+
});
90+
}
91+
92+
const sampleAPI = new (window as any).DevExpress.data.ArrayStore({ key: 'id', data });
93+
const store = new (window as any).DevExpress.data.CustomStore({
94+
key: 'id',
95+
load(loadOptions) {
96+
return new Promise((resolve) => {
97+
setTimeout(() => {
98+
sampleAPI.load(loadOptions).done((items) => {
99+
resolve(items);
100+
});
101+
}, 100);
102+
});
103+
},
104+
totalCount(loadOptions) {
105+
return sampleAPI.totalCount(loadOptions);
106+
},
107+
byKey(key) {
108+
return sampleAPI.byKey(key);
109+
},
110+
});
111+
112+
return {
113+
dataSource: {
114+
store,
115+
paginate: true,
116+
pageSize: 6,
117+
},
118+
valueExpr: 'id',
119+
displayExpr: 'text',
120+
};
121+
}, '#selectBox');
122+
}).after(async () => {
123+
await changeTheme(`${process.env.theme}`);
124+
});
Loading

packages/devextreme/js/__internal/ui/scroll_view/m_scrollable.simulated.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ const KEY_CODES = {
6565
TAB: 'tab',
6666
};
6767

68+
interface ScrollByDelta { x: number; y: number }
69+
6870
const InertiaAnimator = Animator.inherit({
6971
ctor(scroller) {
7072
this.callBase();
@@ -352,7 +354,10 @@ export const Scroller = Class.inherit({
352354
this._scrollStep(delta);
353355
},
354356

355-
_scrollByHandler(delta) {
357+
_scrollByHandler(delta: ScrollByDelta): void {
358+
if (!delta.x && !delta.y) {
359+
return;
360+
}
356361
this._scrollBy(delta);
357362
this._scrollComplete();
358363
},

packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/selectBox.tests.js

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,33 @@ const EMPTY_MESSAGE_CLASS = 'dx-empty-message';
2222

2323
QUnit.testStart(() => {
2424
const markup =
25-
'<div id="qunit-fixture">\
26-
<div id="selectBox"></div>\
27-
\
28-
<div id="selectBoxWithItemTemplate">\
29-
<div data-options="dxTemplate: { name: \'item\'}">\
30-
itemTemplate\
31-
</div>\
25+
'<div id="selectBox"></div>\
26+
\
27+
<div id="selectBoxWithItemTemplate">\
28+
<div data-options="dxTemplate: { name: \'item\'}">\
29+
itemTemplate\
3230
</div>\
33-
\
34-
<div id="selectBoxFieldTemplateWithoutTextBox">\
35-
<div data-options="dxTemplate: { name: \'field\' }">\
36-
<span>test</span>\
37-
</div>\
31+
</div>\
32+
\
33+
<div id="selectBoxFieldTemplateWithoutTextBox">\
34+
<div data-options="dxTemplate: { name: \'field\' }">\
35+
<span>test</span>\
3836
</div>\
37+
</div>\
3938
\
40-
<div id="selectBoxFieldTemplate">\
41-
<div data-options="dxTemplate: { name: \'field\' }">\
42-
fieldTemplate\
43-
</div>\
44-
<div data-options="dxTemplate: { name: \'item\'}">\
45-
itemTemplate\
46-
</div>\
39+
<div id="selectBoxFieldTemplate">\
40+
<div data-options="dxTemplate: { name: \'field\' }">\
41+
fieldTemplate\
4742
</div>\
48-
\
49-
<div id="selectBoxWithoutScrollWrapper">\
50-
<div id="selectBoxWithoutScroll"></div>\
43+
<div data-options="dxTemplate: { name: \'item\'}">\
44+
itemTemplate\
5145
</div>\
52-
<div id="test-container"></div>\
53-
</div>';
46+
</div>\
47+
\
48+
<div id="selectBoxWithoutScrollWrapper">\
49+
<div id="selectBoxWithoutScroll"></div>\
50+
</div>\
51+
<div id="test-container"></div>';
5452

5553
$('#qunit-fixture').html(markup);
5654

packages/devextreme/testing/tests/DevExpress.ui.widgets/scrollView.tests.js

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,16 +242,17 @@ QUnit.module('dimension', moduleConfig, () => {
242242
});
243243

244244
QUnit.module('onReachBottom', () => {
245-
[0.33, 0.5, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.2, 1.25, 1.34, 1.5, 1.875, 2.25, 2.65].forEach((browserZoom) => {
246-
[
247-
{ useNative: false, refreshStrategy: 'simulated' },
248-
{ useNative: true, refreshStrategy: 'pullDown' },
249-
{ useNative: true, refreshStrategy: 'swipeDown' },
250-
].forEach(({ useNative, refreshStrategy }) => {
245+
[
246+
{ useNative: false, refreshStrategy: 'simulated' },
247+
{ useNative: true, refreshStrategy: 'pullDown' },
248+
{ useNative: true, refreshStrategy: 'swipeDown' },
249+
].forEach(({ useNative, refreshStrategy }) => {
250+
[0.33, 0.5, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.2, 1.25, 1.34, 1.5, 1.875, 2.25, 2.65].forEach((browserZoom) => {
251251
const cssStyles = {
252252
transform: `scale(${browserZoom})`,
253253
transformOrigin: '0 0',
254254
};
255+
255256
// T1032842
256257
QUnit.test(`Start loading when reaching bottom boundary with wrapperStyles: ${JSON.stringify(cssStyles)}, useNative: ${useNative}, refreshStrategy: ${refreshStrategy}`, function(assert) {
257258
assert.expect(1);
@@ -288,6 +289,51 @@ QUnit.module('onReachBottom', () => {
288289
scrollView.scrollToElement($lastItem);
289290
});
290291
});
292+
293+
QUnit.test(`ReachBottom should not be fired after change visibility if content is not overflowed, useNative: ${useNative}, refreshStrategy: ${refreshStrategy}`, function(assert) {
294+
const onReachBottomHandler = sinon.spy();
295+
296+
const $scrollView = $('<div>').appendTo('#qunit-fixture');
297+
const $contentWrapper = $('<div>').appendTo($scrollView);
298+
299+
for(let i = 0; i < 40; i++) {
300+
$('<div>')
301+
.addClass('item')
302+
.text(`item${i}`)
303+
.css({ height: 20, width: '100%' })
304+
.appendTo($contentWrapper);
305+
}
306+
307+
$scrollView.appendTo('#qunit-fixture');
308+
309+
const scrollView = $scrollView.dxScrollView({
310+
useNative,
311+
direction: 'vertical',
312+
height: 355.5,
313+
width: '100%',
314+
showScrollbar: 'always',
315+
refreshStrategy,
316+
onReachBottom: onReachBottomHandler,
317+
reachBottomText: 'Updating...'
318+
}).dxScrollView('instance');
319+
320+
scrollView.scrollTo(100);
321+
322+
$(scrollView.element()).trigger('dxhiding');
323+
324+
$contentWrapper.empty();
325+
for(let i = 0; i < 10; i++) {
326+
$('<div>')
327+
.addClass('item')
328+
.text(`item${i}`)
329+
.css({ height: 20, width: '100%' })
330+
.appendTo($contentWrapper);
331+
}
332+
333+
$(scrollView.element()).trigger('dxshown');
334+
335+
assert.strictEqual(onReachBottomHandler.callCount, 0, 'onReachBottom action should not have been triggered');
336+
});
291337
});
292338
});
293339

0 commit comments

Comments
 (0)