Skip to content

Commit 6f3cde4

Browse files
committed
ref(serverless): Fix GCPFunction tests
1 parent 49d7686 commit 6f3cde4

File tree

1 file changed

+118
-83
lines changed

1 file changed

+118
-83
lines changed

packages/serverless/test/gcpfunction.test.ts

Lines changed: 118 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import * as domain from 'domain';
2-
import * as SentryNode from '@sentry/node';
32
import type { Event, Integration } from '@sentry/types';
43

54
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
6-
import * as Sentry from '../src';
75
import { wrapCloudEventFunction, wrapEventFunction, wrapHttpFunction } from '../src/gcpfunction';
86
import type {
97
CloudEventFunction,
@@ -15,10 +13,65 @@ import type {
1513
Response,
1614
} from '../src/gcpfunction/general';
1715

16+
import { init } from '../src/gcpfunction';
17+
18+
const mockStartInactiveSpan = jest.fn((...spanArgs) => ({ ...spanArgs }));
19+
const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs }));
20+
const mockFlush = jest.fn((...args) => Promise.resolve(args));
21+
const mockWithScope = jest.fn();
22+
const mockCaptureMessage = jest.fn();
23+
const mockCaptureException = jest.fn();
24+
const mockInit = jest.fn();
25+
26+
const mockScope = {
27+
setTag: jest.fn(),
28+
setContext: jest.fn(),
29+
addEventProcessor: jest.fn(),
30+
setSDKProcessingMetadata: jest.fn(),
31+
};
32+
33+
const mockSpan = {
34+
end: jest.fn(),
35+
};
36+
37+
jest.mock('@sentry/node', () => {
38+
const original = jest.requireActual('@sentry/node');
39+
return {
40+
...original,
41+
init: (options: unknown) => {
42+
mockInit(options);
43+
},
44+
startInactiveSpan: (...args: unknown[]) => {
45+
mockStartInactiveSpan(...args);
46+
return mockSpan;
47+
},
48+
startSpanManual: (...args: unknown[]) => {
49+
mockStartSpanManual(...args);
50+
mockSpan.end();
51+
return original.startSpanManual(...args);
52+
},
53+
getCurrentScope: () => {
54+
return mockScope;
55+
},
56+
flush: (...args: unknown[]) => {
57+
return mockFlush(...args);
58+
},
59+
withScope: (fn: (scope: unknown) => void) => {
60+
mockWithScope(fn);
61+
fn(mockScope);
62+
},
63+
captureMessage: (...args: unknown[]) => {
64+
mockCaptureMessage(...args);
65+
},
66+
captureException: (...args: unknown[]) => {
67+
mockCaptureException(...args);
68+
},
69+
};
70+
});
71+
1872
describe('GCPFunction', () => {
19-
afterEach(() => {
20-
// @ts-expect-error see "Why @ts-expect-error" note
21-
SentryNode.resetMocks();
73+
beforeEach(() => {
74+
jest.clearAllMocks();
2275
});
2376

2477
async function handleHttp(fn: HttpFunction, trace_headers: { [key: string]: string } | null = null): Promise<void> {
@@ -89,7 +142,7 @@ describe('GCPFunction', () => {
89142
const wrappedHandler = wrapHttpFunction(handler, { flushTimeout: 1337 });
90143

91144
await handleHttp(wrappedHandler);
92-
expect(SentryNode.flush).toBeCalledWith(1337);
145+
expect(mockFlush).toBeCalledWith(1337);
93146
});
94147
});
95148

@@ -112,12 +165,9 @@ describe('GCPFunction', () => {
112165
metadata: {},
113166
};
114167

115-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
116-
// @ts-expect-error see "Why @ts-expect-error" note
117-
expect(SentryNode.fakeSpan.setHttpStatus).toBeCalledWith(200);
118-
// @ts-expect-error see "Why @ts-expect-error" note
119-
expect(SentryNode.fakeSpan.end).toBeCalled();
120-
expect(SentryNode.flush).toBeCalledWith(2000);
168+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
169+
expect(mockSpan.end).toBeCalled();
170+
expect(mockFlush).toBeCalledWith(2000);
121171
});
122172

123173
test('incoming trace headers are correctly parsed and used', async () => {
@@ -149,7 +199,7 @@ describe('GCPFunction', () => {
149199
},
150200
};
151201

152-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
202+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
153203
});
154204

155205
test('capture error', async () => {
@@ -178,11 +228,10 @@ describe('GCPFunction', () => {
178228
metadata: { dynamicSamplingContext: {} },
179229
};
180230

181-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
182-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
183-
// @ts-expect-error see "Why @ts-expect-error" note
184-
expect(SentryNode.fakeSpan.end).toBeCalled();
185-
expect(SentryNode.flush).toBeCalled();
231+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
232+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
233+
expect(mockSpan.end).toBeCalled();
234+
expect(mockFlush).toBeCalled();
186235
});
187236

188237
test('should not throw when flush rejects', async () => {
@@ -203,7 +252,7 @@ describe('GCPFunction', () => {
203252
const mockEnd = jest.fn();
204253
const response = { end: mockEnd } as unknown as Response;
205254

206-
jest.spyOn(Sentry, 'flush').mockImplementationOnce(async () => {
255+
mockFlush.mockImplementationOnce(async () => {
207256
throw new Error();
208257
});
209258

@@ -216,7 +265,7 @@ describe('GCPFunction', () => {
216265
// integration is included in the defaults and the necessary data is stored in `sdkProcessingMetadata`. The
217266
// integration's tests cover testing that it uses that data correctly.
218267
test('wrapHttpFunction request data prereqs', async () => {
219-
Sentry.GCPFunction.init({});
268+
init({});
220269

221270
const handler: HttpFunction = (_req, res) => {
222271
res.end();
@@ -225,13 +274,12 @@ describe('GCPFunction', () => {
225274

226275
await handleHttp(wrappedHandler);
227276

228-
const initOptions = (SentryNode.init as unknown as jest.SpyInstance).mock.calls[0];
277+
const initOptions = (mockInit as unknown as jest.SpyInstance).mock.calls[0];
229278
const defaultIntegrations = initOptions[0].defaultIntegrations.map((i: Integration) => i.name);
230279

231280
expect(defaultIntegrations).toContain('RequestData');
232281

233-
// @ts-expect-error see "Why @ts-expect-error" note
234-
expect(SentryNode.fakeScope.setSDKProcessingMetadata).toHaveBeenCalledWith({
282+
expect(mockScope.setSDKProcessingMetadata).toHaveBeenCalledWith({
235283
request: {
236284
method: 'POST',
237285
url: '/path?q=query',
@@ -259,10 +307,9 @@ describe('GCPFunction', () => {
259307
},
260308
};
261309

262-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
263-
// @ts-expect-error see "Why @ts-expect-error" note
264-
expect(SentryNode.fakeSpan.end).toBeCalled();
265-
expect(SentryNode.flush).toBeCalledWith(2000);
310+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
311+
expect(mockSpan.end).toBeCalled();
312+
expect(mockFlush).toBeCalledWith(2000);
266313
});
267314

268315
test('capture error', async () => {
@@ -282,11 +329,10 @@ describe('GCPFunction', () => {
282329
},
283330
};
284331

285-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
286-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
287-
// @ts-expect-error see "Why @ts-expect-error" note
288-
expect(SentryNode.fakeSpan.end).toBeCalled();
289-
expect(SentryNode.flush).toBeCalled();
332+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
333+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
334+
expect(mockSpan.end).toBeCalled();
335+
expect(mockFlush).toBeCalled();
290336
});
291337
});
292338

@@ -310,10 +356,9 @@ describe('GCPFunction', () => {
310356
},
311357
};
312358

313-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
314-
// @ts-expect-error see "Why @ts-expect-error" note
315-
expect(SentryNode.fakeSpan.end).toBeCalled();
316-
expect(SentryNode.flush).toBeCalledWith(2000);
359+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
360+
expect(mockSpan.end).toBeCalled();
361+
expect(mockFlush).toBeCalledWith(2000);
317362
});
318363

319364
test('capture error', async () => {
@@ -337,11 +382,10 @@ describe('GCPFunction', () => {
337382
},
338383
};
339384

340-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
341-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
342-
// @ts-expect-error see "Why @ts-expect-error" note
343-
expect(SentryNode.fakeSpan.end).toBeCalled();
344-
expect(SentryNode.flush).toBeCalled();
385+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
386+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
387+
expect(mockSpan.end).toBeCalled();
388+
expect(mockFlush).toBeCalled();
345389
});
346390
});
347391

@@ -362,10 +406,9 @@ describe('GCPFunction', () => {
362406
},
363407
};
364408

365-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
366-
// @ts-expect-error see "Why @ts-expect-error" note
367-
expect(SentryNode.fakeSpan.end).toBeCalled();
368-
expect(SentryNode.flush).toBeCalledWith(2000);
409+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
410+
expect(mockSpan.end).toBeCalled();
411+
expect(mockFlush).toBeCalledWith(2000);
369412
});
370413

371414
test('capture error', async () => {
@@ -385,11 +428,10 @@ describe('GCPFunction', () => {
385428
},
386429
};
387430

388-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
389-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
390-
// @ts-expect-error see "Why @ts-expect-error" note
391-
expect(SentryNode.fakeSpan.end).toBeCalled();
392-
expect(SentryNode.flush).toBeCalled();
431+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
432+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
433+
expect(mockSpan.end).toBeCalled();
434+
expect(mockFlush).toBeCalled();
393435
});
394436

395437
test('capture exception', async () => {
@@ -409,8 +451,8 @@ describe('GCPFunction', () => {
409451
},
410452
};
411453

412-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
413-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
454+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
455+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
414456
});
415457
});
416458

@@ -422,10 +464,9 @@ describe('GCPFunction', () => {
422464
const wrappedHandler = wrapEventFunction(handler);
423465
await expect(handleEvent(wrappedHandler)).rejects.toThrowError(error);
424466

425-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
467+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
426468

427-
// @ts-expect-error just mocking around...
428-
const scopeFunction = SentryNode.captureException.mock.calls[0][1];
469+
const scopeFunction = mockCaptureException.mock.calls[0][1];
429470
const event: Event = { exception: { values: [{}] } };
430471
let evtProcessor: ((e: Event) => Event) | undefined = undefined;
431472
scopeFunction({ addEventProcessor: jest.fn().mockImplementation(proc => (evtProcessor = proc)) });
@@ -442,8 +483,7 @@ describe('GCPFunction', () => {
442483
const handler: EventFunction = (_data, _context) => 42;
443484
const wrappedHandler = wrapEventFunction(handler);
444485
await handleEvent(wrappedHandler);
445-
// @ts-expect-error see "Why @ts-expect-error" note
446-
expect(SentryNode.fakeScope.setContext).toBeCalledWith('gcp.function.context', {
486+
expect(mockScope.setContext).toBeCalledWith('gcp.function.context', {
447487
eventType: 'event.type',
448488
resource: 'some.resource',
449489
});
@@ -466,10 +506,9 @@ describe('GCPFunction', () => {
466506
},
467507
};
468508

469-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
470-
// @ts-expect-error see "Why @ts-expect-error" note
471-
expect(SentryNode.fakeSpan.end).toBeCalled();
472-
expect(SentryNode.flush).toBeCalledWith(2000);
509+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
510+
expect(mockSpan.end).toBeCalled();
511+
expect(mockFlush).toBeCalledWith(2000);
473512
});
474513

475514
test('capture error', async () => {
@@ -489,11 +528,10 @@ describe('GCPFunction', () => {
489528
},
490529
};
491530

492-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
493-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
494-
// @ts-expect-error see "Why @ts-expect-error" note
495-
expect(SentryNode.fakeSpan.end).toBeCalled();
496-
expect(SentryNode.flush).toBeCalled();
531+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
532+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
533+
expect(mockSpan.end).toBeCalled();
534+
expect(mockFlush).toBeCalled();
497535
});
498536
});
499537

@@ -514,10 +552,9 @@ describe('GCPFunction', () => {
514552
},
515553
};
516554

517-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
518-
// @ts-expect-error see "Why @ts-expect-error" note
519-
expect(SentryNode.fakeSpan.end).toBeCalled();
520-
expect(SentryNode.flush).toBeCalledWith(2000);
555+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
556+
expect(mockSpan.end).toBeCalled();
557+
expect(mockFlush).toBeCalledWith(2000);
521558
});
522559

523560
test('capture error', async () => {
@@ -537,11 +574,10 @@ describe('GCPFunction', () => {
537574
},
538575
};
539576

540-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
541-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
542-
// @ts-expect-error see "Why @ts-expect-error" note
543-
expect(SentryNode.fakeSpan.end).toBeCalled();
544-
expect(SentryNode.flush).toBeCalled();
577+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
578+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
579+
expect(mockSpan.end).toBeCalled();
580+
expect(mockFlush).toBeCalled();
545581
});
546582

547583
test('capture exception', async () => {
@@ -561,24 +597,23 @@ describe('GCPFunction', () => {
561597
},
562598
};
563599

564-
expect(SentryNode.startSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
565-
expect(SentryNode.captureException).toBeCalledWith(error, expect.any(Function));
600+
expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function));
601+
expect(mockCaptureException).toBeCalledWith(error, expect.any(Function));
566602
});
567603
});
568604

569605
test('wrapCloudEventFunction scope data', async () => {
570606
const handler: CloudEventFunction = _context => 42;
571607
const wrappedHandler = wrapCloudEventFunction(handler);
572608
await handleCloudEvent(wrappedHandler);
573-
// @ts-expect-error see "Why @ts-expect-error" note
574-
expect(SentryNode.fakeScope.setContext).toBeCalledWith('gcp.function.context', { type: 'event.type' });
609+
expect(mockScope.setContext).toBeCalledWith('gcp.function.context', { type: 'event.type' });
575610
});
576611

577612
describe('init()', () => {
578613
test('calls Sentry.init with correct sdk info metadata', () => {
579-
Sentry.GCPFunction.init({});
614+
init({});
580615

581-
expect(Sentry.init).toBeCalledWith(
616+
expect(mockInit).toBeCalledWith(
582617
expect.objectContaining({
583618
_metadata: {
584619
sdk: {
@@ -587,10 +622,10 @@ describe('GCPFunction', () => {
587622
packages: [
588623
{
589624
name: 'npm:@sentry/serverless',
590-
version: '6.6.6',
625+
version: expect.any(String),
591626
},
592627
],
593-
version: '6.6.6',
628+
version: expect.any(String),
594629
},
595630
},
596631
}),

0 commit comments

Comments
 (0)