Skip to content

Commit a2801d8

Browse files
committed
add and fix tests
1 parent 3ef5afb commit a2801d8

File tree

3 files changed

+130
-9
lines changed

3 files changed

+130
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import * as SentryCore from '@sentry/core';
2+
import * as SentryTracing from '@sentry/tracing';
3+
import { IncomingMessage, ServerResponse } from 'http';
4+
5+
import {
6+
withSentryGetServerSideProps,
7+
withSentryServerSideGetInitialProps,
8+
// TODO: Leaving `withSentryGetStaticProps` out for now until we figure out what to do with it
9+
// withSentryGetStaticProps,
10+
// TODO: Leaving these out for now until we figure out pages with no data fetchers
11+
// withSentryServerSideAppGetInitialProps,
12+
// withSentryServerSideDocumentGetInitialProps,
13+
// withSentryServerSideErrorGetInitialProps,
14+
} from '../../src/config/wrappers';
15+
16+
const startTransactionSpy = jest.spyOn(SentryCore, 'startTransaction');
17+
const setMetadataSpy = jest.spyOn(SentryTracing.Transaction.prototype, 'setMetadata');
18+
19+
describe('data-fetching function wrappers', () => {
20+
const route = '/tricks/[trickName]';
21+
let req: IncomingMessage;
22+
let res: ServerResponse;
23+
24+
describe('starts a transaction if tracing enabled', () => {
25+
beforeEach(() => {
26+
req = { headers: {}, url: 'http://dogs.are.great/tricks/kangaroo' } as IncomingMessage;
27+
res = {} as ServerResponse;
28+
29+
jest.spyOn(SentryTracing, 'hasTracingEnabled').mockReturnValueOnce(true);
30+
});
31+
32+
afterEach(() => {
33+
jest.clearAllMocks();
34+
});
35+
36+
test('withSentryGetServerSideProps', async () => {
37+
const origFunction = jest.fn(async () => ({ props: {} }));
38+
39+
const wrappedOriginal = withSentryGetServerSideProps(origFunction, route);
40+
await wrappedOriginal({ req, res } as any);
41+
42+
expect(startTransactionSpy).toHaveBeenCalledWith(
43+
expect.objectContaining({
44+
name: '/tricks/[trickName]',
45+
op: 'nextjs.data.server',
46+
metadata: expect.objectContaining({ source: 'route' }),
47+
}),
48+
);
49+
50+
expect(setMetadataSpy).toHaveBeenCalledWith({ request: req });
51+
});
52+
53+
test('withSentryServerSideGetInitialProps', async () => {
54+
const origFunction = jest.fn(async () => ({}));
55+
56+
const wrappedOriginal = withSentryServerSideGetInitialProps(origFunction);
57+
await wrappedOriginal({ req, res, pathname: route } as any);
58+
59+
expect(startTransactionSpy).toHaveBeenCalledWith(
60+
expect.objectContaining({
61+
name: '/tricks/[trickName]',
62+
op: 'nextjs.data.server',
63+
metadata: expect.objectContaining({ source: 'route' }),
64+
}),
65+
);
66+
67+
expect(setMetadataSpy).toHaveBeenCalledWith({ request: req });
68+
});
69+
});
70+
});

packages/nextjs/test/index.server.test.ts

+59-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { RequestData } from '@sentry/integrations';
12
import * as SentryNode from '@sentry/node';
23
import { getCurrentHub, NodeClient } from '@sentry/node';
34
import { Integration } from '@sentry/types';
45
import { getGlobalObject, logger } from '@sentry/utils';
56
import * as domain from 'domain';
67

78
import { init } from '../src/index.server';
9+
import { UserIntegrationsFunction } from '../src/utils/userIntegrations';
810

911
const { Integrations } = SentryNode;
1012

@@ -143,31 +145,79 @@ describe('Server init()', () => {
143145

144146
describe('integrations', () => {
145147
// Options passed by `@sentry/nextjs`'s `init` to `@sentry/node`'s `init` after modifying them
146-
type ModifiedInitOptions = { integrations: Integration[] };
148+
type ModifiedInitOptionsIntegrationArray = { integrations: Integration[] };
149+
type ModifiedInitOptionsIntegrationFunction = { integrations: UserIntegrationsFunction };
147150

148151
it('adds default integrations', () => {
149152
init({});
150153

151-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
154+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
152155
const rewriteFramesIntegration = findIntegrationByName(nodeInitOptions.integrations, 'RewriteFrames');
156+
const requestDataFramesIntegration = findIntegrationByName(nodeInitOptions.integrations, 'RequestData');
153157

154158
expect(rewriteFramesIntegration).toBeDefined();
159+
expect(requestDataFramesIntegration).toBeDefined();
155160
});
156161

157162
it('supports passing unrelated integrations through options', () => {
158163
init({ integrations: [new Integrations.Console()] });
159164

160-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
165+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
161166
const consoleIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Console');
162167

163168
expect(consoleIntegration).toBeDefined();
164169
});
165170

171+
describe('`RequestData` integration', () => {
172+
it('forces `include.transaction = false` if user provides `RequestData` in an array', () => {
173+
init({
174+
integrations: [new RequestData({ include: { ip: true } })],
175+
});
176+
177+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
178+
const requestDataIntegration = findIntegrationByName(nodeInitOptions.integrations, 'RequestData');
179+
180+
expect(requestDataIntegration).toEqual(
181+
expect.objectContaining({
182+
_options: expect.objectContaining({
183+
include: expect.objectContaining({
184+
transaction: false,
185+
// This proves it's still the user's copy
186+
ip: true,
187+
}),
188+
}),
189+
}),
190+
);
191+
});
192+
193+
it('forces `include.transaction = false` if user provides `RequestData` in a function', () => {
194+
init({
195+
integrations: defaults => [...defaults, new RequestData({ include: { ip: true } })],
196+
});
197+
198+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationFunction;
199+
const materializedIntegrations = nodeInitOptions.integrations(SentryNode.defaultIntegrations);
200+
const requestDataIntegration = findIntegrationByName(materializedIntegrations, 'RequestData');
201+
202+
expect(requestDataIntegration).toEqual(
203+
expect.objectContaining({
204+
_options: expect.objectContaining({
205+
include: expect.objectContaining({
206+
transaction: false,
207+
// This proves it's still the user's copy
208+
ip: true,
209+
}),
210+
}),
211+
}),
212+
);
213+
});
214+
});
215+
166216
describe('`Http` integration', () => {
167217
it('adds `Http` integration with tracing enabled if `tracesSampleRate` is set', () => {
168218
init({ tracesSampleRate: 1.0 });
169219

170-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
220+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
171221
const httpIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Http');
172222

173223
expect(httpIntegration).toBeDefined();
@@ -177,7 +227,7 @@ describe('Server init()', () => {
177227
it('adds `Http` integration with tracing enabled if `tracesSampler` is set', () => {
178228
init({ tracesSampler: () => true });
179229

180-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
230+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
181231
const httpIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Http');
182232

183233
expect(httpIntegration).toBeDefined();
@@ -187,7 +237,7 @@ describe('Server init()', () => {
187237
it('does not add `Http` integration if tracing not enabled in SDK', () => {
188238
init({});
189239

190-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
240+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
191241
const httpIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Http');
192242

193243
expect(httpIntegration).toBeUndefined();
@@ -199,7 +249,7 @@ describe('Server init()', () => {
199249
integrations: [new Integrations.Http({ tracing: false })],
200250
});
201251

202-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
252+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
203253
const httpIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Http');
204254

205255
expect(httpIntegration).toBeDefined();
@@ -212,7 +262,7 @@ describe('Server init()', () => {
212262
integrations: [new Integrations.Http({ tracing: false })],
213263
});
214264

215-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
265+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
216266
const httpIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Http');
217267

218268
expect(httpIntegration).toBeDefined();
@@ -224,7 +274,7 @@ describe('Server init()', () => {
224274
integrations: [new Integrations.Http({ tracing: false })],
225275
});
226276

227-
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptions;
277+
const nodeInitOptions = nodeInit.mock.calls[0][0] as ModifiedInitOptionsIntegrationArray;
228278
const httpIntegration = findIntegrationByName(nodeInitOptions.integrations, 'Http');
229279

230280
expect(httpIntegration).toBeDefined();

packages/nextjs/test/utils/withSentry.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ describe('withSentry', () => {
119119
metadata: {
120120
baggage: expect.any(Array),
121121
source: 'route',
122+
request: expect.objectContaining({ url: 'http://dogs.are.great' }),
122123
},
123124
},
124125
{ request: expect.objectContaining({ url: 'http://dogs.are.great' }) },

0 commit comments

Comments
 (0)