Skip to content

Commit 21b0dae

Browse files
authored
test(browser): Switch from jest to vitest (#13092)
Before: `Time: 10.517 s` After: `Duration 3.65s (transform 2.76s, setup 7ms, collect 15.44s, tests 1.36s, environment 4.96s, prepare 3.63s)` We also change the folder structure of the browser unit tests, because we've removed the in-package integration tests. This change also removes `environment: 'jsdom'` from the central config in favour of explicitly adding jsdom environment via the `@vitest-environment` pragma to the specific test file that needs it. This should means that our tests are not polluted with jsdom globals, and that future writers have to explicitly opt-in to the behaviour.
1 parent 6285808 commit 21b0dae

36 files changed

+303
-226
lines changed

packages/browser/jest.config.js

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

packages/browser/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,8 @@
7070
"fix": "eslint . --format stylish --fix",
7171
"lint": "eslint . --format stylish",
7272
"size:check": "cat build/bundles/bundle.min.js | gzip -9 | wc -c | awk '{$1=$1/1024; print \"ES2017: \",$1,\"kB\";}'",
73-
"test": "yarn test:unit",
74-
"test:unit": "jest",
75-
"test:unit:watch": "jest --watch",
73+
"test": "vitest run",
74+
"test:watch": "vitest --watch",
7675
"yalc:publish": "yalc publish --push --sig"
7776
},
7877
"volta": {

packages/browser/test/unit/eventbuilder.test.ts renamed to packages/browser/test/eventbuilder.test.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { defaultStackParser } from '../../src';
2-
import { eventFromUnknownInput } from '../../src/eventbuilder';
1+
/**
2+
* @vitest-environment jsdom
3+
*/
34

4-
jest.mock('@sentry/core', () => {
5-
const original = jest.requireActual('@sentry/core');
5+
import { afterEach, describe, expect, it, vi } from 'vitest';
6+
7+
import { defaultStackParser } from '../src';
8+
import { eventFromUnknownInput } from '../src/eventbuilder';
9+
10+
vi.mock('@sentry/core', async requireActual => {
611
return {
7-
...original,
12+
...((await requireActual()) as any),
813
getClient() {
914
return {
1015
getOptions(): any {
@@ -21,7 +26,7 @@ class MyTestClass {
2126
}
2227

2328
afterEach(() => {
24-
jest.resetAllMocks();
29+
vi.resetAllMocks();
2530
});
2631

2732
describe('eventFromUnknownInput', () => {

packages/browser/test/unit/helper/browser-client-options.ts renamed to packages/browser/test/helper/browser-client-options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createTransport } from '@sentry/core';
22
import { resolvedSyncPromise } from '@sentry/utils';
33

4-
import type { BrowserClientOptions } from '../../../src/client';
4+
import type { BrowserClientOptions } from '../../src/client';
55

66
export function getDefaultBrowserClientOptions(options: Partial<BrowserClientOptions> = {}): BrowserClientOptions {
77
return {

packages/browser/test/unit/index.bundle.feedback.test.ts renamed to packages/browser/test/index.bundle.feedback.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { browserTracingIntegrationShim, replayIntegrationShim } from '@sentry-internal/integration-shims';
2-
import { feedbackAsyncIntegration } from '../../src';
4+
import { feedbackAsyncIntegration } from '../src';
35

4-
import * as FeedbackBundle from '../../src/index.bundle.feedback';
6+
import * as FeedbackBundle from '../src/index.bundle.feedback';
57

68
describe('index.bundle.feedback', () => {
79
it('has correct exports', () => {

packages/browser/test/unit/index.bundle.replay.test.ts renamed to packages/browser/test/index.bundle.replay.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { browserTracingIntegrationShim, feedbackIntegrationShim } from '@sentry-internal/integration-shims';
2-
import { replayIntegration } from '../../src';
4+
import { replayIntegration } from '../src';
35

4-
import * as ReplayBundle from '../../src/index.bundle.replay';
6+
import * as ReplayBundle from '../src/index.bundle.replay';
57

68
describe('index.bundle.replay', () => {
79
it('has correct exports', () => {

packages/browser/test/unit/index.bundle.test.ts renamed to packages/browser/test/index.bundle.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import {
24
browserTracingIntegrationShim,
35
feedbackIntegrationShim,
46
replayIntegrationShim,
57
} from '@sentry-internal/integration-shims';
68

7-
import * as Bundle from '../../src/index.bundle';
9+
import * as Bundle from '../src/index.bundle';
810

911
describe('index.bundle', () => {
1012
it('has correct exports', () => {

packages/browser/test/unit/index.bundle.tracing.replay.feedback.test.ts renamed to packages/browser/test/index.bundle.tracing.replay.feedback.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { browserTracingIntegration, feedbackAsyncIntegration, replayIntegration } from '../../src';
1+
import { describe, expect, it } from 'vitest';
22

3-
import * as TracingReplayFeedbackBundle from '../../src/index.bundle.tracing.replay.feedback';
3+
import { browserTracingIntegration, feedbackAsyncIntegration, replayIntegration } from '../src';
4+
5+
import * as TracingReplayFeedbackBundle from '../src/index.bundle.tracing.replay.feedback';
46

57
describe('index.bundle.tracing.replay.feedback', () => {
68
it('has correct exports', () => {

packages/browser/test/unit/index.bundle.tracing.replay.test.ts renamed to packages/browser/test/index.bundle.tracing.replay.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { feedbackIntegrationShim } from '@sentry-internal/integration-shims';
2-
import { browserTracingIntegration, replayIntegration } from '../../src';
4+
import { browserTracingIntegration, replayIntegration } from '../src';
35

4-
import * as TracingReplayBundle from '../../src/index.bundle.tracing.replay';
6+
import * as TracingReplayBundle from '../src/index.bundle.tracing.replay';
57

68
describe('index.bundle.tracing.replay', () => {
79
it('has correct exports', () => {

packages/browser/test/unit/index.bundle.tracing.test.ts renamed to packages/browser/test/index.bundle.tracing.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { feedbackIntegrationShim, replayIntegrationShim } from '@sentry-internal/integration-shims';
2-
import { browserTracingIntegration } from '../../src';
4+
import { browserTracingIntegration } from '../src';
35

4-
import * as TracingBundle from '../../src/index.bundle.tracing';
6+
import * as TracingBundle from '../src/index.bundle.tracing';
57

68
describe('index.bundle.tracing', () => {
79
it('has correct exports', () => {

packages/browser/test/unit/index.test.ts renamed to packages/browser/test/index.test.ts

Lines changed: 66 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
* @vitest-environment jsdom
3+
*/
4+
5+
import type { Mock } from 'vitest';
6+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7+
18
import {
29
SDK_VERSION,
310
getGlobalScope,
@@ -8,7 +15,7 @@ import {
815
} from '@sentry/core';
916
import * as utils from '@sentry/utils';
1017

11-
import { setCurrentClient } from '../../src';
18+
import { setCurrentClient } from '../src';
1219
import {
1320
BrowserClient,
1421
Scope,
@@ -22,7 +29,7 @@ import {
2229
getCurrentScope,
2330
init,
2431
showReportDialog,
25-
} from '../../src';
32+
} from '../src';
2633
import { getDefaultBrowserClientOptions } from './helper/browser-client-options';
2734
import { makeSimpleTransport } from './mocks/simpletransport';
2835

@@ -31,16 +38,15 @@ const dsn = 'https://[email protected]/4291';
3138
// eslint-disable-next-line no-var
3239
declare var global: any;
3340

34-
jest.mock('@sentry/core', () => {
35-
const original = jest.requireActual('@sentry/core');
41+
vi.mock('@sentry/core', async requireActual => {
3642
return {
37-
...original,
38-
getReportDialogEndpoint: jest.fn(),
43+
...((await requireActual()) as any),
44+
getReportDialogEndpoint: vi.fn(),
3945
};
4046
});
4147

4248
describe('SentryBrowser', () => {
43-
const beforeSend = jest.fn(event => event);
49+
const beforeSend = vi.fn(event => event);
4450

4551
beforeEach(() => {
4652
getGlobalScope().clear();
@@ -84,7 +90,7 @@ describe('SentryBrowser', () => {
8490

8591
describe('showReportDialog', () => {
8692
beforeEach(() => {
87-
(getReportDialogEndpoint as jest.Mock).mockReset();
93+
(getReportDialogEndpoint as Mock).mockReset();
8894
});
8995

9096
describe('user', () => {
@@ -145,14 +151,14 @@ describe('SentryBrowser', () => {
145151
});
146152

147153
describe('onClose', () => {
148-
const dummyErrorHandler = jest.fn();
154+
const dummyErrorHandler = vi.fn();
149155
beforeEach(() => {
150-
// this prevents jest-environment-jsdom from failing the test
156+
// this prevents vi-environment-jsdom from failing the test
151157
// when an error in `onClose` is thrown
152158
// it does not prevent errors thrown directly inside the test,
153159
// so we don't have to worry about tests passing that should
154160
// otherwise fail
155-
// see: https://github.com/jestjs/jest/blob/main/packages/jest-environment-jsdom/src/index.ts#L95-L115
161+
// see: https://github.com/vijs/vi/blob/main/packages/vi-environment-jsdom/src/index.ts#L95-L115
156162
WINDOW.addEventListener('error', dummyErrorHandler);
157163
});
158164

@@ -166,7 +172,7 @@ describe('SentryBrowser', () => {
166172
};
167173

168174
it('should call `onClose` when receiving `__sentry_reportdialog_closed__` MessageEvent', async () => {
169-
const onClose = jest.fn();
175+
const onClose = vi.fn();
170176

171177
showReportDialog({ onClose });
172178

@@ -179,7 +185,7 @@ describe('SentryBrowser', () => {
179185
});
180186

181187
it('should call `onClose` only once even if it throws', async () => {
182-
const onClose = jest.fn(() => {
188+
const onClose = vi.fn(() => {
183189
throw new Error();
184190
});
185191

@@ -194,7 +200,7 @@ describe('SentryBrowser', () => {
194200
});
195201

196202
it('should not call `onClose` for other MessageEvents', async () => {
197-
const onClose = jest.fn();
203+
const onClose = vi.fn();
198204

199205
showReportDialog({ onClose });
200206

@@ -236,49 +242,52 @@ describe('SentryBrowser', () => {
236242
expect(event.exception.values[0]?.stacktrace.frames).not.toHaveLength(0);
237243
});
238244

239-
it('should capture a message', done => {
240-
const options = getDefaultBrowserClientOptions({
241-
beforeSend: event => {
242-
expect(event.message).toBe('test');
243-
expect(event.exception).toBeUndefined();
244-
done();
245-
return event;
246-
},
247-
dsn,
248-
});
249-
setCurrentClient(new BrowserClient(options));
250-
captureMessage('test');
251-
});
252-
253-
it('should capture an event', done => {
254-
const options = getDefaultBrowserClientOptions({
255-
beforeSend: event => {
256-
expect(event.message).toBe('event');
257-
expect(event.exception).toBeUndefined();
258-
done();
259-
return event;
260-
},
261-
dsn,
262-
});
263-
setCurrentClient(new BrowserClient(options));
264-
captureEvent({ message: 'event' });
265-
});
266-
267-
it('should set `platform` on events', done => {
268-
const options = getDefaultBrowserClientOptions({
269-
beforeSend: event => {
270-
expect(event.platform).toBe('javascript');
271-
done();
272-
return event;
273-
},
274-
dsn,
275-
});
276-
setCurrentClient(new BrowserClient(options));
277-
captureEvent({ message: 'event' });
278-
});
245+
it('should capture a message', () =>
246+
new Promise<void>(resolve => {
247+
const options = getDefaultBrowserClientOptions({
248+
beforeSend: event => {
249+
expect(event.message).toBe('test');
250+
expect(event.exception).toBeUndefined();
251+
resolve();
252+
return event;
253+
},
254+
dsn,
255+
});
256+
setCurrentClient(new BrowserClient(options));
257+
captureMessage('test');
258+
}));
259+
260+
it('should capture an event', () =>
261+
new Promise<void>(resolve => {
262+
const options = getDefaultBrowserClientOptions({
263+
beforeSend: event => {
264+
expect(event.message).toBe('event');
265+
expect(event.exception).toBeUndefined();
266+
resolve();
267+
return event;
268+
},
269+
dsn,
270+
});
271+
setCurrentClient(new BrowserClient(options));
272+
captureEvent({ message: 'event' });
273+
}));
274+
275+
it('should set `platform` on events', () =>
276+
new Promise<void>(resolve => {
277+
const options = getDefaultBrowserClientOptions({
278+
beforeSend: event => {
279+
expect(event.platform).toBe('javascript');
280+
resolve();
281+
return event;
282+
},
283+
dsn,
284+
});
285+
setCurrentClient(new BrowserClient(options));
286+
captureEvent({ message: 'event' });
287+
}));
279288

280289
it('should not dedupe an event on bound client', async () => {
281-
const localBeforeSend = jest.fn();
290+
const localBeforeSend = vi.fn();
282291
const options = getDefaultBrowserClientOptions({
283292
beforeSend: localBeforeSend,
284293
dsn,
@@ -295,7 +304,7 @@ describe('SentryBrowser', () => {
295304
});
296305

297306
it('should use inboundfilter rules of bound client', async () => {
298-
const localBeforeSend = jest.fn();
307+
const localBeforeSend = vi.fn();
299308
const options = getDefaultBrowserClientOptions({
300309
beforeSend: localBeforeSend,
301310
dsn,
@@ -374,7 +383,7 @@ describe('SentryBrowser initialization', () => {
374383
});
375384

376385
it('uses SDK source from global for package name', () => {
377-
const spy = jest.spyOn(utils, 'getSDKSource').mockReturnValue('cdn');
386+
const spy = vi.spyOn(utils, 'getSDKSource').mockReturnValue('cdn');
378387
init({ dsn });
379388

380389
const sdkData = getClient()?.getOptions()._metadata?.sdk || {};

packages/browser/test/unit/integrations/breadcrumbs.test.ts renamed to packages/browser/test/integrations/breadcrumbs.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { describe, expect, it, vi } from 'vitest';
2+
13
import * as SentryCore from '@sentry/core';
24

3-
import { BrowserClient, breadcrumbsIntegration, flush } from '../../../src';
5+
import { BrowserClient, breadcrumbsIntegration, flush } from '../../src';
46
import { getDefaultBrowserClientOptions } from '../helper/browser-client-options';
57

68
describe('Breadcrumbs', () => {
@@ -14,7 +16,7 @@ describe('Breadcrumbs', () => {
1416
SentryCore.setCurrentClient(client);
1517
client.init();
1618

17-
const addBreadcrumbSpy = jest.spyOn(SentryCore, 'addBreadcrumb').mockImplementation(() => {});
19+
const addBreadcrumbSpy = vi.spyOn(SentryCore, 'addBreadcrumb').mockImplementation(() => {});
1820

1921
client.captureMessage('test');
2022
await flush(2000);

packages/browser/test/unit/integrations/contextlines.test.ts renamed to packages/browser/test/integrations/contextlines.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import type { StackFrame } from '@sentry/types';
24

3-
import { applySourceContextToFrame } from '../../../src/integrations/contextlines';
5+
import { applySourceContextToFrame } from '../../src/integrations/contextlines';
46

57
const lines = ['line1', 'line2', 'line3', 'line4', 'line5', 'line6', 'line7', 'line8', 'line9'];
68
describe('ContextLines', () => {

0 commit comments

Comments
 (0)