Skip to content

Commit 5f397d3

Browse files
lukasbrizabedrich-schindler
authored andcommitted
Transform ScrollView jest tests into playwright (#598)
1 parent d7ea85f commit 5f397d3

File tree

64 files changed

+868
-152
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+868
-152
lines changed
Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
import React from 'react';
2+
import {
3+
expect,
4+
test,
5+
} from '@playwright/experimental-ct-react';
6+
import {
7+
mixPropTests,
8+
propTests,
9+
} from '../../../../tests/playwright';
10+
import {
11+
ScrollViewForDetectEndAutoscrollTest,
12+
ScrollViewForRefTest,
13+
ScrollViewForTest,
14+
} from './ScrollView.story';
15+
import { directionPropTest } from './_propTests/directionPropTest';
16+
import { nextArrowColorPropTest } from './_propTests/nextArrowColorPropTest';
17+
import { nextArrowElementPropTest } from './_propTests/nextArrowElementPropTest';
18+
import { prevArrowColorPropTest } from './_propTests/prevArrowColorPropTest';
19+
import { prevArrowElementPropTest } from './_propTests/prevArrowElementPropTest';
20+
import { endShadowSizePropTest } from './_propTests/endShadowSizePropTest';
21+
import { startShadowSizePropTest } from './_propTests/startShadowSizePropTest';
22+
import { mixArrowsDirectionPropTest } from './_propTests/mixes/mixArrowsDirectionPropTest';
23+
import { mixEndShadowBackgroundDirectionPropTest } from './_propTests/mixes/mixEndShadowBackgroundDirectionPropTest';
24+
import { mixStartShadowBackgroundDirectionPropTest } from './_propTests/mixes/mixStartShadowBackgroundDirectionPropTest';
25+
import { shadowsPropTest } from './_propTests/shadowsPropTest';
26+
import type { ExtendedWindow } from './types';
27+
28+
test.describe('ScrollView', () => {
29+
test.describe('visual', () => {
30+
[
31+
...propTests.defaultComponentPropTest,
32+
...mixArrowsDirectionPropTest,
33+
...mixEndShadowBackgroundDirectionPropTest,
34+
...mixPropTests([
35+
endShadowSizePropTest,
36+
directionPropTest,
37+
]),
38+
...nextArrowColorPropTest,
39+
...nextArrowElementPropTest,
40+
...prevArrowColorPropTest,
41+
...prevArrowElementPropTest,
42+
...shadowsPropTest,
43+
...mixStartShadowBackgroundDirectionPropTest,
44+
...mixPropTests([
45+
startShadowSizePropTest,
46+
directionPropTest,
47+
]),
48+
].forEach(({
49+
name,
50+
onBeforeTest,
51+
onBeforeSnapshot,
52+
props,
53+
}) => {
54+
test(name, async ({
55+
mount,
56+
page,
57+
}) => {
58+
if (onBeforeTest) {
59+
await onBeforeTest(page);
60+
}
61+
62+
const component = await mount(
63+
<ScrollViewForTest
64+
{...props}
65+
/>,
66+
);
67+
68+
/**
69+
* Because onBeforeSnapshot is not propagated through mixPropTests
70+
*/
71+
if (
72+
props?.startShadowBackground !== undefined
73+
|| props?.startShadowSize !== undefined
74+
) {
75+
await page.evaluate((id) => {
76+
(window as ExtendedWindow).scrollEnd = false;
77+
const parent = document.getElementById(id);
78+
parent.children[0].addEventListener('scrollend', () => {
79+
(window as ExtendedWindow).scrollEnd = true;
80+
}, { once: true });
81+
}, 'scrollbar');
82+
83+
if (props?.direction === 'horizontal') {
84+
await page.evaluate((id) => {
85+
const parent = document.getElementById(id);
86+
parent.children[0].scrollLeft += 124;
87+
}, 'scrollbar');
88+
} else {
89+
await page.evaluate((id) => {
90+
const parent = document.getElementById(id);
91+
parent.children[0].scrollTop += 124;
92+
}, 'scrollbar');
93+
}
94+
95+
await page.waitForFunction(() => (window as ExtendedWindow).scrollEnd === true);
96+
}
97+
98+
if (onBeforeSnapshot) {
99+
await onBeforeSnapshot(page, component);
100+
}
101+
102+
const screenshot = await component.screenshot({ animations: 'disabled' });
103+
expect(screenshot).toMatchSnapshot();
104+
});
105+
});
106+
});
107+
108+
test.describe('non-visual', () => {
109+
test('id', async ({ mount }) => {
110+
const id = 'testId';
111+
112+
const component = await mount(
113+
<ScrollViewForTest
114+
arrows
115+
id={id}
116+
/>,
117+
);
118+
119+
expect(component.locator(`div[id="${id}"]`)).toBeDefined();
120+
expect(component.locator(`div[id="${id}__content"]`)).toBeDefined();
121+
expect(component.locator(`div[id="${id}__arrowPrevButton"]`)).toBeDefined();
122+
expect(component.locator(`div[id="${id}__arrowNextButton"]`)).toBeDefined();
123+
});
124+
125+
test('ref', async ({ mount }) => {
126+
const id = 'testId';
127+
128+
const component = await mount(
129+
<ScrollViewForRefTest
130+
id={id}
131+
testRefAttrName="test-ref"
132+
testRefAttrValue="test-ref-value"
133+
/>,
134+
);
135+
136+
const refValue = await component.evaluate((_, idArg) => document.getElementById(idArg).firstElementChild.getAttribute('test-ref'), id);
137+
138+
expect(refValue).toBe('test-ref-value');
139+
});
140+
});
141+
142+
test.describe('functionality', () => {
143+
test('scroll by arrowScrollStep when click on arrow', async ({
144+
mount,
145+
page,
146+
}) => {
147+
const id = 'testId';
148+
149+
const component = await mount(
150+
<ScrollViewForTest
151+
arrows
152+
arrowsScrollStep={600}
153+
id={id}
154+
/>,
155+
);
156+
157+
const arrow = component.locator(`button[id="${id}__arrowNextButton"]`);
158+
await page.evaluate((idArg) => {
159+
const parent = document.getElementById(idArg);
160+
parent.children[0].setAttribute('style', 'scroll-behavior: unset;');
161+
}, id);
162+
const scroll = component.locator(`div[id="${id}"] > div:first-child`);
163+
await arrow.click();
164+
165+
const atrValue = await scroll.evaluate((element) => element.scrollTop);
166+
167+
expect(atrValue).toBe(600);
168+
});
169+
170+
test('scroll at end when content change and autoScroll is "always"', async ({
171+
mount,
172+
page,
173+
}) => {
174+
const id = 'testId';
175+
176+
const component = await mount(
177+
<ScrollViewForTest
178+
autoScroll="always"
179+
id={id}
180+
/>,
181+
);
182+
183+
await page.evaluate((idArg) => {
184+
(window as ExtendedWindow).scrollEnd = false;
185+
const parent = document.getElementById(idArg);
186+
parent.children[0].setAttribute('style', 'scroll-behavior: unset;');
187+
}, id);
188+
189+
await page.evaluate((idArg) => {
190+
const parent = document.getElementById(idArg);
191+
parent.children[0].addEventListener('scrollend', () => {
192+
(window as ExtendedWindow).scrollEnd = true;
193+
});
194+
parent.children[0].textContent += 'content fragment content fragment content fragment';
195+
}, id);
196+
197+
await page.waitForFunction(() => (window as ExtendedWindow).scrollEnd === true);
198+
199+
const scroll = component.locator(`div[id="${id}"] > div:first-child`);
200+
const atrValue = await scroll.evaluate((element) => element.scrollTop);
201+
202+
expect(atrValue).not.toBe(0);
203+
});
204+
205+
test('scroll at end when scrolled down and content change and autoScroll is "detectEnd"', async ({
206+
mount,
207+
page,
208+
}) => {
209+
const id = 'testId';
210+
let initialScrollTop = 0;
211+
212+
await page.exposeFunction('onScrollEnd', (value: number) => {
213+
initialScrollTop = value;
214+
});
215+
216+
const component = await mount(
217+
<ScrollViewForDetectEndAutoscrollTest
218+
id={id}
219+
/>,
220+
);
221+
222+
/**
223+
* First need to wait for initial scroll down.
224+
*/
225+
await page.evaluate((idArg) => {
226+
(window as ExtendedWindow).scrollEnd = false;
227+
228+
const parent = document.getElementById(idArg);
229+
parent.children[0].addEventListener('scrollend', () => {
230+
(window as ExtendedWindow).scrollEnd = true;
231+
(window as ExtendedWindow)?.onScrollEnd(parent.children[0].scrollTop);
232+
}, { once: true });
233+
}, id);
234+
235+
await page.waitForFunction(() => (window as ExtendedWindow).scrollEnd === true);
236+
237+
/**
238+
* Add scroll detect setup.
239+
*/
240+
await page.evaluate((idArg) => {
241+
(window as ExtendedWindow).scrollEnd = false;
242+
const parent = document.getElementById(idArg);
243+
parent.children[0].addEventListener('scrollend', () => {
244+
(window as ExtendedWindow).scrollEnd = true;
245+
});
246+
}, id);
247+
248+
const button = component.getByRole('button');
249+
await button.click();
250+
251+
/**
252+
* Wait for scroll down.
253+
*/
254+
await page.waitForFunction(() => (window as ExtendedWindow).scrollEnd === true);
255+
256+
const scrollTopAfter = await page.evaluate((idArg) => {
257+
const parent = document.getElementById(idArg);
258+
return parent.children[0].scrollTop;
259+
}, id);
260+
261+
expect(scrollTopAfter).toBeGreaterThan(initialScrollTop);
262+
});
263+
264+
test('do not display top arrow after scroll before debounce expires', async ({
265+
mount,
266+
page,
267+
}) => {
268+
const id = 'testId';
269+
const debounceTimeout = 2000;
270+
271+
const component = await mount(
272+
<ScrollViewForTest
273+
arrows
274+
debounce={debounceTimeout}
275+
id={id}
276+
/>,
277+
);
278+
279+
/**
280+
* Setup scroll down listener.
281+
*/
282+
await page.evaluate((idArg) => {
283+
(window as ExtendedWindow).scrollEnd = false;
284+
const parent = document.getElementById(idArg);
285+
parent.children[0].addEventListener('scrollend', () => {
286+
(window as ExtendedWindow).scrollEnd = true;
287+
}, { once: true });
288+
}, id);
289+
290+
/**
291+
* Scroll down
292+
*/
293+
await page.evaluate((idArg) => {
294+
const parent = document.getElementById(idArg);
295+
parent.children[0].scrollTop += 200;
296+
}, id);
297+
await page.waitForFunction(() => (window as ExtendedWindow).scrollEnd === true);
298+
299+
const bottomArrowAfter = component.locator(`button[id="${id}__arrowPrevButton"]`);
300+
await expect(bottomArrowAfter).not.toBeVisible();
301+
});
302+
303+
test('do not display bottom arrow after scroll when debounce expires', async ({
304+
mount,
305+
page,
306+
}) => {
307+
const id = 'testId';
308+
const debounceTimeout = 5000;
309+
310+
const component = await mount(
311+
<ScrollViewForTest
312+
arrows
313+
debounce={debounceTimeout}
314+
id={id}
315+
/>,
316+
);
317+
318+
/**
319+
* Setup scroll down listener.
320+
*/
321+
await page.evaluate((idArg) => {
322+
(window as ExtendedWindow).scrollEnd = false;
323+
const parent = document.getElementById(idArg);
324+
parent.children[0].addEventListener('scrollend', () => {
325+
(window as ExtendedWindow).scrollEnd = true;
326+
}, { once: true });
327+
}, id);
328+
329+
/**
330+
* Scroll down
331+
*/
332+
await page.evaluate((idArg) => {
333+
const parent = document.getElementById(idArg);
334+
parent.children[0].scrollTop = parent.children[0].children[0].clientHeight;
335+
}, id);
336+
await page.waitForFunction(() => (window as ExtendedWindow).scrollEnd === true);
337+
338+
const bottomArrowBefore = component.locator(`button[id="${id}__arrowNextButton"]`);
339+
await expect(bottomArrowBefore).toBeVisible();
340+
341+
/**
342+
* Wait on debounce timeout to expire.
343+
*/
344+
await page.waitForTimeout(1.5 * debounceTimeout);
345+
346+
const bottomArrowAfter = component.locator(`button[id="${id}__arrowNextButton"]`);
347+
await expect(bottomArrowAfter).not.toBeVisible();
348+
});
349+
});
350+
});
31.9 KB
6.88 KB
6.99 KB
5.56 KB
5.89 KB
40 KB
40.3 KB
33.3 KB
34 KB

0 commit comments

Comments
 (0)