Skip to content

Commit 2703fd4

Browse files
committed
tests: added middleware e2e tests
1 parent 677686f commit 2703fd4

File tree

10 files changed

+222
-0
lines changed

10 files changed

+222
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineEventHandler, getHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Simple API endpoint that will trigger all server middleware
5+
return {
6+
message: 'Server middleware test endpoint',
7+
path: event.path,
8+
method: event.method,
9+
headers: {
10+
'x-first-middleware': getHeader(event, 'x-first-middleware'),
11+
'x-second-middleware': getHeader(event, 'x-second-middleware'),
12+
'x-auth-middleware': getHeader(event, 'x-auth-middleware'),
13+
},
14+
};
15+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-first-middleware', 'executed');
6+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-second-middleware', 'executed');
6+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-auth-middleware', 'executed');
6+
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { expect, test } from '@playwright/test';
2+
import { waitForTransaction } from '@sentry-internal/test-utils';
3+
4+
test.describe('Server Middleware Instrumentation', () => {
5+
test('should create separate spans for each server middleware', async ({ request }) => {
6+
const serverTxnEventPromise = waitForTransaction('nuxt-3', txnEvent => {
7+
return txnEvent.transaction?.includes('GET /api/middleware-test') ?? false;
8+
});
9+
10+
// Make request to the API endpoint that will trigger all server middleware
11+
const response = await request.get('/api/middleware-test');
12+
expect(response.status()).toBe(200);
13+
14+
const responseData = await response.json();
15+
expect(responseData.message).toBe('Server middleware test endpoint');
16+
17+
const serverTxnEvent = await serverTxnEventPromise;
18+
19+
// Verify that we have spans for each middleware
20+
const middlewareSpans = serverTxnEvent.spans?.filter(span => span.op === 'http.server.middleware') || [];
21+
22+
expect(middlewareSpans).toHaveLength(3);
23+
24+
// Check for specific middleware spans
25+
const firstMiddlewareSpan = middlewareSpans.find(span => span.data?.['nuxt.middleware.name'] === '01.first.ts');
26+
const secondMiddlewareSpan = middlewareSpans.find(span => span.data?.['nuxt.middleware.name'] === '02.second.ts');
27+
const authMiddlewareSpan = middlewareSpans.find(span => span.data?.['nuxt.middleware.name'] === '03.auth.ts');
28+
29+
expect(firstMiddlewareSpan).toBeDefined();
30+
expect(secondMiddlewareSpan).toBeDefined();
31+
expect(authMiddlewareSpan).toBeDefined();
32+
33+
// Verify each span has the correct attributes
34+
[firstMiddlewareSpan, secondMiddlewareSpan, authMiddlewareSpan].forEach(span => {
35+
expect(span).toEqual(
36+
expect.objectContaining({
37+
op: 'http.server.middleware',
38+
data: expect.objectContaining({
39+
'sentry.op': 'http.server.middleware',
40+
'sentry.origin': 'auto.http.nuxt',
41+
'sentry.source': 'custom',
42+
'http.request.method': 'GET',
43+
'http.route': '/api/middleware-test',
44+
}),
45+
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
46+
span_id: expect.stringMatching(/[a-f0-9]{16}/),
47+
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
48+
}),
49+
);
50+
});
51+
52+
// Verify spans have different span IDs (each middleware gets its own span)
53+
const spanIds = middlewareSpans.map(span => span.span_id);
54+
const uniqueSpanIds = new Set(spanIds);
55+
expect(uniqueSpanIds.size).toBe(3);
56+
57+
// Verify spans share the same trace ID
58+
const traceIds = middlewareSpans.map(span => span.trace_id);
59+
const uniqueTraceIds = new Set(traceIds);
60+
expect(uniqueTraceIds.size).toBe(1);
61+
});
62+
63+
test('middleware spans should have proper parent-child relationship', async ({ request }) => {
64+
const serverTxnEventPromise = waitForTransaction('nuxt-3', txnEvent => {
65+
return txnEvent.transaction?.includes('GET /api/middleware-test') ?? false;
66+
});
67+
68+
await request.get('/api/middleware-test');
69+
const serverTxnEvent = await serverTxnEventPromise;
70+
71+
const middlewareSpans = serverTxnEvent.spans?.filter(span => span.op === 'http.server.middleware') || [];
72+
73+
// All middleware spans should be children of the main transaction
74+
middlewareSpans.forEach(span => {
75+
expect(span.parent_span_id).toBe(serverTxnEvent.contexts?.trace?.span_id);
76+
});
77+
});
78+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineEventHandler, getHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Simple API endpoint that will trigger all server middleware
5+
return {
6+
message: 'Server middleware test endpoint',
7+
path: event.path,
8+
method: event.method,
9+
headers: {
10+
'x-first-middleware': getHeader(event, 'x-first-middleware'),
11+
'x-second-middleware': getHeader(event, 'x-second-middleware'),
12+
'x-auth-middleware': getHeader(event, 'x-auth-middleware'),
13+
},
14+
};
15+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-first-middleware', 'executed');
6+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-second-middleware', 'executed');
6+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { defineEventHandler, setHeader } from '#imports';
2+
3+
export default defineEventHandler(async event => {
4+
// Set a header to indicate this middleware ran
5+
setHeader(event, 'x-auth-middleware', 'executed');
6+
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { expect, test } from '@playwright/test';
2+
import { waitForTransaction } from '@sentry-internal/test-utils';
3+
4+
test.describe('Server Middleware Instrumentation', () => {
5+
test('should create separate spans for each server middleware', async ({ request }) => {
6+
const serverTxnEventPromise = waitForTransaction('nuxt-4', txnEvent => {
7+
return txnEvent.transaction?.includes('GET /api/middleware-test') ?? false;
8+
});
9+
10+
// Make request to the API endpoint that will trigger all server middleware
11+
const response = await request.get('/api/middleware-test');
12+
expect(response.status()).toBe(200);
13+
14+
const responseData = await response.json();
15+
expect(responseData.message).toBe('Server middleware test endpoint');
16+
17+
const serverTxnEvent = await serverTxnEventPromise;
18+
19+
// Verify that we have spans for each middleware
20+
const middlewareSpans = serverTxnEvent.spans?.filter(span => span.op === 'http.server.middleware') || [];
21+
22+
expect(middlewareSpans).toHaveLength(3);
23+
24+
// Check for specific middleware spans
25+
const firstMiddlewareSpan = middlewareSpans.find(span => span.data?.['nuxt.middleware.name'] === '01.first.ts');
26+
const secondMiddlewareSpan = middlewareSpans.find(span => span.data?.['nuxt.middleware.name'] === '02.second.ts');
27+
const authMiddlewareSpan = middlewareSpans.find(span => span.data?.['nuxt.middleware.name'] === '03.auth.ts');
28+
29+
expect(firstMiddlewareSpan).toBeDefined();
30+
expect(secondMiddlewareSpan).toBeDefined();
31+
expect(authMiddlewareSpan).toBeDefined();
32+
33+
// Verify each span has the correct attributes
34+
[firstMiddlewareSpan, secondMiddlewareSpan, authMiddlewareSpan].forEach(span => {
35+
expect(span).toEqual(
36+
expect.objectContaining({
37+
op: 'http.server.middleware',
38+
data: expect.objectContaining({
39+
'sentry.op': 'http.server.middleware',
40+
'sentry.origin': 'auto.http.nuxt',
41+
'sentry.source': 'custom',
42+
'http.request.method': 'GET',
43+
'http.route': '/api/middleware-test',
44+
}),
45+
parent_span_id: expect.stringMatching(/[a-f0-9]{16}/),
46+
span_id: expect.stringMatching(/[a-f0-9]{16}/),
47+
trace_id: expect.stringMatching(/[a-f0-9]{32}/),
48+
}),
49+
);
50+
});
51+
52+
// Verify spans have different span IDs (each middleware gets its own span)
53+
const spanIds = middlewareSpans.map(span => span.span_id);
54+
const uniqueSpanIds = new Set(spanIds);
55+
expect(uniqueSpanIds.size).toBe(3);
56+
57+
// Verify spans share the same trace ID
58+
const traceIds = middlewareSpans.map(span => span.trace_id);
59+
const uniqueTraceIds = new Set(traceIds);
60+
expect(uniqueTraceIds.size).toBe(1);
61+
});
62+
63+
test('middleware spans should have proper parent-child relationship', async ({ request }) => {
64+
const serverTxnEventPromise = waitForTransaction('nuxt-4', txnEvent => {
65+
return txnEvent.transaction?.includes('GET /api/middleware-test') ?? false;
66+
});
67+
68+
await request.get('/api/middleware-test');
69+
const serverTxnEvent = await serverTxnEventPromise;
70+
71+
const middlewareSpans = serverTxnEvent.spans?.filter(span => span.op === 'http.server.middleware') || [];
72+
73+
// All middleware spans should be children of the main transaction
74+
middlewareSpans.forEach(span => {
75+
expect(span.parent_span_id).toBe(serverTxnEvent.contexts?.trace?.span_id);
76+
});
77+
});
78+
});

0 commit comments

Comments
 (0)