Skip to content

Commit 3540666

Browse files
committed
Update react router sdk tests
1 parent 56c4346 commit 3540666

File tree

2 files changed

+116
-5
lines changed

2 files changed

+116
-5
lines changed

packages/react-router/src/server/sdk.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,27 @@ export function init(options: NodeOptions): NodeClient | undefined {
2626
return client;
2727
}
2828

29+
const matchedRegexes = [
30+
/GET \/node_modules\//,
31+
/GET \/favicon\.ico/,
32+
/GET \/@id\//,
33+
];
34+
2935
/**
30-
* Filters out noisy transactions such as requests to node_modules
36+
* Filters out noisy transactions such as requests to node_modules, favicon.ico, @id/
3137
*
3238
* @param options The NodeOptions passed to the SDK
3339
* @returns An EventProcessor that filters low-quality transactions
3440
*/
3541
export function lowQualityTransactionsFilter(options: NodeOptions): EventProcessor {
3642
return Object.assign(
3743
(event => {
44+
3845
if (event.type !== 'transaction' || !event.transaction) {
3946
return event;
4047
}
4148

42-
if (event.transaction.match(/\/node_modules\//)) {
49+
if (matchedRegexes.some(regex => event.transaction?.match(regex))) {
4350
options.debug &&
4451
logger.log('[ReactRouter] Filtered node_modules transaction:', event.transaction);
4552
return null;

packages/react-router/test/server/sdk.test.ts

Lines changed: 107 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2+
3+
import { getGlobalScope } from '@sentry/core';
4+
import type { Event, EventType } from '@sentry/core';
15
import * as SentryNode from '@sentry/node';
6+
import type { NodeClient } from '@sentry/node';
27
import { SDK_VERSION } from '@sentry/node';
3-
import { afterEach, describe, expect, it, vi } from 'vitest';
4-
import { init as reactRouterInit } from '../../src/server/sdk';
8+
9+
import { init as reactRouterInit, lowQualityTransactionsFilter } from '../../src/server/sdk';
510

611
const nodeInit = vi.spyOn(SentryNode, 'init');
712

@@ -39,7 +44,106 @@ describe('React Router server SDK', () => {
3944
});
4045

4146
it('returns client from init', () => {
42-
expect(reactRouterInit({})).not.toBeUndefined();
47+
const client = reactRouterInit({
48+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
49+
}) as NodeClient;
50+
expect(client).not.toBeUndefined();
51+
});
52+
53+
it('registers the low quality transactions filter', async () => {
54+
const addEventProcessor = vi.spyOn(getGlobalScope(), 'addEventProcessor');
55+
addEventProcessor.mockClear();
56+
57+
reactRouterInit({
58+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
59+
}) as NodeClient;
60+
61+
expect(addEventProcessor).toHaveBeenCalledTimes(1);
62+
const processor = addEventProcessor.mock.calls[0]![0];
63+
expect(processor?.id).toEqual('ReactRouterLowQualityTransactionsFilter');
64+
});
65+
66+
describe('transaction filtering', () => {
67+
const beforeSendEvent = vi.fn(event => event);
68+
let client: NodeClient;
69+
70+
beforeEach(() => {
71+
vi.clearAllMocks();
72+
beforeSendEvent.mockClear();
73+
SentryNode.getGlobalScope().clear();
74+
75+
client = reactRouterInit({
76+
dsn: 'https://public@dsn.ingest.sentry.io/1337',
77+
}) as NodeClient;
78+
79+
client.on('beforeSendEvent', beforeSendEvent);
80+
});
81+
82+
describe('filters out low quality transactions', () => {
83+
it.each([
84+
'GET /node_modules/react/index.js',
85+
'GET /favicon.ico',
86+
'GET /@id/package',
87+
])('%s', async (transaction) => {
88+
client.captureEvent({ type: 'transaction', transaction });
89+
90+
await client.flush();
91+
92+
expect(beforeSendEvent).not.toHaveBeenCalled();
93+
});
94+
});
95+
96+
describe('allows high quality transactions', () => {
97+
it.each([
98+
'GET /',
99+
'GET /users',
100+
'POST /api/data',
101+
'GET /projects/123',
102+
])('%s', async (transaction) => {
103+
client.captureEvent({ type: 'transaction', transaction });
104+
105+
await client.flush();
106+
107+
expect(beforeSendEvent).toHaveBeenCalledWith(
108+
expect.objectContaining({ transaction }),
109+
expect.any(Object)
110+
);
111+
});
112+
});
113+
});
114+
});
115+
116+
describe('lowQualityTransactionsFilter', () => {
117+
describe('filters out low quality transactions', () => {
118+
it.each([
119+
['node_modules request', 'GET /node_modules/react/index.js'],
120+
['favicon.ico request', 'GET /favicon.ico'],
121+
['@id request', 'GET /@id/package']
122+
])('%s', (description, transaction) => {
123+
const filter = lowQualityTransactionsFilter({});
124+
const event = {
125+
type: 'transaction' as EventType,
126+
transaction,
127+
} as Event;
128+
129+
expect(filter(event, {})).toBeNull();
130+
});
131+
});
132+
133+
describe('does not filter good transactions', () => {
134+
it.each([
135+
['normal page request', 'GET /users'],
136+
['API request', 'POST /api/users'],
137+
['app route', 'GET /projects/123']
138+
])('%s', (description, transaction) => {
139+
const filter = lowQualityTransactionsFilter({});
140+
const event = {
141+
type: 'transaction' as EventType,
142+
transaction,
143+
} as Event;
144+
145+
expect(filter(event, {})).toBe(event);
146+
});
43147
});
44148
});
45149
});

0 commit comments

Comments
 (0)