Skip to content

Commit fe45660

Browse files
committed
test: add test for ISR case that always return same body
1 parent aab8803 commit fe45660

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

tests/e2e/page-router.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,40 @@ test.describe('Simple Page Router (no basePath, no i18n)', () => {
494494
'.env.production.local': 'defined in .env.production.local',
495495
})
496496
})
497+
498+
test('ISR pages that are the same after regeneration execute background getStaticProps uninterrupted', async ({
499+
page,
500+
pageRouter,
501+
}) => {
502+
const slug = Date.now()
503+
504+
await page.goto(new URL(`always-the-same-body/${slug}`, pageRouter.url).href)
505+
506+
await new Promise((resolve) => setTimeout(resolve, 15_000))
507+
508+
await page.goto(new URL(`always-the-same-body/${slug}`, pageRouter.url).href)
509+
510+
await new Promise((resolve) => setTimeout(resolve, 15_000))
511+
512+
await page.goto(new URL(`always-the-same-body/${slug}`, pageRouter.url).href)
513+
514+
const response = await fetch(new URL(`read-static-props-blobs/${slug}`, pageRouter.url).href)
515+
expect(response.ok, 'response for stored data status should not fail').toBe(true)
516+
517+
const data = await response.json()
518+
519+
expect(typeof data.start, 'timestamp of getStaticProps start should be a number').toEqual(
520+
'number',
521+
)
522+
expect(typeof data.end, 'timestamp of getStaticProps end should be a number').toEqual('number')
523+
524+
// duration should be around 5s overall, due to 5s timeout, but this is not exact so let's be generous and allow 10 seconds
525+
// which is still less than 15 seconds between requests
526+
expect(
527+
data.end - data.start,
528+
'getStaticProps duration should not be longer than 10 seconds',
529+
).toBeLessThan(10_000)
530+
})
497531
})
498532

499533
test.describe('Page Router with basePath and i18n', () => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { getDeployStore } from '@netlify/blobs'
2+
import { Context } from '@netlify/functions'
3+
4+
function numberOrNull(value: string | null) {
5+
if (!value) {
6+
return null
7+
}
8+
9+
const maybeNumber = parseInt(value)
10+
return isNaN(maybeNumber) ? null : maybeNumber
11+
}
12+
13+
// intentionally using Netlify Function to not hit Next.js server handler function instance
14+
// to avoid potentially resuming suspended execution
15+
export default async function handler(_request: Request, context: Context) {
16+
const slug = context.params['slug']
17+
18+
const store = getDeployStore({ name: 'get-static-props-tracker', consistency: 'strong' })
19+
20+
const [start, end] = await Promise.all([store.get(`${slug}-start`), store.get(`${slug}-end`)])
21+
22+
return Response.json({ slug, start: numberOrNull(start), end: numberOrNull(end) })
23+
}
24+
25+
export const config = {
26+
path: '/read-static-props-blobs/:slug',
27+
}

tests/fixtures/page-router/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"build": "next build"
99
},
1010
"dependencies": {
11+
"@netlify/blobs": "^8.1.0",
1112
"@netlify/functions": "^2.7.0",
1213
"next": "latest",
1314
"react": "18.2.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { getDeployStore } from '@netlify/blobs'
2+
3+
const Show = ({ slug }) => {
4+
// ensure that the content is stable to trigger 304 responses
5+
return <pre>{slug}</pre>
6+
}
7+
8+
/** @type {import('next').getStaticPaths} */
9+
export async function getStaticPaths() {
10+
return {
11+
paths: [],
12+
fallback: 'blocking',
13+
}
14+
}
15+
16+
/** @type {import('next').GetStaticProps} */
17+
export async function getStaticProps({ params }) {
18+
const store = getDeployStore({ name: 'get-static-props-tracker', consistency: 'strong' })
19+
20+
const start = Date.now()
21+
22+
console.log(`[timestamp] ${params.slug} getStaticProps start`)
23+
24+
const storeStartPromise = store.set(`${params.slug}-start`, start)
25+
26+
// simulate a long running operation
27+
await new Promise((resolve) => setTimeout(resolve, 5000))
28+
29+
const storeEndPromise = store.set(`${params.slug}-end`, Date.now())
30+
31+
console.log(
32+
`[timestamp] ${params.slug} getStaticProps end (duration: ${(Date.now() - start) / 1000}s)`,
33+
)
34+
35+
await Promise.all([storeStartPromise, storeEndPromise])
36+
37+
// ensure that the data is stable and always the same to trigger 304 responses
38+
return {
39+
props: {
40+
slug: params.slug,
41+
},
42+
revalidate: 5,
43+
}
44+
}
45+
46+
export default Show

0 commit comments

Comments
 (0)