Skip to content

Commit

Permalink
fix(navgiation): tests for not scrolling to hash on 'replace' navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
danroberts committed Aug 9, 2022
1 parent f27c4e7 commit fd2dc86
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 0 deletions.
9 changes: 9 additions & 0 deletions packages/fastify-renderer/src/client/react/locationHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ export const useTransitionLocation = ({ base = '' } = {}) => {
const prevLocation = useRef(path + location.search + location.hash)
const [startTransition, isPending] = useTransition()
const router = useRouter()
useEffect(() => {
if (!router.navigationHistory)
router.navigationHistory = {
current: {
path,
replace: false,
},
}
}, [])

useEffect(() => {
// this function checks if the location has been changed since the
Expand Down
98 changes: 98 additions & 0 deletions packages/test-apps/simple-react/NavigationHistoryTest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React from 'react'
import { Link, useLocation } from 'wouter'

const NavigationHistoryTest = () => {
const [path, navigate] = useLocation()

return (
<>
<h1>Navigation Test</h1>
<p>Leaving this page will set the navigation details on the window for inspection in the tests</p>
<br />
<Link href="/navigation-history-test#section">
<a id="section-link">Go to the content</a>
</Link>
<br />
<Link href="/">
<a id="home-link">Home</a>
</Link>
<br />
<button
id="section-link-replace"
onClick={() => {
navigate('/navigation-history-test#section', { replace: true })
}}
>
Update url without scrolling
</button>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h2 id="section">Another Section</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Fuga earum maiores, excepturi aspernatur perspiciatis
doloribus suscipit voluptates ipsam nam in nostrum vel obcaecati cum illum ex quasi quo est at.
</p>
</>
)
}

export default NavigationHistoryTest
4 changes: 4 additions & 0 deletions packages/test-apps/simple-react/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ export const server = async () => {
return {}
})

server.get('/navigation-history-test', { render: require.resolve('./NavigationHistoryTest') }, async (_request) => {
return {}
})

await server.register(async (instance) => {
instance.setRenderConfig({ document: CustomDocumentTemplate })

Expand Down
50 changes: 50 additions & 0 deletions packages/test-apps/simple-react/test/navigation-history.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Page } from 'playwright-chromium'
import { newTestPage, reactReady, rootURL } from '../../helpers'

describe('navigation details', () => {
let page: Page

beforeEach(async () => {
page = await newTestPage()
await page.goto(`${rootURL}/navigation-history-test`)
await reactReady(page)
})

test('navigating to an anchor will scroll down to the anchor', async () => {
const visibleBeforeClick = await isIntersectingViewport(page, '#section')
expect(visibleBeforeClick).toBe(false)

await page.click('#section-link')

const visibleAfterClick = await isIntersectingViewport(page, '#section')
expect(visibleAfterClick).toBe(true)
})

test('navigating to an anchor that is on the same page via replace: true will not scroll to the anchor', async () => {
const visibleBeforeClick = await isIntersectingViewport(page, '#section')
expect(visibleBeforeClick).toBe(false)

await page.click('#section-link-replace')

const visibleAfterClick = await isIntersectingViewport(page, '#section')
expect(visibleAfterClick).toBe(false)
})
})

const isIntersectingViewport = (page: Page, selector: string): Promise<boolean> => {
return page.$eval(selector, async (element) => {
const visibleRatio: number = await new Promise((resolve) => {
const observer = new IntersectionObserver((entries) => {
resolve(entries[0].intersectionRatio)
observer.disconnect()
})
observer.observe(element)
// Firefox doesn't call IntersectionObserver callback unless
// there are rafs.
requestAnimationFrame(() => {
/**/
})
})
return visibleRatio > 0
})
}

0 comments on commit fd2dc86

Please sign in to comment.