Skip to content

Commit 8b5579f

Browse files
committed
test: move middleware-pages to test variants
1 parent 65209f6 commit 8b5579f

File tree

9 files changed

+437
-344
lines changed

9 files changed

+437
-344
lines changed

tests/e2e/edge-middleware.test.ts

Lines changed: 101 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ type ExtendedWindow = Window & {
88
didReload?: boolean
99
}
1010

11+
type ExtendedFixtures = {
12+
edgeOrNodeMiddleware: Fixture
13+
edgeOrNodeMiddlewarePages: Fixture
14+
}
15+
1116
for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
1217
{
1318
expectedRuntime: 'edge-runtime',
1419
label: 'Edge runtime middleware',
15-
testWithSwitchableMiddlewareRuntime: test.extend<{}, { edgeOrNodeMiddleware: Fixture }>({
20+
testWithSwitchableMiddlewareRuntime: test.extend<{}, ExtendedFixtures>({
1621
edgeOrNodeMiddleware: [
1722
async ({ middleware }, use) => {
1823
await use(middleware)
@@ -21,13 +26,21 @@ for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
2126
scope: 'worker',
2227
},
2328
],
29+
edgeOrNodeMiddlewarePages: [
30+
async ({ middlewarePages }, use) => {
31+
await use(middlewarePages)
32+
},
33+
{
34+
scope: 'worker',
35+
},
36+
],
2437
}),
2538
},
2639
hasNodeMiddlewareSupport()
2740
? {
2841
expectedRuntime: 'node',
2942
label: 'Node.js runtime middleware',
30-
testWithSwitchableMiddlewareRuntime: test.extend<{}, { edgeOrNodeMiddleware: Fixture }>({
43+
testWithSwitchableMiddlewareRuntime: test.extend<{}, ExtendedFixtures>({
3144
edgeOrNodeMiddleware: [
3245
async ({ middlewareNode }, use) => {
3346
await use(middlewareNode)
@@ -36,6 +49,14 @@ for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
3649
scope: 'worker',
3750
},
3851
],
52+
edgeOrNodeMiddlewarePages: [
53+
async ({ middlewarePagesNode }, use) => {
54+
await use(middlewarePagesNode)
55+
},
56+
{
57+
scope: 'worker',
58+
},
59+
],
3960
}),
4061
}
4162
: undefined,
@@ -103,91 +124,95 @@ for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
103124
const size = await getImageSize(Buffer.from(imageBuffer), 'png')
104125
expect([size.width, size.height]).toEqual([1200, 630])
105126
})
127+
}
106128

107-
test.describe('json data', () => {
108-
const testConfigs = [
109-
{
110-
describeLabel: 'NextResponse.next() -> getServerSideProps page',
111-
selector: 'NextResponse.next()#getServerSideProps',
112-
jsonPathMatcher: '/link/next-getserversideprops.json',
113-
},
114-
{
115-
describeLabel: 'NextResponse.next() -> getStaticProps page',
116-
selector: 'NextResponse.next()#getStaticProps',
117-
jsonPathMatcher: '/link/next-getstaticprops.json',
118-
},
119-
{
120-
describeLabel: 'NextResponse.next() -> fully static page',
121-
selector: 'NextResponse.next()#fullyStatic',
122-
jsonPathMatcher: '/link/next-fullystatic.json',
123-
},
124-
{
125-
describeLabel: 'NextResponse.rewrite() -> getServerSideProps page',
126-
selector: 'NextResponse.rewrite()#getServerSideProps',
127-
jsonPathMatcher: '/link/rewrite-me-getserversideprops.json',
128-
},
129-
{
130-
describeLabel: 'NextResponse.rewrite() -> getStaticProps page',
131-
selector: 'NextResponse.rewrite()#getStaticProps',
132-
jsonPathMatcher: '/link/rewrite-me-getstaticprops.json',
133-
},
134-
]
135-
136-
// Linking to static pages reloads on rewrite for versions below 14
137-
if (nextVersionSatisfies('>=14.0.0')) {
138-
testConfigs.push({
139-
describeLabel: 'NextResponse.rewrite() -> fully static page',
140-
selector: 'NextResponse.rewrite()#fullyStatic',
141-
jsonPathMatcher: '/link/rewrite-me-fullystatic.json',
142-
})
143-
}
129+
test.describe('json data', () => {
130+
const testConfigs = [
131+
{
132+
describeLabel: 'NextResponse.next() -> getServerSideProps page',
133+
selector: 'NextResponse.next()#getServerSideProps',
134+
jsonPathMatcher: '/link/next-getserversideprops.json',
135+
},
136+
{
137+
describeLabel: 'NextResponse.next() -> getStaticProps page',
138+
selector: 'NextResponse.next()#getStaticProps',
139+
jsonPathMatcher: '/link/next-getstaticprops.json',
140+
},
141+
{
142+
describeLabel: 'NextResponse.next() -> fully static page',
143+
selector: 'NextResponse.next()#fullyStatic',
144+
jsonPathMatcher: '/link/next-fullystatic.json',
145+
},
146+
{
147+
describeLabel: 'NextResponse.rewrite() -> getServerSideProps page',
148+
selector: 'NextResponse.rewrite()#getServerSideProps',
149+
jsonPathMatcher: '/link/rewrite-me-getserversideprops.json',
150+
},
151+
{
152+
describeLabel: 'NextResponse.rewrite() -> getStaticProps page',
153+
selector: 'NextResponse.rewrite()#getStaticProps',
154+
jsonPathMatcher: '/link/rewrite-me-getstaticprops.json',
155+
},
156+
]
157+
158+
// Linking to static pages reloads on rewrite for versions below 14
159+
if (nextVersionSatisfies('>=14.0.0')) {
160+
testConfigs.push({
161+
describeLabel: 'NextResponse.rewrite() -> fully static page',
162+
selector: 'NextResponse.rewrite()#fullyStatic',
163+
jsonPathMatcher: '/link/rewrite-me-fullystatic.json',
164+
})
165+
}
144166

145-
test.describe('no 18n', () => {
146-
for (const testConfig of testConfigs) {
147-
test.describe(testConfig.describeLabel, () => {
148-
test('json data fetch', async ({ middlewarePages, page }) => {
149-
const dataFetchPromise = new Promise<Response>((resolve) => {
150-
page.on('response', (response) => {
151-
if (response.url().includes(testConfig.jsonPathMatcher)) {
152-
resolve(response)
153-
}
154-
})
167+
test.describe('no 18n', () => {
168+
for (const testConfig of testConfigs) {
169+
test.describe(testConfig.describeLabel, () => {
170+
test('json data fetch', async ({ edgeOrNodeMiddlewarePages, page }) => {
171+
const dataFetchPromise = new Promise<Response>((resolve) => {
172+
page.on('response', (response) => {
173+
if (response.url().includes(testConfig.jsonPathMatcher)) {
174+
resolve(response)
175+
}
155176
})
177+
})
156178

157-
await page.goto(`${middlewarePages.url}/link`)
179+
const pageResponse = await page.goto(`${edgeOrNodeMiddlewarePages.url}/link`)
180+
expect(await pageResponse?.headerValue('x-runtime')).toEqual(expectedRuntime)
158181

159-
await page.hover(`[data-link="${testConfig.selector}"]`)
182+
await page.hover(`[data-link="${testConfig.selector}"]`)
160183

161-
const dataResponse = await dataFetchPromise
184+
const dataResponse = await dataFetchPromise
162185

163-
expect(dataResponse.ok()).toBe(true)
164-
})
186+
expect(dataResponse.ok()).toBe(true)
187+
})
165188

166-
test('navigation', async ({ middlewarePages, page }) => {
167-
await page.goto(`${middlewarePages.url}/link`)
189+
test('navigation', async ({ edgeOrNodeMiddlewarePages, page }) => {
190+
const pageResponse = await page.goto(`${edgeOrNodeMiddlewarePages.url}/link`)
191+
expect(await pageResponse?.headerValue('x-runtime')).toEqual(expectedRuntime)
168192

169-
await page.evaluate(() => {
170-
// set some value to window to check later if browser did reload and lost this state
171-
;(window as ExtendedWindow).didReload = false
172-
})
193+
await page.evaluate(() => {
194+
// set some value to window to check later if browser did reload and lost this state
195+
;(window as ExtendedWindow).didReload = false
196+
})
173197

174-
await page.click(`[data-link="${testConfig.selector}"]`)
198+
await page.click(`[data-link="${testConfig.selector}"]`)
175199

176-
// wait for page to be rendered
177-
await page.waitForSelector(`[data-page="${testConfig.selector}"]`)
200+
// wait for page to be rendered
201+
await page.waitForSelector(`[data-page="${testConfig.selector}"]`)
178202

179-
// check if browser navigation worked by checking if state was preserved
180-
const browserNavigationWorked =
181-
(await page.evaluate(() => {
182-
return (window as ExtendedWindow).didReload
183-
})) === false
203+
// check if browser navigation worked by checking if state was preserved
204+
const browserNavigationWorked =
205+
(await page.evaluate(() => {
206+
return (window as ExtendedWindow).didReload
207+
})) === false
184208

185-
// we expect client navigation to work without browser reload
186-
expect(browserNavigationWorked).toBe(true)
187-
})
209+
// we expect client navigation to work without browser reload
210+
expect(browserNavigationWorked).toBe(true)
188211
})
189-
}
190-
})
212+
})
213+
}
214+
})
215+
if (expectedRuntime !== 'node') {
191216
test.describe('with 18n', () => {
192217
for (const testConfig of testConfigs) {
193218
test.describe(testConfig.describeLabel, () => {
@@ -242,8 +267,10 @@ for (const { expectedRuntime, label, testWithSwitchableMiddlewareRuntime } of [
242267
})
243268
}
244269
})
245-
})
270+
}
271+
})
246272

273+
if (expectedRuntime !== 'node') {
247274
// those tests use `fetch` instead of `page.goto` intentionally to avoid potential client rendering
248275
// hiding any potential edge/server issues
249276
test.describe('Middleware with i18n and excluded paths', () => {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export { middleware } from './middleware-shared'
2+
3+
export const config = {
4+
runtime: 'nodejs',
5+
}

tests/fixtures/middleware-pages/middleware.js renamed to tests/fixtures/middleware-pages/middleware-shared.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
1+
import type { NextRequest } from 'next/server'
12
import { NextResponse, URLPattern } from 'next/server'
23

3-
export async function middleware(request) {
4+
export async function middleware(request: NextRequest) {
5+
const response = getResponse(request)
6+
7+
response.headers.append('Deno' in globalThis ? 'x-deno' : 'x-node', Date.now().toString())
8+
// report Next.js Middleware Runtime (not the execution runtime, but target runtime)
9+
// @ts-expect-error EdgeRuntime global not declared
10+
response.headers.append('x-runtime', typeof EdgeRuntime !== 'undefined' ? EdgeRuntime : 'node')
11+
response.headers.set('x-hello-from-middleware-res', 'hello')
12+
13+
return response
14+
}
15+
16+
const getResponse = (request: NextRequest) => {
417
const url = request.nextUrl
518

619
// this is needed for tests to get the BUILD_ID
@@ -93,7 +106,10 @@ export async function middleware(request) {
93106
})
94107
}
95108

96-
const PATTERNS = [
109+
const PATTERNS: [
110+
URLPattern,
111+
(params: ReturnType<URLPattern['exec']>) => { pathname: string; params: Record<string, string> },
112+
][] = [
97113
[
98114
new URLPattern({ pathname: '/:locale/:id' }),
99115
({ pathname }) => ({
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { middleware } from './middleware-shared'

tests/fixtures/middleware-pages/next.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ if (platform === 'win32') {
2525
module.exports = {
2626
trailingSlash: true,
2727
output: 'standalone',
28+
distDir: process.env.NEXT_DIST_DIR ?? '.next',
2829
eslint: {
2930
ignoreDuringBuilds: true,
3031
},
32+
experimental: {
33+
nodeMiddleware: true,
34+
},
3135
generateBuildId: () => 'build-id',
3236
redirects() {
3337
return [

tests/fixtures/middleware-pages/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
"version": "0.1.0",
44
"private": true,
55
"scripts": {
6-
"postinstall": "next build",
6+
"postinstall": "npm run build",
77
"dev": "next dev",
8-
"build": "next build"
8+
"build": "node ../../utils/build-variants.mjs"
99
},
1010
"dependencies": {
1111
"next": "latest",
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"node-middleware": {
3+
"distDir": ".next-node-middleware",
4+
"files": {
5+
"middleware.ts": "middleware-node.ts"
6+
},
7+
"test": {
8+
"dependencies": {
9+
"next": [
10+
{
11+
"versionConstraint": ">=15.2.0",
12+
"canaryOnly": true
13+
},
14+
{
15+
"versionConstraint": ">=15.5.0"
16+
}
17+
]
18+
}
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)