Skip to content

Commit ae62f5c

Browse files
committed
e2e test it baby
1 parent f03c734 commit ae62f5c

File tree

3 files changed

+70
-5
lines changed

3 files changed

+70
-5
lines changed

app/hooks/use-scroll-restoration.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import { useEffect, useRef } from 'react'
22
import { useLocation, useNavigation } from 'react-router-dom'
33

4-
export function useScrollRestoration(elementRef: React.RefObject<HTMLElement>) {
4+
/**
5+
* Given a ref to a scrolling container element, keep track of its scroll
6+
* position before navigation and restore it on return (e.g., back/forward nav).
7+
* Note that `location.key` is used as the cache key, not `location.pathname`,
8+
* so the same path navigated to at different points in the history stack will
9+
* not share the same scroll position.
10+
*/
11+
export function useScrollRestoration(container: React.RefObject<HTMLElement>) {
512
const cache = useRef(new Map<string, number>())
613
const { key } = useLocation()
714
const { state } = useNavigation()
815
useEffect(() => {
916
if (state === 'loading') {
10-
cache.current.set(key, elementRef.current?.scrollTop ?? 0)
17+
cache.current.set(key, container.current?.scrollTop ?? 0)
1118
} else if (state === 'idle' && cache.current.has(key)) {
12-
elementRef.current?.scrollTo(0, cache.current.get(key)!)
19+
container.current?.scrollTo(0, cache.current.get(key)!)
1320
}
14-
}, [key, state, elementRef])
21+
}, [key, state, container])
1522
}

app/layouts/helpers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function ContentPane() {
1515
const ref = useRef<HTMLDivElement>(null)
1616
useScrollRestoration(ref)
1717
return (
18-
<div ref={ref} className="flex flex-col overflow-auto">
18+
<div ref={ref} className="flex flex-col overflow-auto" data-testid="scroll-container">
1919
<div className="flex flex-grow flex-col pb-8">
2020
<SkipLinkTarget />
2121
<main className="[&>*]:gutter">

app/test/e2e/scroll-restore.e2e.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { type Page, expect, test } from './utils'
2+
3+
async function expectScrollTop(page: Page, expected: number) {
4+
const container = await page.getByTestId('scroll-container')
5+
const getScrollTop = () => container.evaluate((el: HTMLElement) => el.scrollTop)
6+
await expect.poll(getScrollTop).toBe(expected)
7+
}
8+
9+
async function scrollTo(page: Page, to: number) {
10+
const container = await page.getByTestId('scroll-container')
11+
await container.evaluate((el: HTMLElement, to) => el.scrollTo(0, to), to)
12+
}
13+
14+
test('scroll restore', async ({ page }) => {
15+
// open small window to make scrolling easier
16+
await page.setViewportSize({ width: 800, height: 500 })
17+
18+
// nav to disks and scroll it
19+
await page.goto('/projects/mock-project/disks')
20+
await expectScrollTop(page, 0)
21+
await scrollTo(page, 143)
22+
23+
// nav to snapshots
24+
await page.getByRole('link', { name: 'Snapshots' }).click()
25+
await expectScrollTop(page, 0)
26+
27+
// go back to disks, scroll is restored, scroll it some more
28+
await page.goBack()
29+
await expect(page).toHaveURL('/projects/mock-project/disks')
30+
await expectScrollTop(page, 143)
31+
await scrollTo(page, 190)
32+
33+
// go forward to snapshots, now scroll it
34+
await page.goForward()
35+
await expect(page).toHaveURL('/projects/mock-project/snapshots')
36+
await expectScrollTop(page, 0)
37+
await scrollTo(page, 30)
38+
39+
// new nav to disks
40+
await page.getByRole('link', { name: 'Disks' }).click()
41+
await expectScrollTop(page, 0)
42+
43+
// back to snapshots, scroll is restored
44+
await page.goBack()
45+
await expect(page).toHaveURL('/projects/mock-project/snapshots')
46+
await expectScrollTop(page, 30)
47+
48+
// back again to disks, newer scroll value is restored
49+
await page.goBack()
50+
await expect(page).toHaveURL('/projects/mock-project/disks')
51+
await expectScrollTop(page, 190)
52+
53+
// forward again to newest disks history entry, scroll remains 0
54+
await page.goForward()
55+
await page.goForward()
56+
await expect(page).toHaveURL('/projects/mock-project/disks')
57+
await expectScrollTop(page, 0)
58+
})

0 commit comments

Comments
 (0)