Skip to content

Commit 48882d2

Browse files
authored
test(react-router): Test v8 middleware (#17783)
1 parent 80e26e0 commit 48882d2

File tree

6 files changed

+97
-0
lines changed

6 files changed

+97
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createContext } from 'react-router';
2+
3+
export type User = {
4+
id: string;
5+
name: string;
6+
};
7+
8+
export const userContext = createContext<User | null>(null);

dev-packages/e2e-tests/test-applications/react-router-7-framework/app/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ export default [
1717
route('static', 'routes/performance/static.tsx'),
1818
route('server-loader', 'routes/performance/server-loader.tsx'),
1919
route('server-action', 'routes/performance/server-action.tsx'),
20+
route('with-middleware', 'routes/performance/with-middleware.tsx'),
2021
]),
2122
] satisfies RouteConfig;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { Route } from './+types/with-middleware';
2+
import type { User } from '../../context';
3+
import { userContext } from '../../context';
4+
import * as Sentry from '@sentry/react-router';
5+
6+
async function getUser() {
7+
await new Promise(resolve => setTimeout(resolve, 500));
8+
return {
9+
id: '1',
10+
name: 'Carlos Gomez',
11+
};
12+
}
13+
14+
const authMiddleware: Route.MiddlewareFunction = async ({ request, context }, next) => {
15+
Sentry.startSpan({ name: 'authMiddleware', op: 'middleware.auth' }, async () => {
16+
const user: User = await getUser();
17+
context.set(userContext, user);
18+
await next();
19+
});
20+
};
21+
22+
export const middleware: Route.MiddlewareFunction[] = [authMiddleware];
23+
24+
export const loader = async ({ context }: Route.LoaderArgs) => {
25+
const user = context.get(userContext);
26+
return { user };
27+
};
28+
29+
export default function WithMiddlewarePage({ loaderData }: Route.ComponentProps) {
30+
const { user } = loaderData;
31+
32+
return (
33+
<div>
34+
<h1>With Middleware Page</h1>
35+
<p>User: {user?.name}</p>
36+
</div>
37+
);
38+
}

dev-packages/e2e-tests/test-applications/react-router-7-framework/package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
},
2525
"scripts": {
2626
"build": "react-router build",
27+
"test:build-latest": "pnpm install && pnpm add react-router@latest && pnpm add @react-router/node@latest && pnpm add @react-router/serve@latest && pnpm build",
2728
"dev": "NODE_OPTIONS='--import ./instrument.mjs' react-router dev",
2829
"start": "NODE_OPTIONS='--import ./instrument.mjs' react-router-serve ./build/server/index.js",
2930
"proxy": "node start-event-proxy.mjs",
@@ -54,5 +55,13 @@
5455
},
5556
"volta": {
5657
"extends": "../../package.json"
58+
},
59+
"sentryTest": {
60+
"variants": [
61+
{
62+
"build-command": "pnpm test:build-latest",
63+
"label": "react-router-7-framework (latest)"
64+
}
65+
]
5766
}
5867
}

dev-packages/e2e-tests/test-applications/react-router-7-framework/react-router.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ import type { Config } from '@react-router/dev/config';
33
export default {
44
ssr: true,
55
prerender: ['/performance/static'],
6+
future: {
7+
v8_middleware: true,
8+
},
69
} satisfies Config;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { expect, test } from '@playwright/test';
2+
import { waitForTransaction } from '@sentry-internal/test-utils';
3+
import { APP_NAME } from '../constants';
4+
5+
test.describe('server - middleware', () => {
6+
test('should send middleware transaction on pageload', async ({ page }) => {
7+
const serverTxPromise = waitForTransaction(APP_NAME, async transactionEvent => {
8+
return transactionEvent.transaction === 'GET /performance/with-middleware';
9+
});
10+
11+
const pageloadTxPromise = waitForTransaction(APP_NAME, async transactionEvent => {
12+
return transactionEvent.transaction === '/performance/with-middleware';
13+
});
14+
15+
const customMiddlewareTxPromise = waitForTransaction(APP_NAME, async transactionEvent => {
16+
return transactionEvent.transaction === 'authMiddleware';
17+
});
18+
19+
await page.goto(`/performance/with-middleware`);
20+
21+
const serverTx = await serverTxPromise;
22+
const pageloadTx = await pageloadTxPromise;
23+
const customMiddlewareTx = await customMiddlewareTxPromise;
24+
25+
const traceIds = {
26+
server: serverTx?.contexts?.trace?.trace_id,
27+
pageload: pageloadTx?.contexts?.trace?.trace_id,
28+
customMiddleware: customMiddlewareTx?.contexts?.trace?.trace_id,
29+
};
30+
31+
expect(pageloadTx).toBeDefined();
32+
expect(customMiddlewareTx).toBeDefined();
33+
34+
// Assert that all transactions belong to the same trace
35+
expect(traceIds.server).toBe(traceIds.pageload);
36+
expect(traceIds.server).toBe(traceIds.customMiddleware);
37+
});
38+
});

0 commit comments

Comments
 (0)