Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed Mar 5, 2024
1 parent 372bacb commit 4cb8f43
Show file tree
Hide file tree
Showing 4 changed files with 315 additions and 1 deletion.
10 changes: 10 additions & 0 deletions test/e2e/app-dir/app-client-cache/app/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export default function HomePage() {
To Random Number - prefetch: true
</Link>
</div>
<div>
<Link href="/0?timeout=1000" prefetch={true}>
To Random Number - prefetch: true, slow
</Link>
</div>
<div>
<Link href="/1">To Random Number - prefetch: auto</Link>
</div>
Expand All @@ -15,6 +20,11 @@ export default function HomePage() {
To Random Number 2 - prefetch: false
</Link>
</div>
<div>
<Link href="/2?timeout=1000" prefetch={false}>
To Random Number 2 - prefetch: false, slow
</Link>
</div>
<div>
<Link href="/1?timeout=1000">
To Random Number - prefetch: auto, slow
Expand Down
233 changes: 233 additions & 0 deletions test/e2e/app-dir/app-client-cache/client-cache.experimental.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import { nextTestSetup } from 'e2e-utils'
import { BrowserInterface } from 'test/lib/browsers/base'
import { browserConfigWithFixedTime, fastForwardTo } from './test-utils'

describe('app dir client cache semantics (experimental clientRouterCache)', () => {
describe('clientRouterCache = true', () => {
const { next } = nextTestSetup({
files: __dirname,
nextConfig: {
experimental: { clientRouterCache: true },
},
})

let browser: BrowserInterface

beforeEach(async () => {
browser = (await next.browser(
'/',
browserConfigWithFixedTime
)) as BrowserInterface
})

describe('prefetch={true}', () => {
test('the prefetched data should remain the same "indefinitely"', async () => {
const initialRandomNumber = await browser
.elementByCss('[href="/0?timeout=0"]')
.click()
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

let newRandomNumber = await browser
.elementByCss('[href="/0?timeout=0"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).toBe(newRandomNumber)

await browser.eval(fastForwardTo, 2 * 60 * 60 * 1000) // fast forward 2 hours

await browser.elementByCss('[href="/"]').click()

newRandomNumber = await browser
.elementByCss('[href="/0?timeout=0"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).toBe(newRandomNumber)
})
})

describe('prefetch={false}', () => {
test('we should get a loading state before fetching the page, followed by same data "indefinitely"', async () => {
// verify we rendered the loading state
await browser
.elementByCss('[href="/2?timeout=1000"]')
.click()
.waitForElementByCss('#loading')

const initialRandomNumber = await browser
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

await browser.eval(fastForwardTo, 2 * 60 * 60 * 1000) // fast forward 2 hours

const newRandomNumber = await browser
.elementByCss('[href="/2?timeout=1000"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).toBe(newRandomNumber)
})
})

describe('prefetch={undefined} - default', () => {
test('we should get a loading state before fetching the page, followed by same data "indefinitely"', async () => {
// verify we rendered the loading state
await browser
.elementByCss('[href="/1?timeout=1000"]')
.click()
.waitForElementByCss('#loading')

const initialRandomNumber = await browser
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

await browser.eval(fastForwardTo, 2 * 60 * 60 * 1000) // fast forward 2 hours

const newRandomNumber = await browser
.elementByCss('[href="/1?timeout=1000"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).toBe(newRandomNumber)
})
})
})

describe('clientRouterCache = false', () => {
const { next } = nextTestSetup({
files: __dirname,
nextConfig: {
experimental: { clientRouterCache: false },
},
})

let browser: BrowserInterface

beforeEach(async () => {
browser = (await next.browser(
'/',
browserConfigWithFixedTime
)) as BrowserInterface
})

describe('prefetch={true}', () => {
test('the prefetch data should be new each navigation', async () => {
const initialRandomNumber = await browser
.elementByCss('[href="/0?timeout=0"]')
.click()
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

let newRandomNumber = await browser
.elementByCss('[href="/0?timeout=0"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).not.toBe(newRandomNumber)

await browser.eval(fastForwardTo, 5 * 1000) // fast forward 5 seconds

await browser.elementByCss('[href="/"]').click()

newRandomNumber = await browser
.elementByCss('[href="/0?timeout=0"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).not.toBe(newRandomNumber)
})

test('we should get a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => {
// this test introduces an artificial delay in rendering the requested page, so we verify a loading state is rendered
await browser
.elementByCss('[href="/0?timeout=1000"]')
.click()
.waitForElementByCss('#loading')

const initialRandomNumber = await browser
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

await browser.eval(fastForwardTo, 5 * 1000) // fast forward 5 seconds

const newRandomNumber = await browser
.elementByCss('[href="/0?timeout=1000"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).not.toBe(newRandomNumber)
})
})

describe('prefetch={false}', () => {
test('we should get a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => {
// this test introduces an artificial delay in rendering the requested page, so we verify a loading state is rendered
await browser
.elementByCss('[href="/2?timeout=1000"]')
.click()
.waitForElementByCss('#loading')

const initialRandomNumber = await browser
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

await browser.eval(fastForwardTo, 5 * 1000) // fast forward 5 seconds

const newRandomNumber = await browser
.elementByCss('[href="/2?timeout=1000"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).not.toBe(newRandomNumber)
})
})

describe('prefetch={undefined} - default', () => {
test('we should get a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => {
// this test introduces an artificial delay in rendering the requested page, so we verify a loading state is rendered
await browser
.elementByCss('[href="/1?timeout=1000"]')
.click()
.waitForElementByCss('#loading')

const initialRandomNumber = await browser
.waitForElementByCss('#random-number')
.text()

await browser.elementByCss('[href="/"]').click()

await browser.eval(fastForwardTo, 5 * 1000) // fast forward 5 seconds

const newRandomNumber = await browser
.elementByCss('[href="/1?timeout=1000"]')
.click()
.waitForElementByCss('#random-number')
.text()

expect(initialRandomNumber).not.toBe(newRandomNumber)
})
})
})
})
1 change: 0 additions & 1 deletion test/e2e/app-dir/app-client-cache/next.config.js

This file was deleted.

72 changes: 72 additions & 0 deletions test/e2e/app-dir/app-client-cache/test-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { BrowserInterface } from 'test/lib/browsers/base'
import type { Request } from 'playwright'

export const getPathname = (url: string) => {
const urlObj = new URL(url)
return urlObj.pathname
}

export const browserConfigWithFixedTime = {
beforePageLoad: (page) => {
page.addInitScript(() => {
const startTime = new Date()
const fixedTime = new Date('2023-04-17T00:00:00Z')

// Override the Date constructor
// @ts-ignore
// eslint-disable-next-line no-native-reassign
Date = class extends Date {
constructor() {
super()
// @ts-ignore
return new startTime.constructor(fixedTime)
}

static now() {
return fixedTime.getTime()
}
}
})
},
}

export const fastForwardTo = (ms) => {
// Increment the fixed time by the specified duration
const currentTime = new Date()
currentTime.setTime(currentTime.getTime() + ms)

// Update the Date constructor to use the new fixed time
// @ts-ignore
// eslint-disable-next-line no-native-reassign
Date = class extends Date {
constructor() {
super()
// @ts-ignore
return new currentTime.constructor(currentTime)
}

static now() {
return currentTime.getTime()
}
}
}

export const createRequestsListener = async (browser: BrowserInterface) => {
// wait for network idle
await browser.waitForIdleNetwork()

let requests = []

browser.on('request', (req: Request) => {
requests.push([req.url(), !!req.headers()['next-router-prefetch']])
})

await browser.refresh()

return {
getRequests: () => requests,
clearRequests: () => {
requests = []
},
}
}

0 comments on commit 4cb8f43

Please sign in to comment.