Skip to content

Commit 50ead24

Browse files
author
Luca Forstner
authored
test(e2e): Add test for Next.js middleware (#8350)
1 parent df4f4ab commit 50ead24

File tree

6 files changed

+154
-2
lines changed

6 files changed

+154
-2
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { NextResponse } from 'next/server';
2+
import type { NextRequest } from 'next/server';
3+
4+
export function middleware(request: NextRequest) {
5+
if (request.headers.has('x-should-throw')) {
6+
throw new Error('Middleware Error');
7+
}
8+
9+
return NextResponse.next();
10+
}
11+
12+
// See "Matching Paths" below to learn more
13+
export const config = {
14+
matcher: ['/api/endpoint-behind-middleware'],
15+
};
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1-
export const config = { runtime: 'edge' };
1+
export const config = {
2+
runtime: 'edge',
3+
};
24

3-
export default () => new Response('Hello world!');
5+
export default async function handler() {
6+
return new Response(
7+
JSON.stringify({
8+
name: 'Jim Halpert',
9+
}),
10+
{
11+
status: 200,
12+
headers: {
13+
'content-type': 'application/json',
14+
},
15+
},
16+
);
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next';
2+
3+
type Data = {
4+
name: string;
5+
};
6+
7+
export default function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
8+
res.status(200).json({ name: 'John Doe' });
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const config = { runtime: 'edge' };
2+
3+
export default () => {
4+
throw new Error('Edge Route Error');
5+
};
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { test, expect } from '@playwright/test';
2+
import { waitForTransaction, waitForError } from '../../../test-utils/event-proxy-server';
3+
4+
test('Should create a transaction for edge routes', async ({ request }) => {
5+
test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode.");
6+
7+
const edgerouteTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => {
8+
return (
9+
transactionEvent?.transaction === 'GET /api/edge-endpoint' && transactionEvent?.contexts?.trace?.status === 'ok'
10+
);
11+
});
12+
13+
const response = await request.get('/api/edge-endpoint');
14+
expect(await response.json()).toStrictEqual({ name: 'Jim Halpert' });
15+
16+
const edgerouteTransaction = await edgerouteTransactionPromise;
17+
18+
expect(edgerouteTransaction.contexts?.trace?.status).toBe('ok');
19+
expect(edgerouteTransaction.contexts?.trace?.op).toBe('http.server');
20+
expect(edgerouteTransaction.contexts?.runtime?.name).toBe('edge');
21+
});
22+
23+
test('Should create a transaction with error status for faulty edge routes', async ({ request }) => {
24+
test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode.");
25+
26+
const edgerouteTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => {
27+
return (
28+
transactionEvent?.transaction === 'GET /api/error-edge-endpoint' &&
29+
transactionEvent?.contexts?.trace?.status === 'internal_error'
30+
);
31+
});
32+
33+
request.get('/api/error-edge-endpoint').catch(() => {
34+
// Noop
35+
});
36+
37+
const edgerouteTransaction = await edgerouteTransactionPromise;
38+
39+
expect(edgerouteTransaction.contexts?.trace?.status).toBe('internal_error');
40+
expect(edgerouteTransaction.contexts?.trace?.op).toBe('http.server');
41+
expect(edgerouteTransaction.contexts?.runtime?.name).toBe('edge');
42+
});
43+
44+
test('Should record exceptions for faulty edge routes', async ({ request }) => {
45+
test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode.");
46+
47+
const errorEventPromise = waitForError('nextjs-13-app-dir', errorEvent => {
48+
return errorEvent?.exception?.values?.[0]?.value === 'Edge Route Error';
49+
});
50+
51+
request.get('/api/error-edge-endpoint').catch(() => {
52+
// Noop
53+
});
54+
55+
expect(await errorEventPromise).toBeDefined();
56+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { test, expect } from '@playwright/test';
2+
import { waitForTransaction, waitForError } from '../../../test-utils/event-proxy-server';
3+
4+
test('Should create a transaction for middleware', async ({ request }) => {
5+
test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode.");
6+
7+
const middlewareTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => {
8+
return transactionEvent?.transaction === 'middleware' && transactionEvent?.contexts?.trace?.status === 'ok';
9+
});
10+
11+
const response = await request.get('/api/endpoint-behind-middleware');
12+
expect(await response.json()).toStrictEqual({ name: 'John Doe' });
13+
14+
const middlewareTransaction = await middlewareTransactionPromise;
15+
16+
expect(middlewareTransaction.contexts?.trace?.status).toBe('ok');
17+
expect(middlewareTransaction.contexts?.trace?.op).toBe('middleware.nextjs');
18+
expect(middlewareTransaction.contexts?.runtime?.name).toBe('edge');
19+
});
20+
21+
test('Should create a transaction with error status for faulty middleware', async ({ request }) => {
22+
test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode.");
23+
24+
const middlewareTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => {
25+
return (
26+
transactionEvent?.transaction === 'middleware' && transactionEvent?.contexts?.trace?.status === 'internal_error'
27+
);
28+
});
29+
30+
request.get('/api/endpoint-behind-middleware', { headers: { 'x-should-throw': '1' } }).catch(() => {
31+
// Noop
32+
});
33+
34+
const middlewareTransaction = await middlewareTransactionPromise;
35+
36+
expect(middlewareTransaction.contexts?.trace?.status).toBe('internal_error');
37+
expect(middlewareTransaction.contexts?.trace?.op).toBe('middleware.nextjs');
38+
expect(middlewareTransaction.contexts?.runtime?.name).toBe('edge');
39+
});
40+
41+
test('Records exceptions happening in middleware', async ({ request }) => {
42+
test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode.");
43+
44+
const errorEventPromise = waitForError('nextjs-13-app-dir', errorEvent => {
45+
return errorEvent?.exception?.values?.[0]?.value === 'Middleware Error';
46+
});
47+
48+
request.get('/api/endpoint-behind-middleware', { headers: { 'x-should-throw': '1' } }).catch(() => {
49+
// Noop
50+
});
51+
52+
expect(await errorEventPromise).toBeDefined();
53+
});

0 commit comments

Comments
 (0)