Skip to content

Commit

Permalink
test: add test for ISR case that always return same body
Browse files Browse the repository at this point in the history
  • Loading branch information
pieh committed Jan 16, 2025
1 parent aab8803 commit 62ed00c
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 0 deletions.
39 changes: 39 additions & 0 deletions tests/e2e/page-router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,45 @@ test.describe('Simple Page Router (no basePath, no i18n)', () => {
'.env.production.local': 'defined in .env.production.local',
})
})

test('ISR pages that are the same after regeneration execute background getStaticProps uninterrupted', async ({
page,
pageRouter,
}) => {
const slug = Date.now()

await page.goto(new URL(`always-the-same-body/${slug}`, pageRouter.url).href)

await new Promise((resolve) => setTimeout(resolve, 15_000))

await page.goto(new URL(`always-the-same-body/${slug}`, pageRouter.url).href)

await new Promise((resolve) => setTimeout(resolve, 15_000))

await page.goto(new URL(`always-the-same-body/${slug}`, pageRouter.url).href)

await new Promise((resolve) => setTimeout(resolve, 15_000))

// keep lambda executing to allow for background getStaticProps to finish in case background work execution was suspended
await fetch(new URL(`api/sleep-5`, pageRouter.url).href)

const response = await fetch(new URL(`read-static-props-blobs/${slug}`, pageRouter.url).href)
expect(response.ok, 'response for stored data status should not fail').toBe(true)

const data = await response.json()

expect(typeof data.start, 'timestamp of getStaticProps start should be a number').toEqual(
'number',
)
expect(typeof data.end, 'timestamp of getStaticProps end should be a number').toEqual('number')

// duration should be around 5s overall, due to 5s timeout, but this is not exact so let's be generous and allow 10 seconds
// which is still less than 15 seconds between requests
expect(
data.end - data.start,
'getStaticProps duration should not be longer than 10 seconds',
).toBeLessThan(10_000)
})
})

test.describe('Page Router with basePath and i18n', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getDeployStore } from '@netlify/blobs'
import { Context } from '@netlify/functions'

function numberOrNull(value: string | null) {
if (!value) {
return null
}

const maybeNumber = parseInt(value)
return isNaN(maybeNumber) ? null : maybeNumber
}

// intentionally using Netlify Function to not hit Next.js server handler function instance
// to avoid potentially resuming suspended execution
export default async function handler(_request: Request, context: Context) {
const slug = context.params['slug']

const store = getDeployStore({ name: 'get-static-props-tracker', consistency: 'strong' })

const [start, end] = await Promise.all([store.get(`${slug}-start`), store.get(`${slug}-end`)])

return Response.json({ slug, start: numberOrNull(start), end: numberOrNull(end) })
}

export const config = {
path: '/read-static-props-blobs/:slug',
}
1 change: 1 addition & 0 deletions tests/fixtures/page-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build": "next build"
},
"dependencies": {
"@netlify/blobs": "^8.1.0",
"@netlify/functions": "^2.7.0",
"next": "latest",
"react": "18.2.0",
Expand Down
50 changes: 50 additions & 0 deletions tests/fixtures/page-router/pages/always-the-same-body/[slug].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { getDeployStore } from '@netlify/blobs'

const Show = ({ slug }) => {
// ensure that the content is stable to trigger 304 responses
return <pre>{slug}</pre>
}

/** @type {import('next').getStaticPaths} */
export async function getStaticPaths() {
return {
paths: [],
fallback: 'blocking',
}
}

/** @type {import('next').GetStaticProps} */
export async function getStaticProps({ params }) {
const store = getDeployStore({ name: 'get-static-props-tracker', consistency: 'strong' })

const start = Date.now()

console.log(`[timestamp] ${params.slug} getStaticProps start`)

const storeStartPromise = store.set(`${params.slug}-start`, start).then(() => {
console.log(`[timestamp] ${params.slug} getStaticProps start stored`)
})

// simulate a long running operation
await new Promise((resolve) => setTimeout(resolve, 5000))

const storeEndPromise = store.set(`${params.slug}-end`, Date.now()).then(() => {
console.log(`[timestamp] ${params.slug} getStaticProps end stored`)
})

console.log(
`[timestamp] ${params.slug} getStaticProps end (duration: ${(Date.now() - start) / 1000}s)`,
)

await Promise.all([storeStartPromise, storeEndPromise])

// ensure that the data is stable and always the same to trigger 304 responses
return {
props: {
slug: params.slug,
},
revalidate: 5,
}
}

export default Show
5 changes: 5 additions & 0 deletions tests/fixtures/page-router/pages/api/sleep-5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default async function handler(req, res) {
await new Promise((resolve) => setTimeout(resolve, 5000))

res.json({ message: 'ok' })
}

0 comments on commit 62ed00c

Please sign in to comment.