Skip to content

Commit 67c004b

Browse files
test: e2e infinite scroll (#562)
# Motivation Given that the `InfiniteScroll` component will need some adjustments for compatibility with Svelte v5, I thought it would be a good idea to first add an end-to-end test to verify that the scroll works as expected. # Notes Requires #563 configuration to build the showcase app. # Changes - Add a `testId` to the component - Provide some demo and test data within the infinite scroll component page - Write e2e tests that assert that data are loaded on scroll
1 parent ecde5eb commit 67c004b

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

e2e/infinite-scroll.e2e.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
const testUrl = "/components/infinite-scroll";
4+
5+
test("should render 100 elements by default", async ({ page }) => {
6+
await page.goto(testUrl);
7+
8+
const ul = page.getByTestId("showcase-infinite-scroll");
9+
10+
const firstLi = ul.locator("li:nth-of-type(1)");
11+
await expect(firstLi).toBeVisible();
12+
13+
const liList = ul.locator("li");
14+
expect(await liList.count()).toBe(100);
15+
});
16+
17+
test("should render 200 elements on scroll", async ({ page }) => {
18+
await page.goto(testUrl);
19+
20+
const ul = page.getByTestId("showcase-infinite-scroll");
21+
22+
const lastLi = ul.locator("li:nth-of-type(100)");
23+
await expect(lastLi).toBeVisible();
24+
25+
await lastLi.scrollIntoViewIfNeeded();
26+
27+
const lastLiAfterIntersect = ul.locator("li:nth-of-type(200)");
28+
await expect(lastLiAfterIntersect).toBeVisible();
29+
30+
const liList = ul.locator("li");
31+
expect(await liList.count()).toBe(200);
32+
});
33+
34+
test("should reach end of scroll", async ({ page }) => {
35+
await page.goto(testUrl);
36+
37+
const ul = page.getByTestId("showcase-infinite-scroll");
38+
39+
const lastLi = ul.locator("li:nth-of-type(100)");
40+
await expect(lastLi).toBeVisible();
41+
42+
await lastLi.scrollIntoViewIfNeeded();
43+
44+
const lastLiAfterIntersect = ul.locator("li:nth-of-type(200)");
45+
await expect(lastLiAfterIntersect).toBeVisible();
46+
47+
await lastLiAfterIntersect.scrollIntoViewIfNeeded();
48+
49+
const veryLastLiAfterIntersect = ul.locator("li:nth-of-type(300)");
50+
await expect(veryLastLiAfterIntersect).toBeVisible();
51+
52+
const liList = ul.locator("li");
53+
expect(await liList.count()).toBe(300);
54+
55+
await veryLastLiAfterIntersect.scrollIntoViewIfNeeded();
56+
57+
const endMessage = ul.getByTestId("infinite-scroll-end");
58+
await expect(endMessage).toBeVisible();
59+
});

src/lib/components/InfiniteScroll.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
1010
export let layout: "list" | "grid" = "list";
1111
export let disabled = false;
12+
export let testId: string | undefined = undefined;
1213
1314
// IntersectionObserverInit is not recognized by the linter
1415
// eslint-disable-next-line no-undef
@@ -75,7 +76,7 @@
7576
onDestroy(() => observer.disconnect());
7677
</script>
7778

78-
<ul bind:this={container} class:card-grid={layout === "grid"}>
79+
<ul bind:this={container} class:card-grid={layout === "grid"} data-tid={testId}>
7980
<slot />
8081
</ul>
8182

src/routes/(split)/components/infinite-scroll/+page.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
<script lang="ts">
2+
import InfiniteScroll from "$lib/components/InfiniteScroll.svelte";
3+
import Tag from "$lib/components/Tag.svelte";
4+
5+
const generate = (index: number): number[] => [ ...Array(100).keys().map(i => i + index) ];
6+
7+
let scrollDisabled = false;
8+
let elements = generate(0);
9+
10+
const onIntersect = () => {
11+
if (elements.length >= 300) {
12+
scrollDisabled = true;
13+
return;
14+
}
15+
16+
setTimeout(() => elements = [...elements, ...generate(elements.length)], 500);
17+
}
18+
</script>
19+
120
# Infinite Scroll
221

322
The Infinite Scroll component calls an action to be performed when the user scrolls a specified distance of the list presented in the page.
@@ -33,3 +52,22 @@ It sets the reference to the last element of the list after each re-render. **Pa
3352
| Event | Description | Detail |
3453
| -------------- | ---------------------------------------------------------------------------------------------------------- | --------- |
3554
| `nnsIntersect` | Triggered each time the next observed item is intersecting. The event that can be use to call your action. | No detail |
55+
56+
## Showcase
57+
58+
<InfiniteScroll on:nnsIntersect={onIntersect} disabled={scrollDisabled} testId="showcase-infinite-scroll">
59+
{#each elements as _element, i}
60+
<li><Tag>Element {i}</Tag></li>
61+
{/each}
62+
63+
{#if scrollDisabled}
64+
<li data-tid="infinite-scroll-end"><Tag intent="success">Maximum pagination reached</Tag></li>
65+
{/if}
66+
67+
</InfiniteScroll>
68+
69+
<style lang="scss">
70+
li {
71+
margin: 0 0 var(--padding);
72+
}
73+
</style>

0 commit comments

Comments
 (0)