Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ const router = createRouter({ routeTree, ...(__APP_BASEPATH__ ? { basepath: __AP
declare const __APP_DSN__: string;

Sentry.init({
traceLifecycle: 'static',
environment: 'qa', // dynamic sampling bias to keep transactions
dsn: __APP_DSN__,
integrations: [Sentry.tanstackRouterBrowserTracingIntegration(router)],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, test } from '@playwright/test';
import { waitForError, waitForTransaction } from '@sentry-internal/test-utils';
import { getSpanOp, waitForError, waitForStreamedSpan } from '@sentry-internal/test-utils';

// Only meaningful in the `tanstack-router (basepath)` variant, where the router is created with
// `basepath: '/app'`. The rest of the suite runs in both variants.
Expand All @@ -12,39 +12,38 @@ test.describe('router basepath', () => {
// pageload against the raw browser path let the catch-all `/$a/$b/$c` route absorb `app` as a
// param instead of matching `/posts/$postId`.
test('does not leak the basepath into the matched route params', async ({ page }) => {
const transactionPromise = waitForTransaction('tanstack-router', async transactionEvent => {
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
const pageloadSpanPromise = waitForStreamedSpan('tanstack-router', span => {
return span.is_segment && getSpanOp(span) === 'pageload';
});

await page.goto(`${BASE}/posts/456`);

const rootSpan = await transactionPromise;
const pageloadSpan = await pageloadSpanPromise;

// `onResolved` later merges the correct params in, but never clears the ones the bad initial
// match already set, so the stale `a`/`b`/`c` params survive on the span. Keys are passed as
// arrays because `toHaveProperty` would otherwise read the dots as a nested lookup.
const traceData = rootSpan.contexts?.trace?.data;
expect(traceData).not.toHaveProperty(['url.path.parameter.a']);
expect(traceData).not.toHaveProperty(['url.path.parameter.b']);
expect(traceData).not.toHaveProperty(['url.path.parameter.c']);
expect(traceData).toHaveProperty(['url.path.parameter.postId'], '456');
expect(traceData).toHaveProperty(['url.template'], '/posts/$postId');
expect(pageloadSpan.attributes).not.toHaveProperty(['url.path.parameter.a']);
expect(pageloadSpan.attributes).not.toHaveProperty(['url.path.parameter.b']);
expect(pageloadSpan.attributes).not.toHaveProperty(['url.path.parameter.c']);
expect(pageloadSpan.attributes['url.path.parameter.postId']).toEqual({ type: 'string', value: '456' });
expect(pageloadSpan.attributes['url.template']).toEqual({ type: 'string', value: '/posts/$postId' });
});

// The first test only checks the span. The scope transaction is a separate value: it is set once
// when the pageload span starts, and the later `updateName` in `onResolved` does not rewrite it.
// So even when the sent transaction name is correct, errors captured after the pageload still
// So even when the sent span name is correct, errors captured after the pageload still
// carry the name from the initial match. This test checks that scope transaction.
test('attributes errors to the matched route for the whole page lifetime', async ({ page }) => {
const transactionPromise = waitForTransaction('tanstack-router', async transactionEvent => {
return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload';
const pageloadSpanPromise = waitForStreamedSpan('tanstack-router', span => {
return span.is_segment && getSpanOp(span) === 'pageload';
});
const errorPromise = waitForError('tanstack-router', async errorEvent => {
return errorEvent.exception?.values?.[0]?.value === 'Error thrown after pageload';
});

await page.goto(`${BASE}/posts/456`);
await transactionPromise;
await pageloadSpanPromise;

await page.evaluate(() => {
setTimeout(() => {
Expand Down
Loading
Loading