Skip to content

Commit 944cd97

Browse files
committed
add tests for nuxt-3-min
1 parent 625cd7a commit 944cd97

File tree

8 files changed

+222
-2
lines changed

8 files changed

+222
-2
lines changed

dev-packages/e2e-tests/test-applications/nuxt-3-min/nuxt.config.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
// https://nuxt.com/docs/api/configuration/nuxt-config
22
export default defineNuxtConfig({
33
modules: ['@sentry/nuxt/module'],
4-
imports: {
5-
autoImport: false,
4+
imports: { autoImport: false },
5+
6+
routeRules: {
7+
'/rendering-modes/client-side-only-page': { ssr: false },
8+
'/rendering-modes/isr-cached-page': { isr: true },
9+
'/rendering-modes/isr-1h-cached-page': { isr: 3600 },
10+
'/rendering-modes/swr-cached-page': { swr: true },
11+
'/rendering-modes/swr-1h-cached-page': { swr: 3600 },
12+
'/rendering-modes/pre-rendered-page': { prerender: true },
613
},
14+
715
runtimeConfig: {
816
public: {
917
sentry: {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><p>Client Side Only Page</p></template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><p>ISR 1h Cached Page</p></template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><p>ISR Cached Page</p></template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><p>Pre-Rendered Page</p></template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><p>SWR 1h Cached Page</p></template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<template><p>SWR Cached Page</p></template>
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import { expect, test, type Page } from '@playwright/test';
2+
import { waitForTransaction } from '@sentry-internal/test-utils';
3+
4+
test.describe('Rendering Modes with Cached HTML', () => {
5+
test('changes tracing meta tags with multiple requests on Client-Side only page', async ({ page }) => {
6+
await testChangingTracingMetaTagsOnISRPage(page, '/rendering-modes/client-side-only-page', 'Client Side Only Page');
7+
});
8+
9+
test('changes tracing meta tags with multiple requests on ISR-cached page', async ({ page }) => {
10+
await testChangingTracingMetaTagsOnISRPage(page, '/rendering-modes/isr-cached-page', 'ISR Cached Page');
11+
});
12+
13+
test('changes tracing meta tags with multiple requests on 1h ISR-cached page', async ({ page }) => {
14+
await testChangingTracingMetaTagsOnISRPage(page, '/rendering-modes/isr-1h-cached-page', 'ISR 1h Cached Page');
15+
});
16+
17+
test('exclude tracing meta tags on SWR-cached page', async ({ page }) => {
18+
await testExcludeTracingMetaTagsOnCachedPage(page, '/rendering-modes/swr-cached-page', 'SWR Cached Page');
19+
});
20+
21+
test('exclude tracing meta tags on SWR 1h cached page', async ({ page }) => {
22+
await testExcludeTracingMetaTagsOnCachedPage(page, '/rendering-modes/swr-1h-cached-page', 'SWR 1h Cached Page');
23+
});
24+
25+
test('exclude tracing meta tags on pre-rendered page', async ({ page }) => {
26+
await testExcludeTracingMetaTagsOnCachedPage(page, '/rendering-modes/pre-rendered-page', 'Pre-Rendered Page');
27+
});
28+
});
29+
30+
/**
31+
* Tests that tracing meta-tags change with multiple requests on ISR-cached pages
32+
* This utility handles the common pattern of:
33+
* 1. Making two requests to an ISR-cached page
34+
* 2. Verifying tracing meta-tags are present and change between requests
35+
* 3. Verifying distributed tracing works correctly for both requests
36+
* 4. Verifying trace IDs are different between requests
37+
*
38+
* @param page - Playwright page object
39+
* @param routePath - The route path to test (e.g., '/rendering-modes/isr-cached-page')
40+
* @param expectedPageText - The text to verify is visible on the page (e.g., 'ISR Cached Page')
41+
*/
42+
export async function testChangingTracingMetaTagsOnISRPage(
43+
page: Page,
44+
routePath: string,
45+
expectedPageText: string,
46+
): Promise<void> {
47+
// === 1. Request ===
48+
const clientTxnEventPromise1 = waitForTransaction('nuxt-3-min', txnEvent => {
49+
return txnEvent.transaction === routePath;
50+
});
51+
52+
const serverTxnEventPromise1 = waitForTransaction('nuxt-3-min', txnEvent => {
53+
return txnEvent.transaction?.includes(`GET ${routePath}`) ?? false;
54+
});
55+
56+
const [_1, clientTxnEvent1, serverTxnEvent1] = await Promise.all([
57+
page.goto(routePath),
58+
clientTxnEventPromise1,
59+
serverTxnEventPromise1,
60+
expect(page.getByText(expectedPageText, { exact: true })).toBeVisible(),
61+
]);
62+
63+
const baggageMetaTagContent1 = await page.locator('meta[name="baggage"]').getAttribute('content');
64+
const sentryTraceMetaTagContent1 = await page.locator('meta[name="sentry-trace"]').getAttribute('content');
65+
const [htmlMetaTraceId1] = sentryTraceMetaTagContent1?.split('-') || [];
66+
67+
// === 2. Request ===
68+
69+
const clientTxnEventPromise2 = waitForTransaction('nuxt-3-min', txnEvent => {
70+
return txnEvent.transaction === routePath;
71+
});
72+
73+
const serverTxnEventPromise2 = waitForTransaction('nuxt-3-min', txnEvent => {
74+
return txnEvent.transaction?.includes(`GET ${routePath}`) ?? false;
75+
});
76+
77+
const [_2, clientTxnEvent2, serverTxnEvent2] = await Promise.all([
78+
page.goto(routePath),
79+
clientTxnEventPromise2,
80+
serverTxnEventPromise2,
81+
expect(page.getByText(expectedPageText, { exact: true })).toBeVisible(),
82+
]);
83+
84+
const baggageMetaTagContent2 = await page.locator('meta[name="baggage"]').getAttribute('content');
85+
const sentryTraceMetaTagContent2 = await page.locator('meta[name="sentry-trace"]').getAttribute('content');
86+
const [htmlMetaTraceId2] = sentryTraceMetaTagContent2?.split('-') || [];
87+
88+
const serverTxnEvent1TraceId = serverTxnEvent1.contexts?.trace?.trace_id;
89+
const serverTxnEvent2TraceId = serverTxnEvent2.contexts?.trace?.trace_id;
90+
91+
await test.step('Test distributed trace from 1. request', () => {
92+
expect(baggageMetaTagContent1).toContain(`sentry-trace_id=${serverTxnEvent1TraceId}`);
93+
94+
expect(clientTxnEvent1.contexts?.trace?.trace_id).toBe(serverTxnEvent1TraceId);
95+
expect(clientTxnEvent1.contexts?.trace?.parent_span_id).toBe(serverTxnEvent1.contexts?.trace?.span_id);
96+
expect(serverTxnEvent1.contexts?.trace?.trace_id).toBe(htmlMetaTraceId1);
97+
});
98+
99+
await test.step('Test distributed trace from 2. request', () => {
100+
expect(baggageMetaTagContent2).toContain(`sentry-trace_id=${serverTxnEvent2TraceId}`);
101+
102+
expect(clientTxnEvent2.contexts?.trace?.trace_id).toBe(serverTxnEvent2TraceId);
103+
expect(clientTxnEvent2.contexts?.trace?.parent_span_id).toBe(serverTxnEvent2.contexts?.trace?.span_id);
104+
expect(serverTxnEvent2.contexts?.trace?.trace_id).toBe(htmlMetaTraceId2);
105+
});
106+
107+
await test.step('Test that trace IDs from subsequent requests are different', () => {
108+
// Different trace IDs for the server transactions
109+
expect(serverTxnEvent1TraceId).toBeDefined();
110+
expect(serverTxnEvent1TraceId).not.toBe(serverTxnEvent2TraceId);
111+
expect(serverTxnEvent1TraceId).not.toBe(htmlMetaTraceId2);
112+
});
113+
}
114+
115+
/**
116+
* Tests that tracing meta-tags are excluded on cached pages (SWR, pre-rendered, etc.)
117+
* This utility handles the common pattern of:
118+
* 1. Making two requests to a cached page
119+
* 2. Verifying no tracing meta-tags are present
120+
* 3. Verifying only the first request creates a server transaction
121+
* 4. Verifying traces are not distributed
122+
*
123+
* @param page - Playwright page object
124+
* @param routePath - The route path to test (e.g., '/rendering-modes/swr-cached-page')
125+
* @param expectedPageText - The text to verify is visible on the page (e.g., 'SWR Cached Page')
126+
* @returns Object containing transaction events for additional custom assertions
127+
*/
128+
export async function testExcludeTracingMetaTagsOnCachedPage(
129+
page: Page,
130+
routePath: string,
131+
expectedPageText: string,
132+
): Promise<void> {
133+
// === 1. Request ===
134+
const clientTxnEventPromise1 = waitForTransaction('nuxt-3-min', txnEvent => {
135+
return txnEvent.transaction === routePath;
136+
});
137+
138+
// Only the 1. request creates a server transaction
139+
const serverTxnEventPromise1 = waitForTransaction('nuxt-3-min', txnEvent => {
140+
return txnEvent.transaction?.includes(`GET ${routePath}`) ?? false;
141+
});
142+
143+
const [_1, clientTxnEvent1, serverTxnEvent1] = await Promise.all([
144+
page.goto(routePath),
145+
clientTxnEventPromise1,
146+
serverTxnEventPromise1,
147+
expect(page.getByText(expectedPageText, { exact: true })).toBeVisible(),
148+
]);
149+
150+
// Verify no baggage and sentry-trace meta-tags are present on first request
151+
expect(await page.locator('meta[name="baggage"]').count()).toBe(0);
152+
expect(await page.locator('meta[name="sentry-trace"]').count()).toBe(0);
153+
154+
// === 2. Request ===
155+
156+
await page.goto(routePath);
157+
158+
const clientTxnEventPromise2 = waitForTransaction('nuxt-3-min', txnEvent => {
159+
return txnEvent.transaction === routePath;
160+
});
161+
162+
let serverTxnEvent2 = undefined;
163+
const serverTxnEventPromise2 = Promise.race([
164+
waitForTransaction('nuxt-3-min', txnEvent => {
165+
return txnEvent.transaction?.includes(`GET ${routePath}`) ?? false;
166+
}),
167+
new Promise((_, reject) => setTimeout(() => reject(new Error('No second server transaction expected')), 2000)),
168+
]);
169+
170+
try {
171+
serverTxnEvent2 = await serverTxnEventPromise2;
172+
throw new Error('Second server transaction should not have been sent');
173+
} catch (error) {
174+
expect(error.message).toBe('No second server transaction expected');
175+
}
176+
177+
const [clientTxnEvent2] = await Promise.all([
178+
clientTxnEventPromise2,
179+
expect(page.getByText(expectedPageText, { exact: true })).toBeVisible(),
180+
]);
181+
182+
const clientTxnEvent1TraceId = clientTxnEvent1.contexts?.trace?.trace_id;
183+
const clientTxnEvent2TraceId = clientTxnEvent2.contexts?.trace?.trace_id;
184+
185+
const serverTxnEvent1TraceId = serverTxnEvent1.contexts?.trace?.trace_id;
186+
const serverTxnEvent2TraceId = serverTxnEvent2?.contexts?.trace?.trace_id;
187+
188+
await test.step('No baggage and sentry-trace meta-tags are present on second request', async () => {
189+
expect(await page.locator('meta[name="baggage"]').count()).toBe(0);
190+
expect(await page.locator('meta[name="sentry-trace"]').count()).toBe(0);
191+
});
192+
193+
await test.step('1. Server Transaction and all Client Transactions are defined', () => {
194+
expect(serverTxnEvent1TraceId).toBeDefined();
195+
expect(clientTxnEvent1TraceId).toBeDefined();
196+
expect(clientTxnEvent2TraceId).toBeDefined();
197+
expect(serverTxnEvent2).toBeUndefined();
198+
expect(serverTxnEvent2TraceId).toBeUndefined();
199+
});
200+
201+
await test.step('Trace is not distributed', () => {
202+
// Cannot create distributed trace as HTML Meta Tags are not added (caching leads to multiple usages of the same server trace id)
203+
expect(clientTxnEvent1TraceId).not.toBe(clientTxnEvent2TraceId);
204+
expect(clientTxnEvent1TraceId).not.toBe(serverTxnEvent1TraceId);
205+
});
206+
}

0 commit comments

Comments
 (0)