Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 12c5e73

Browse files
timfishAbhiPrasad
andauthoredMar 25, 2025··
test(google-serverless): Migrate to Vitest (#15567)
Co-authored-by: Abhijeet Prasad <[email protected]>
1 parent 00a1018 commit 12c5e73

File tree

13 files changed

+345
-349
lines changed

13 files changed

+345
-349
lines changed
 

‎packages/google-cloud-serverless/jest.config.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎packages/google-cloud-serverless/package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,7 @@
5555
"devDependencies": {
5656
"@google-cloud/bigquery": "^5.3.0",
5757
"@google-cloud/common": "^3.4.1",
58-
"@google-cloud/functions-framework": "^1.7.1",
59-
"@google-cloud/pubsub": "^2.5.0",
6058
"@types/node": "^18.19.1",
61-
"google-gax": "^2.9.0",
6259
"nock": "^13.5.5"
6360
},
6461
"scripts": {
@@ -77,8 +74,8 @@
7774
"clean": "rimraf build coverage sentry-google-cloud-*.tgz",
7875
"fix": "eslint . --format stylish --fix",
7976
"lint": "eslint . --format stylish",
80-
"test": "jest",
81-
"test:watch": "jest --watch",
77+
"test": "vitest run",
78+
"test:watch": "vitest --watch",
8279
"yalc:publish": "yalc publish --push --sig"
8380
},
8481
"volta": {

‎packages/google-cloud-serverless/src/integrations/google-cloud-grpc.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import type { Client, IntegrationFn } from '@sentry/core';
33
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, fill, getClient } from '@sentry/core';
44
import { startInactiveSpan } from '@sentry/node';
55

6-
interface GrpcFunction extends CallableFunction {
6+
export interface GrpcFunction extends CallableFunction {
77
(...args: unknown[]): EventEmitter;
88
}
99

10-
interface GrpcFunctionObject extends GrpcFunction {
10+
export interface GrpcFunctionObject extends GrpcFunction {
1111
requestStream: boolean;
1212
responseStream: boolean;
1313
originalName: string;
@@ -21,7 +21,7 @@ interface CreateStubFunc extends CallableFunction {
2121
(createStub: unknown, options: StubOptions): PromiseLike<Stub>;
2222
}
2323

24-
interface Stub {
24+
export interface Stub {
2525
[key: string]: GrpcFunctionObject;
2626
}
2727

@@ -78,7 +78,7 @@ function wrapCreateStub(origCreate: CreateStubFunc): CreateStubFunc {
7878
}
7979

8080
/** Patches the function in grpc stub to enable tracing */
81-
function fillGrpcFunction(stub: Stub, serviceIdentifier: string, methodName: string): void {
81+
export function fillGrpcFunction(stub: Stub, serviceIdentifier: string, methodName: string): void {
8282
const funcObj = stub[methodName];
8383
if (typeof funcObj !== 'function') {
8484
return;

‎packages/google-cloud-serverless/test/__mocks__/dns.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

‎packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
2+
import { describe, vi, beforeEach, test, expect } from 'vitest';
23

34
import { wrapCloudEventFunction } from '../../src/gcpfunction/cloud_events';
45
import type { CloudEventFunction, CloudEventFunctionWithCallback } from '../../src/gcpfunction/general';
56

6-
const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs }));
7-
const mockFlush = jest.fn((...args) => Promise.resolve(args));
8-
const mockCaptureException = jest.fn();
7+
const mockStartSpanManual = vi.fn((...spanArgs) => ({ ...spanArgs }));
8+
const mockFlush = vi.fn((...args) => Promise.resolve(args));
9+
const mockCaptureException = vi.fn();
910

1011
const mockScope = {
11-
setContext: jest.fn(),
12+
setContext: vi.fn(),
1213
};
1314

1415
const mockSpan = {
15-
end: jest.fn(),
16+
end: vi.fn(),
1617
};
1718

18-
jest.mock('@sentry/node', () => {
19-
const original = jest.requireActual('@sentry/node');
19+
vi.mock('@sentry/node', async () => {
20+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
21+
const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node');
2022
return {
2123
...original,
2224
startSpanManual: (...args: unknown[]) => {
@@ -38,7 +40,7 @@ jest.mock('@sentry/node', () => {
3840

3941
describe('wrapCloudEventFunction', () => {
4042
beforeEach(() => {
41-
jest.clearAllMocks();
43+
vi.clearAllMocks();
4244
});
4345

4446
function handleCloudEvent(fn: CloudEventFunctionWithCallback): Promise<any> {

‎packages/google-cloud-serverless/test/gcpfunction/events.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
2+
import { describe, vi, beforeEach, test, expect } from 'vitest';
23

34
import type { Event } from '@sentry/core';
45
import { wrapEventFunction } from '../../src/gcpfunction/events';
56
import type { EventFunction, EventFunctionWithCallback } from '../../src/gcpfunction/general';
67

7-
const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs }));
8-
const mockFlush = jest.fn((...args) => Promise.resolve(args));
9-
const mockCaptureException = jest.fn();
8+
const mockStartSpanManual = vi.fn((...spanArgs) => ({ ...spanArgs }));
9+
const mockFlush = vi.fn((...args) => Promise.resolve(args));
10+
const mockCaptureException = vi.fn();
1011

1112
const mockScope = {
12-
setContext: jest.fn(),
13+
setContext: vi.fn(),
1314
};
1415

1516
const mockSpan = {
16-
end: jest.fn(),
17+
end: vi.fn(),
1718
};
1819

19-
jest.mock('@sentry/node', () => {
20-
const original = jest.requireActual('@sentry/node');
20+
vi.mock('@sentry/node', async () => {
21+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
22+
const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node');
2123
return {
2224
...original,
2325
startSpanManual: (...args: unknown[]) => {
@@ -39,7 +41,7 @@ jest.mock('@sentry/node', () => {
3941

4042
describe('wrapEventFunction', () => {
4143
beforeEach(() => {
42-
jest.clearAllMocks();
44+
vi.clearAllMocks();
4345
});
4446

4547
function handleEvent(fn: EventFunctionWithCallback): Promise<any> {
@@ -238,7 +240,7 @@ describe('wrapEventFunction', () => {
238240
const scopeFunction = mockCaptureException.mock.calls[0][1];
239241
const event: Event = { exception: { values: [{}] } };
240242
let evtProcessor: ((e: Event) => Event) | undefined = undefined;
241-
scopeFunction({ addEventProcessor: jest.fn().mockImplementation(proc => (evtProcessor = proc)) });
243+
scopeFunction({ addEventProcessor: vi.fn().mockImplementation(proc => (evtProcessor = proc)) });
242244

243245
expect(evtProcessor).toBeInstanceOf(Function);
244246
// @ts-expect-error just mocking around...

‎packages/google-cloud-serverless/test/gcpfunction/http.test.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
import type { Integration } from '@sentry/core';
2-
32
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
3+
import { describe, vi, beforeEach, test, expect, type MockInstance } from 'vitest';
44

55
import { wrapHttpFunction } from '../../src/gcpfunction/http';
6-
76
import type { HttpFunction, Request, Response } from '../../src/gcpfunction/general';
8-
97
import { init } from '../../src/sdk';
108

11-
const mockStartSpanManual = jest.fn((...spanArgs) => ({ ...spanArgs }));
12-
const mockFlush = jest.fn((...args) => Promise.resolve(args));
13-
const mockCaptureException = jest.fn();
14-
const mockInit = jest.fn();
9+
const mockStartSpanManual = vi.fn((...spanArgs) => ({ ...spanArgs }));
10+
const mockFlush = vi.fn((...args) => Promise.resolve(args));
11+
const mockCaptureException = vi.fn();
12+
const mockInit = vi.fn();
1513

1614
const mockScope = {
17-
setSDKProcessingMetadata: jest.fn(),
15+
setSDKProcessingMetadata: vi.fn(),
1816
};
1917

2018
const mockSpan = {
21-
end: jest.fn(),
19+
end: vi.fn(),
2220
};
2321

24-
jest.mock('@sentry/node', () => {
25-
const original = jest.requireActual('@sentry/node');
22+
vi.mock('@sentry/node', async () => {
23+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
24+
const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node');
2625
return {
2726
...original,
2827
init: (options: unknown) => {
@@ -47,7 +46,7 @@ jest.mock('@sentry/node', () => {
4746

4847
describe('GCPFunction', () => {
4948
beforeEach(() => {
50-
jest.clearAllMocks();
49+
vi.clearAllMocks();
5150
});
5251

5352
async function handleHttp(fn: HttpFunction, trace_headers: { [key: string]: string } | null = null): Promise<void> {
@@ -146,7 +145,7 @@ describe('GCPFunction', () => {
146145
body: { foo: 'bar' },
147146
} as Request;
148147

149-
const mockEnd = jest.fn();
148+
const mockEnd = vi.fn();
150149
const response = { end: mockEnd } as unknown as Response;
151150

152151
mockFlush.mockImplementationOnce(async () => {
@@ -171,8 +170,8 @@ describe('GCPFunction', () => {
171170

172171
await handleHttp(wrappedHandler);
173172

174-
const initOptions = (mockInit as unknown as jest.SpyInstance).mock.calls[0];
175-
const defaultIntegrations = initOptions[0]?.defaultIntegrations.map((i: Integration) => i.name);
173+
const initOptions = (mockInit as unknown as MockInstance).mock.calls[0];
174+
const defaultIntegrations = initOptions?.[0]?.defaultIntegrations.map((i: Integration) => i.name);
176175

177176
expect(defaultIntegrations).toContain('RequestData');
178177

Lines changed: 172 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,210 @@
1-
jest.mock('dns');
1+
import { vi, describe, beforeEach, test, expect } from 'vitest';
2+
import { NodeClient } from '@sentry/node';
3+
import { createTransport } from '@sentry/core';
4+
import { setCurrentClient, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
5+
import { googleCloudGrpcIntegration, fillGrpcFunction } from '../../src/integrations/google-cloud-grpc';
6+
import type { GrpcFunctionObject, Stub, GrpcFunction } from '../../src/integrations/google-cloud-grpc';
27

3-
import * as dns from 'dns';
4-
import { EventEmitter } from 'events';
5-
import * as fs from 'fs';
6-
import * as path from 'path';
7-
import { PubSub } from '@google-cloud/pubsub';
8-
import * as http2 from 'http2';
9-
import * as nock from 'nock';
8+
const mockSpanEnd = vi.fn();
9+
const mockStartInactiveSpan = vi.fn();
10+
const mockFill = vi.fn();
1011

11-
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
12-
import { NodeClient, createTransport, setCurrentClient } from '@sentry/node';
13-
import { googleCloudGrpcIntegration } from '../../src/integrations/google-cloud-grpc';
12+
let mockClient: NodeClient;
1413

15-
const spyConnect = jest.spyOn(http2, 'connect');
16-
17-
const mockSpanEnd = jest.fn();
18-
const mockStartInactiveSpan = jest.fn(spanArgs => ({ ...spanArgs }));
14+
vi.mock('@sentry/core', async () => {
15+
const original = await vi.importActual('@sentry/core');
16+
return {
17+
...original,
18+
fill: (obj: any, name: string, replacement: any) => {
19+
mockFill(obj, name, replacement);
20+
obj[name] = replacement(obj[name]);
21+
},
22+
getClient: () => mockClient,
23+
};
24+
});
1925

20-
jest.mock('@sentry/node', () => {
26+
vi.mock('@sentry/node', async () => {
27+
const original = await vi.importActual('@sentry/node');
2128
return {
22-
...jest.requireActual('@sentry/node'),
29+
...original,
2330
startInactiveSpan: (ctx: unknown) => {
2431
mockStartInactiveSpan(ctx);
2532
return { end: mockSpanEnd };
2633
},
2734
};
2835
});
2936

30-
/** Fake HTTP2 stream */
31-
class FakeStream extends EventEmitter {
32-
public rstCode: number = 0;
33-
close() {
34-
this.emit('end');
35-
this.emit('close');
36-
}
37-
end() {}
38-
pause() {}
39-
resume() {}
40-
write(_data: Buffer, cb: CallableFunction) {
41-
process.nextTick(cb, null);
42-
}
43-
}
44-
45-
/** Fake HTTP2 session for GRPC */
46-
class FakeSession extends EventEmitter {
47-
public socket: EventEmitter = new EventEmitter();
48-
public request: jest.Mock = jest.fn();
49-
ping() {}
50-
mockRequest(fn: (stream: FakeStream) => void): FakeStream {
51-
const stream = new FakeStream();
52-
this.request.mockImplementationOnce(() => {
53-
process.nextTick(fn, stream);
54-
return stream;
55-
});
56-
return stream;
57-
}
58-
mockUnaryRequest(responseData: Buffer) {
59-
this.mockRequest(stream => {
60-
stream.emit(
61-
'response',
62-
{ ':status': 200, 'content-type': 'application/grpc', 'content-disposition': 'attachment' },
63-
4,
64-
);
65-
stream.emit('data', responseData);
66-
stream.emit('trailers', { 'grpc-status': '0', 'content-disposition': 'attachment' });
67-
});
68-
}
69-
close() {
70-
this.emit('close');
71-
this.socket.emit('close');
72-
}
73-
ref() {}
74-
unref() {}
37+
// Need to override mock because the integration loads google-gax as a CJS file
38+
async function mock(mockedUri: string, stub: any) {
39+
// @ts-expect-error we are using import on purpose
40+
const { Module } = await import('module');
41+
42+
// @ts-expect-error test
43+
Module._load_original = Module._load;
44+
// @ts-expect-error test
45+
Module._load = (uri, parent) => {
46+
if (uri === mockedUri) return stub;
47+
// @ts-expect-error test
48+
return Module._load_original(uri, parent);
49+
};
7550
}
7651

77-
function mockHttp2Session(): FakeSession {
78-
const session = new FakeSession();
79-
spyConnect.mockImplementationOnce(() => {
80-
process.nextTick(() => session.emit('connect'));
81-
return session as unknown as http2.ClientHttp2Session;
82-
});
83-
return session;
84-
}
52+
vi.hoisted(
53+
() =>
54+
void mock('google-gax', {
55+
GrpcClient: {
56+
prototype: {
57+
createStub: vi.fn(),
58+
},
59+
},
60+
}),
61+
);
8562

8663
describe('GoogleCloudGrpc tracing', () => {
87-
const mockClient = new NodeClient({
88-
tracesSampleRate: 1.0,
89-
integrations: [],
90-
dsn: 'https://withAWSServices@domain/123',
91-
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => Promise.resolve({})),
92-
stackParser: () => [],
93-
});
64+
beforeEach(() => {
65+
mockClient = new NodeClient({
66+
tracesSampleRate: 1.0,
67+
integrations: [],
68+
dsn: 'https://withAWSServices@domain/123',
69+
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => Promise.resolve({})),
70+
stackParser: () => [],
71+
});
9472

95-
const integration = googleCloudGrpcIntegration();
96-
mockClient.addIntegration(integration);
73+
const integration = googleCloudGrpcIntegration();
74+
mockClient.addIntegration(integration);
75+
integration.setup?.(mockClient);
9776

98-
beforeEach(() => {
99-
nock('https://www.googleapis.com').post('/oauth2/v4/token').reply(200, []);
10077
setCurrentClient(mockClient);
10178
mockSpanEnd.mockClear();
10279
mockStartInactiveSpan.mockClear();
80+
mockFill.mockClear();
10381
});
10482

105-
afterAll(() => {
106-
nock.restore();
107-
spyConnect.mockRestore();
108-
});
109-
110-
// We use google cloud pubsub as an example of grpc service for which we can trace requests.
111-
describe('pubsub', () => {
112-
// @ts-expect-error see "Why @ts-expect-error" note
113-
const dnsLookup = dns.lookup as jest.Mock;
114-
// @ts-expect-error see "Why @ts-expect-error" note
115-
const resolveTxt = dns.resolveTxt as jest.Mock;
116-
dnsLookup.mockImplementation((hostname, ...args) => {
117-
expect(hostname).toEqual('pubsub.googleapis.com');
118-
process.nextTick(args[args.length - 1], null, [{ address: '0.0.0.0', family: 4 }]);
119-
});
120-
resolveTxt.mockImplementation((hostname, cb) => {
121-
expect(hostname).toEqual('pubsub.googleapis.com');
122-
process.nextTick(cb, null, []);
83+
describe('setup', () => {
84+
test('integration name is correct', () => {
85+
const integration = googleCloudGrpcIntegration();
86+
expect(integration.name).toBe('GoogleCloudGrpc');
12387
});
12488

125-
const pubsub = new PubSub({
126-
credentials: {
127-
client_email: 'client@email',
128-
private_key: fs.readFileSync(path.resolve(__dirname, 'private.pem')).toString(),
129-
},
130-
projectId: 'project-id',
89+
test('setupOnce patches GrpcClient.createStub', () => {
90+
const mockCreateStub = vi.fn();
91+
const mockGrpcClient = {
92+
prototype: {
93+
createStub: mockCreateStub,
94+
},
95+
};
96+
97+
// eslint-disable-next-line @typescript-eslint/no-var-requires
98+
require('google-gax').GrpcClient = mockGrpcClient;
99+
100+
const integration = googleCloudGrpcIntegration();
101+
integration.setupOnce?.();
102+
expect(mockCreateStub).toBeDefined();
131103
});
132104

133-
afterEach(() => {
134-
dnsLookup.mockReset();
135-
resolveTxt.mockReset();
105+
test('setupOnce throws when google-gax is not available and not optional', () => {
106+
// eslint-disable-next-line @typescript-eslint/no-var-requires
107+
require('google-gax').GrpcClient = undefined;
108+
109+
const integration = googleCloudGrpcIntegration();
110+
expect(() => integration.setupOnce?.()).toThrow();
136111
});
137112

138-
afterAll(async () => {
139-
await pubsub.close();
113+
test('setupOnce does not throw when google-gax is not available and optional', () => {
114+
// eslint-disable-next-line @typescript-eslint/no-var-requires
115+
require('google-gax').GrpcClient = undefined;
116+
117+
const optionalIntegration = googleCloudGrpcIntegration({ optional: true });
118+
expect(() => optionalIntegration.setupOnce?.()).not.toThrow();
140119
});
120+
});
141121

142-
test('publish', async () => {
143-
mockHttp2Session().mockUnaryRequest(Buffer.from('00000000120a1031363337303834313536363233383630', 'hex'));
144-
const resp = await pubsub.topic('nicetopic').publish(Buffer.from('data'));
145-
expect(resp).toEqual('1637084156623860');
146-
expect(mockStartInactiveSpan).toBeCalledWith({
147-
op: 'grpc.pubsub',
122+
describe('fillGrpcFunction', () => {
123+
test('patches unary call methods with tracing', () => {
124+
const mockStub: Stub = {
125+
unaryMethod: Object.assign(vi.fn(), {
126+
requestStream: false,
127+
responseStream: false,
128+
originalName: 'unaryMethod',
129+
} as GrpcFunctionObject),
130+
};
131+
132+
const mockEventEmitter = {
133+
on: vi.fn(),
134+
};
135+
136+
(mockStub.unaryMethod as any).apply = vi.fn().mockReturnValue(mockEventEmitter);
137+
138+
fillGrpcFunction(mockStub, 'test-service', 'unaryMethod');
139+
140+
const result = (mockStub.unaryMethod as GrpcFunction)();
141+
expect(result).toBe(mockEventEmitter);
142+
expect(mockEventEmitter.on).toHaveBeenCalledWith('status', expect.any(Function));
143+
expect(mockStartInactiveSpan).toHaveBeenCalledWith({
144+
name: 'unary call unaryMethod',
145+
onlyIfParent: true,
146+
op: 'grpc.test-service',
148147
attributes: {
149148
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.grpc.serverless',
150149
},
151-
name: 'unary call publish',
152-
onlyIfParent: true,
153150
});
154151
});
152+
153+
test('does not patch non-unary call methods', () => {
154+
const mockStub: Stub = {
155+
clientStreamMethod: Object.assign(vi.fn(), {
156+
requestStream: true,
157+
responseStream: false,
158+
originalName: 'clientStreamMethod',
159+
} as GrpcFunctionObject),
160+
serverStreamMethod: Object.assign(vi.fn(), {
161+
requestStream: false,
162+
responseStream: true,
163+
originalName: 'serverStreamMethod',
164+
} as GrpcFunctionObject),
165+
bidiStreamMethod: Object.assign(vi.fn(), {
166+
requestStream: true,
167+
responseStream: true,
168+
originalName: 'bidiStreamMethod',
169+
} as GrpcFunctionObject),
170+
};
171+
172+
fillGrpcFunction(mockStub, 'test-service', 'clientStreamMethod');
173+
fillGrpcFunction(mockStub, 'test-service', 'serverStreamMethod');
174+
fillGrpcFunction(mockStub, 'test-service', 'bidiStreamMethod');
175+
176+
expect(mockStartInactiveSpan).not.toHaveBeenCalled();
177+
});
178+
179+
test('does not patch non-function properties', () => {
180+
const mockStub: Stub = {
181+
nonFunction: Object.assign(vi.fn(), {
182+
requestStream: false,
183+
responseStream: false,
184+
originalName: 'nonFunction',
185+
} as GrpcFunctionObject),
186+
};
187+
188+
fillGrpcFunction(mockStub, 'test-service', 'nonFunction');
189+
expect(mockStartInactiveSpan).not.toHaveBeenCalled();
190+
});
191+
192+
test('does not patch methods when return value is not an EventEmitter', () => {
193+
const mockStub: Stub = {
194+
unaryMethod: Object.assign(vi.fn(), {
195+
requestStream: false,
196+
responseStream: false,
197+
originalName: 'unaryMethod',
198+
} as GrpcFunctionObject),
199+
};
200+
201+
(mockStub.unaryMethod as any).apply = vi.fn().mockReturnValue({ notAnEventEmitter: true });
202+
203+
fillGrpcFunction(mockStub, 'test-service', 'unaryMethod');
204+
205+
const result = (mockStub.unaryMethod as GrpcFunction)();
206+
expect(result).toEqual({ notAnEventEmitter: true });
207+
expect(mockStartInactiveSpan).not.toHaveBeenCalled();
208+
});
155209
});
156210
});

‎packages/google-cloud-serverless/test/integrations/google-cloud-http.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import * as fs from 'fs';
22
import * as path from 'path';
33
import { BigQuery } from '@google-cloud/bigquery';
4-
import * as nock from 'nock';
4+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
5+
// @ts-ignore ESM/CJS interop issue
6+
import nock from 'nock';
7+
import { describe, vi, beforeEach, test, expect, afterAll } from 'vitest';
58

69
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
710
import { NodeClient, createTransport, setCurrentClient } from '@sentry/node';
811
import { googleCloudHttpIntegration } from '../../src/integrations/google-cloud-http';
912

10-
const mockSpanEnd = jest.fn();
11-
const mockStartInactiveSpan = jest.fn(spanArgs => ({ ...spanArgs }));
13+
const mockSpanEnd = vi.fn();
14+
const mockStartInactiveSpan = vi.fn(spanArgs => ({ ...spanArgs }));
1215

13-
jest.mock('@sentry/node', () => {
16+
vi.mock('@sentry/node', async () => {
17+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
18+
const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node');
1419
return {
15-
...jest.requireActual('@sentry/node'),
20+
...original,
1621
startInactiveSpan: (ctx: unknown) => {
1722
mockStartInactiveSpan(ctx);
1823
return { end: mockSpanEnd };

‎packages/google-cloud-serverless/test/sdk.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import { vi, describe, beforeEach, test, expect } from 'vitest';
2+
13
import { init } from '../src/sdk';
24

3-
const mockInit = jest.fn();
5+
const mockInit = vi.fn();
46

5-
jest.mock('@sentry/node', () => {
6-
const original = jest.requireActual('@sentry/node');
7+
vi.mock('@sentry/node', async () => {
8+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
9+
const original = (await vi.importActual('@sentry/node')) as typeof import('@sentry/node');
710
return {
811
...original,
912
init: (options: unknown) => {
@@ -14,7 +17,7 @@ jest.mock('@sentry/node', () => {
1417

1518
describe('init()', () => {
1619
beforeEach(() => {
17-
jest.clearAllMocks();
20+
vi.clearAllMocks();
1821
});
1922

2023
test('calls Sentry.init with correct sdk info metadata', () => {

‎packages/google-cloud-serverless/tsconfig.test.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"extends": "./tsconfig.json",
33

4-
"include": ["test/**/*"],
4+
"include": ["test/**/*", "vite.config.ts"],
55

66
"compilerOptions": {
77
// should include all types from `./tsconfig.json` plus types for all test frameworks used
8-
"types": ["node", "jest"]
8+
"types": ["node"]
99

1010
// other package-specific, test-specific options
1111
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import baseConfig from '../../vite/vite.config';
2+
3+
export default {
4+
...baseConfig,
5+
test: {
6+
...baseConfig.test,
7+
},
8+
};

‎yarn.lock

Lines changed: 105 additions & 176 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.