Skip to content

Commit d83f850

Browse files
committed
adjust tests
1 parent 275b1aa commit d83f850

7 files changed

Lines changed: 80 additions & 4 deletions

File tree

dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/server-transactions.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ test('Sends parameterized transaction name to Sentry', async ({ page }) => {
1414

1515
expect(transaction).toBeDefined();
1616
expect(transaction.transaction).toBe('GET user/:id');
17+
expect(transaction.contexts?.trace?.data?.['http.route']).toBe('user/:id');
1718
});
1819

1920
test('Sends form data with action span', async ({ page }) => {
@@ -271,6 +272,7 @@ test('Sends two linked transactions (server & client) to Sentry', async ({ page
271272
const pageLoadParentSpanId = pageloadTransaction.contexts?.trace?.parent_span_id;
272273

273274
expect(httpServerTransaction.transaction).toBe('GET http://localhost:3030/');
275+
expect(httpServerTransaction.contexts?.trace?.data?.['http.route']).toBeUndefined();
274276
expect(pageloadTransaction.transaction).toBe('/');
275277

276278
expect(httpServerTraceId).toBeDefined();

packages/elysia/test/withElysia.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { HTTP_ROUTE } from '@sentry/conventions/attributes';
12
import type { ErrorContext } from 'elysia';
23
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
34

@@ -32,6 +33,12 @@ const mockGetIsolationScope = vi.fn(() => ({
3233
const mockGetClient = vi.fn(() => ({
3334
on: vi.fn(),
3435
}));
36+
const mockRootSpan = {
37+
setAttributes: vi.fn(),
38+
updateName: vi.fn(),
39+
};
40+
const mockGetActiveSpan = vi.fn();
41+
const mockGetRootSpan = vi.fn(() => mockRootSpan);
3542
const mockGetTraceData = vi.fn(() => ({
3643
'sentry-trace': 'abc123-def456-1',
3744
baggage: 'sentry-environment=test,sentry-trace_id=abc123',
@@ -43,8 +50,10 @@ vi.mock('@sentry/core', async importActual => {
4350
return {
4451
...actual,
4552
captureException: (...args: unknown[]) => mockCaptureException(...args),
53+
getActiveSpan: () => mockGetActiveSpan(),
4654
getIsolationScope: () => mockGetIsolationScope(),
4755
getClient: () => mockGetClient(),
56+
getRootSpan: () => mockGetRootSpan(),
4857
getTraceData: () => mockGetTraceData(),
4958
};
5059
});
@@ -88,6 +97,23 @@ describe('withElysia', () => {
8897
expect(headers['baggage']).toBe('sentry-environment=test,sentry-trace_id=abc123');
8998
});
9099

100+
it('sets the matched route on the root span', () => {
101+
mockGetActiveSpan.mockReturnValueOnce(mockRootSpan);
102+
// @ts-expect-error - mock app
103+
withElysia(mockApp);
104+
105+
onAfterHandleHandler({
106+
route: '/users/:id',
107+
request: new Request('https://example.com/users/42', { method: 'GET' }),
108+
set: { headers: {} },
109+
});
110+
111+
expect(mockRootSpan.setAttributes).toHaveBeenCalledWith({
112+
'sentry.source': 'route',
113+
[HTTP_ROUTE]: '/users/:id',
114+
});
115+
});
116+
91117
it('does not set headers when trace data is empty', () => {
92118
mockGetTraceData.mockReturnValueOnce({});
93119
// @ts-expect-error - mock app

packages/hono/test/shared/middlewareHandlers.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as SentryCore from '@sentry/core';
2+
import { HTTP_ROUTE } from '@sentry/conventions/attributes';
23
import { beforeEach, describe, expect, it, vi } from 'vitest';
34
import { requestHandler, responseHandler } from '../../src/shared/middlewareHandlers';
45

@@ -245,6 +246,18 @@ describe('responseHandler', () => {
245246

246247
expect(mockSetTransactionName).toHaveBeenCalledWith('GET /test');
247248
});
249+
250+
it('sets http.route on the root span', () => {
251+
getActiveSpanMock.mockReturnValue(mockRootSpan);
252+
253+
// oxlint-disable-next-line typescript/no-explicit-any
254+
requestHandler(createMockContext(200) as any);
255+
256+
expect(mockRootSpan.setAttributes).toHaveBeenCalledWith({
257+
'sentry.source': 'route',
258+
[HTTP_ROUTE]: 'GET /test',
259+
});
260+
});
248261
});
249262
});
250263

packages/nextjs/test/config/withSentry.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as SentryCore from '@sentry/core';
2-
import { URL_FULL, URL_PATH } from '@sentry/conventions/attributes';
2+
import { HTTP_ROUTE, URL_FULL, URL_PATH } from '@sentry/conventions/attributes';
33
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
44
import type { NextApiRequest, NextApiResponse } from 'next';
55
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
@@ -55,6 +55,7 @@ describe('withSentry', () => {
5555
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.nextjs',
5656
[URL_FULL]: 'https://dogs.are.great/api/dogs?good=true',
5757
[URL_PATH]: '/api/dogs',
58+
[HTTP_ROUTE]: '/my-parameterized-route',
5859
},
5960
},
6061
expect.any(Function),

packages/nextjs/test/edge/withSentryAPI.test.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { afterAll, afterEach, describe, it, vi } from 'vitest';
1+
import * as SentryCore from '@sentry/core';
2+
import { HTTP_ROUTE, URL_FULL, URL_PATH } from '@sentry/conventions/attributes';
3+
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
4+
import { afterAll, afterEach, describe, expect, it, vi } from 'vitest';
25
import { wrapApiHandlerWithSentry } from '../../src/edge';
36

47
const origRequest = global.Request;
@@ -30,7 +33,7 @@ afterAll(() => {
3033
});
3134

3235
afterEach(() => {
33-
vi.clearAllMocks();
36+
vi.restoreAllMocks();
3437
});
3538

3639
describe('wrapApiHandlerWithSentry', () => {
@@ -41,4 +44,28 @@ describe('wrapApiHandlerWithSentry', () => {
4144

4245
await wrappedFunction();
4346
});
47+
48+
it('adds normalized request URL and route attributes to the active root span', async () => {
49+
const rootSpan = {
50+
updateName: vi.fn(),
51+
setAttributes: vi.fn(),
52+
};
53+
vi.spyOn(SentryCore, 'getActiveSpan').mockReturnValueOnce({} as any);
54+
vi.spyOn(SentryCore, 'getRootSpan').mockReturnValueOnce(rootSpan as any);
55+
vi.spyOn(SentryCore, 'spanToJSON').mockReturnValueOnce({ data: {} } as any);
56+
const origFunction = vi.fn(() => new Response());
57+
const parameterizedRoute = '/user/[userId]/post/[postId]';
58+
const wrappedFunction = wrapApiHandlerWithSentry(origFunction, parameterizedRoute);
59+
60+
await wrappedFunction(new Request('https://dogs.are.great/user/123/post/456?good=true'));
61+
62+
expect(rootSpan.updateName).toHaveBeenCalledWith(`POST ${parameterizedRoute}`);
63+
expect(rootSpan.setAttributes).toHaveBeenCalledWith({
64+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
65+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
66+
[URL_FULL]: 'https://dogs.are.great/user/123/post/456?good=true',
67+
[URL_PATH]: '/user/123/post/456',
68+
[HTTP_ROUTE]: parameterizedRoute,
69+
});
70+
});
4471
});

packages/nextjs/test/server/enhanceHandleRequestRootSpan.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { HTTP_ROUTE } from '@sentry/conventions/attributes';
12
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
23
import { describe, expect, it } from 'vitest';
34
import { ATTR_NEXT_ROUTE, ATTR_NEXT_SPAN_NAME, ATTR_NEXT_SPAN_TYPE } from '../../src/common/nextSpanAttributes';
@@ -105,6 +106,7 @@ describe('enhanceHandleRequestRootSpan', () => {
105106
enhanceHandleRequestRootSpan(span);
106107

107108
expect(getName()).toBe('GET /posts/[slug]');
109+
expect(span.attributes[HTTP_ROUTE]).toBe('/posts/[slug]');
108110
});
109111

110112
it('does not apply the backfill for the special GET /_app transaction', () => {

packages/sveltekit/test/server-common/handle.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { EventEnvelopeHeaders, Span } from '@sentry/core';
2+
import { HTTP_ROUTE } from '@sentry/conventions/attributes';
23
import {
34
getRootSpan,
45
getSpanDescendants,
@@ -143,6 +144,7 @@ describe('sentryHandle', () => {
143144
expect(spanToJSON(_span!).op).toEqual('http.server');
144145
expect(spanToJSON(_span!).status).toEqual(isError ? 'internal_error' : 'ok');
145146
expect(spanToJSON(_span!).data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]).toEqual('route');
147+
expect(spanToJSON(_span!).data?.[HTTP_ROUTE]).toEqual('/users/[id]');
146148

147149
expect(spanToJSON(_span!).timestamp).toBeDefined();
148150

@@ -151,6 +153,7 @@ describe('sentryHandle', () => {
151153
});
152154

153155
it("doesn't start a span if sveltekit tracing is enabled", async () => {
156+
const kitRootSpan = SentryCore.startInactiveSpan({ name: 'sveltekit.handle.root' });
154157
let _span: Span | undefined = undefined;
155158
client.on('spanEnd', span => {
156159
if (span === getRootSpan(span)) {
@@ -160,14 +163,16 @@ describe('sentryHandle', () => {
160163

161164
try {
162165
await sentryHandle()({
163-
event: mockEvent({ tracing: { enabled: true } }),
166+
event: mockEvent({ tracing: { enabled: true, root: kitRootSpan } }),
164167
resolve: resolve(type, isError),
165168
});
166169
} catch {
167170
//
168171
}
169172

170173
expect(_span).toBeUndefined();
174+
expect(spanToJSON(kitRootSpan).data?.[HTTP_ROUTE]).toEqual('/users/[id]');
175+
kitRootSpan.end();
171176
});
172177

173178
it('starts a child span for nested server calls (i.e. if there is an active span)', async () => {

0 commit comments

Comments
 (0)