Skip to content

Commit 76e92d0

Browse files
committed
test(utils): Switch to using vitest
1 parent 4d61a6d commit 76e92d0

38 files changed

+147
-127
lines changed

packages/utils/jest.config.js

-9
This file was deleted.

packages/utils/package.json

+2-6
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@
4141
"dependencies": {
4242
"@sentry/types": "8.20.0"
4343
},
44-
"devDependencies": {
45-
"@types/array.prototype.flat": "^1.2.1",
46-
"array.prototype.flat": "^1.3.0"
47-
},
4844
"scripts": {
4945
"build": "run-p build:transpile build:types",
5046
"build:dev": "yarn build",
@@ -61,8 +57,8 @@
6157
"clean": "rimraf build coverage cjs esm sentry-utils-*.tgz",
6258
"fix": "eslint . --format stylish --fix",
6359
"lint": "eslint . --format stylish",
64-
"test": "jest",
65-
"test:watch": "jest --watch",
60+
"test": "vitest run",
61+
"test:watch": "vitest --watch",
6662
"version": "node ../../scripts/versionbump.js src/version.ts",
6763
"yalc:publish": "yalc publish --push --sig"
6864
},

packages/utils/src/object.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ export function addNonEnumerableProperty(obj: object, name: string, value: unkno
6565
export function markFunctionWrapped(wrapped: WrappedFunction, original: WrappedFunction): void {
6666
try {
6767
const proto = original.prototype || {};
68-
wrapped.prototype = original.prototype = proto;
68+
wrapped.prototype = proto;
6969
addNonEnumerableProperty(wrapped, '__sentry_original__', original);
70+
original.prototype = proto;
7071
} catch (o_O) {} // eslint-disable-line no-empty
7172
}
7273

packages/utils/test/aggregate-errors.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect } from 'vitest';
2+
13
import type { Event, EventHint, Exception, ExtendedError, StackParser } from '@sentry/types';
24

35
import { applyAggregateErrorsToEvent, createStackParser } from '../src/index';

packages/utils/test/array.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import type { NestedArray } from '../src/array';
24
import { flatten } from '../src/array';
35

packages/utils/test/baggage.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { expect, test } from 'vitest';
2+
13
import { baggageHeaderToDynamicSamplingContext, dynamicSamplingContextToSentryBaggageHeader } from '../src/baggage';
24

35
test.each([

packages/utils/test/browser.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
2+
13
import { JSDOM } from 'jsdom';
24

35
import { getDomElement, htmlTreeAsString } from '../src/browser';

packages/utils/test/buildPolyfills/nullishCoalesce.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { _nullishCoalesce } from '../../src/buildPolyfills';
24
import type { Value } from '../../src/buildPolyfills/types';
35
import { _nullishCoalesce as _nullishCoalesceOrig } from './originals';

packages/utils/test/buildPolyfills/optionalChain.test.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { default as arrayFlat } from 'array.prototype.flat';
1+
import { describe, expect, it } from 'vitest';
22

33
import { _optionalChain } from '../../src/buildPolyfills';
44
import type { GenericFunction, GenericObject, Value } from '../../src/buildPolyfills/types';
55
import { _optionalChain as _optionalChainOrig } from './originals';
66

7-
// Older versions of Node don't have `Array.prototype.flat`, which crashes these tests. On newer versions that do have
8-
// it, this is a no-op.
9-
arrayFlat.shim();
10-
117
type OperationType = 'access' | 'call' | 'optionalAccess' | 'optionalCall';
128
type OperationExecutor =
139
| ((intermediateValue: GenericObject) => Value)

packages/utils/test/clientreport.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import type { ClientReport } from '@sentry/types';
24

35
import { createClientReportEnvelope } from '../src/clientreport';

packages/utils/test/cookie.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2828
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2929
*/
30+
import { describe, expect, it } from 'vitest';
3031

3132
import { parseCookie } from '../src/cookie';
3233

packages/utils/test/dsn.test.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1+
import { beforeEach, describe, expect, test, vi } from 'vitest';
2+
13
import { DEBUG_BUILD } from '../src/debug-build';
24
import { dsnToString, makeDsn } from '../src/dsn';
35
import { logger } from '../src/logger';
46

5-
function testIf(condition: boolean): jest.It {
7+
function testIf(condition: boolean) {
68
return condition ? test : test.skip;
79
}
810

9-
const loggerErrorSpy = jest.spyOn(logger, 'error').mockImplementation(() => {});
10-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
11+
const loggerErrorSpy = vi.spyOn(logger, 'error').mockImplementation(() => {});
12+
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
1113

1214
describe('Dsn', () => {
1315
beforeEach(() => {
14-
jest.clearAllMocks();
16+
vi.clearAllMocks();
1517
});
1618

1719
describe('fromComponents', () => {

packages/utils/test/envelope.test.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { afterEach, describe, expect, it, test, vi } from 'vitest';
2+
13
import type { Event, EventEnvelope, SpanAttributes } from '@sentry/types';
24

35
import {
@@ -108,12 +110,8 @@ describe('envelope', () => {
108110
name: 'with TextEncoder/Decoder polyfill',
109111
before: () => {
110112
GLOBAL_OBJ.__SENTRY__ = {} as InternalGlobal['__SENTRY__'];
111-
GLOBAL_OBJ.__SENTRY__.encodePolyfill = jest.fn<Uint8Array, [string]>((input: string) =>
112-
new TextEncoder().encode(input),
113-
);
114-
GLOBAL_OBJ.__SENTRY__.decodePolyfill = jest.fn<string, [Uint8Array]>((input: Uint8Array) =>
115-
new TextDecoder().decode(input),
116-
);
113+
GLOBAL_OBJ.__SENTRY__.encodePolyfill = vi.fn((input: string) => new TextEncoder().encode(input));
114+
GLOBAL_OBJ.__SENTRY__.decodePolyfill = vi.fn((input: Uint8Array) => new TextDecoder().decode(input));
117115
},
118116
after: () => {
119117
expect(GLOBAL_OBJ.__SENTRY__.encodePolyfill).toHaveBeenCalled();

packages/utils/test/eventbuilder.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it, test } from 'vitest';
2+
13
import type { Client } from '@sentry/types';
24

35
import { createStackParser, eventFromUnknownInput, nodeStackLineParser } from '../src';

packages/utils/test/instrument/fetch.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { parseFetchArgs } from '../../src/instrument/fetch';
24

35
describe('instrument > parseFetchArgs', () => {

packages/utils/test/is.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it, test } from 'vitest';
2+
13
import {
24
isDOMError,
35
isDOMException,

packages/utils/test/lru.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, test } from 'vitest';
2+
13
import { LRUMap } from '../src/lru';
24

35
describe('LRUMap', () => {

packages/utils/test/misc.test.ts

+46-27
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { afterEach, describe, expect, it, test, vi } from 'vitest';
2+
3+
import * as cryptoMod from 'node:crypto';
4+
15
import type { Event, Mechanism, StackFrame } from '@sentry/types';
26

37
import {
@@ -6,9 +10,26 @@ import {
610
arrayify,
711
checkOrSetAlreadyCaught,
812
getEventDescription,
13+
parseSemver,
914
uuid4,
1015
} from '../src/misc';
1116

17+
const NODE_VERSION = parseSemver(process.versions.node);
18+
/**
19+
* Returns`describe` or `describe.skip` depending on allowed major versions of Node.
20+
*
21+
* @param {{ min?: number; max?: number }} allowedVersion
22+
*/
23+
export const conditionalTest = (allowedVersion: { min?: number; max?: number }) => {
24+
if (!NODE_VERSION) {
25+
return test.skip;
26+
}
27+
28+
return NODE_VERSION < (allowedVersion.min || -Infinity) || NODE_VERSION > (allowedVersion.max || Infinity)
29+
? test.skip
30+
: test;
31+
};
32+
1233
describe('getEventDescription()', () => {
1334
test('message event', () => {
1435
expect(
@@ -290,6 +311,10 @@ describe('checkOrSetAlreadyCaught()', () => {
290311
});
291312

292313
describe('uuid4 generation', () => {
314+
afterEach(() => {
315+
vi.unstubAllGlobals();
316+
});
317+
293318
const uuid4Regex = /^[0-9A-F]{12}[4][0-9A-F]{3}[89AB][0-9A-F]{15}$/i;
294319
// Jest messes with the global object, so there is no global crypto object in any node version
295320
// For this reason we need to create our own crypto object for each test to cover all the code paths
@@ -299,45 +324,39 @@ describe('uuid4 generation', () => {
299324
}
300325
});
301326

302-
it('returns valid uuid v4 ids via crypto.getRandomValues', () => {
303-
// eslint-disable-next-line @typescript-eslint/no-var-requires
304-
const cryptoMod = require('crypto');
305-
306-
(global as any).crypto = { getRandomValues: cryptoMod.getRandomValues };
327+
conditionalTest({ min: 17 })('returns valid uuid v4 ids via crypto.getRandomValues', () => {
328+
vi.stubGlobal('crypto', { getRandomValues: (cryptoMod as any).getRandomValues });
307329

308330
for (let index = 0; index < 1_000; index++) {
309331
expect(uuid4()).toMatch(uuid4Regex);
310332
}
311333
});
312334

313335
it('returns valid uuid v4 ids via crypto.randomUUID', () => {
314-
// eslint-disable-next-line @typescript-eslint/no-var-requires
315-
const cryptoMod = require('crypto');
316-
317-
(global as any).crypto = { randomUUID: cryptoMod.randomUUID };
336+
vi.stubGlobal('crypto', { getRandomValues: cryptoMod.randomUUID });
318337

319338
for (let index = 0; index < 1_000; index++) {
320339
expect(uuid4()).toMatch(uuid4Regex);
321340
}
322341
});
323342

324343
it("return valid uuid v4 even if crypto doesn't exists", () => {
325-
(global as any).crypto = { getRandomValues: undefined, randomUUID: undefined };
344+
vi.stubGlobal('crypto', { getRandomValues: undefined, randomUUID: undefined });
326345

327346
for (let index = 0; index < 1_000; index++) {
328347
expect(uuid4()).toMatch(uuid4Regex);
329348
}
330349
});
331350

332351
it('return valid uuid v4 even if crypto invoked causes an error', () => {
333-
(global as any).crypto = {
352+
vi.stubGlobal('crypto', {
334353
getRandomValues: () => {
335354
throw new Error('yo');
336355
},
337356
randomUUID: () => {
338357
throw new Error('yo');
339358
},
340-
};
359+
});
341360

342361
for (let index = 0; index < 1_000; index++) {
343362
expect(uuid4()).toMatch(uuid4Regex);
@@ -346,22 +365,22 @@ describe('uuid4 generation', () => {
346365

347366
// Corner case related to crypto.getRandomValues being only
348367
// semi-implemented (e.g. Chromium 23.0.1235.0 (151422))
349-
it('returns valid uuid v4 even if crypto.getRandomValues does not return a typed array', () => {
350-
// eslint-disable-next-line @typescript-eslint/no-var-requires
351-
const cryptoMod = require('crypto');
352-
353-
const getRandomValues = (typedArray: Uint8Array) => {
354-
if (cryptoMod.getRandomValues) {
355-
cryptoMod.getRandomValues(typedArray);
368+
conditionalTest({ min: 17 })(
369+
'returns valid uuid v4 even if crypto.getRandomValues does not return a typed array',
370+
() => {
371+
const getRandomValues = (typedArray: Uint8Array) => {
372+
if ((cryptoMod as any).getRandomValues) {
373+
(cryptoMod as any).getRandomValues(typedArray);
374+
}
375+
};
376+
377+
vi.stubGlobal('crypto', { getRandomValues });
378+
379+
for (let index = 0; index < 1_000; index++) {
380+
expect(uuid4()).toMatch(uuid4Regex);
356381
}
357-
};
358-
359-
(global as any).crypto = { getRandomValues };
360-
361-
for (let index = 0; index < 1_000; index++) {
362-
expect(uuid4()).toMatch(uuid4Regex);
363-
}
364-
});
382+
},
383+
);
365384
});
366385

367386
describe('arrayify()', () => {

packages/utils/test/normalize-url.test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { describe, expect, it } from 'vitest';
2+
13
import { normalizeUrlToBase } from '../src/normalize';
24

35
describe('normalizeUrlToBase()', () => {

packages/utils/test/normalize.test.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
/**
2-
* @jest-environment jsdom
2+
* @vitest-environment jsdom
33
*/
44

5+
import { describe, expect, test, vi } from 'vitest';
6+
57
import * as isModule from '../src/is';
68
import { normalize } from '../src/normalize';
79
import { addNonEnumerableProperty } from '../src/object';
@@ -49,8 +51,8 @@ describe('normalize()', () => {
4951
});
5052
});
5153

52-
describe('extracts data from `Event` objects', () => {
53-
const isElement = jest.spyOn(isModule, 'isElement').mockReturnValue(true);
54+
test('extracts data from `Event` objects', () => {
55+
const isElement = vi.spyOn(isModule, 'isElement').mockReturnValue(true);
5456
const getAttribute = () => undefined;
5557

5658
const parkElement = { tagName: 'PARK', getAttribute };
@@ -593,7 +595,7 @@ describe('normalize()', () => {
593595

594596
describe('handles serialization errors', () => {
595597
test('restricts effect of error to problematic node', () => {
596-
jest.spyOn(stacktraceModule, 'getFunctionName').mockImplementationOnce(() => {
598+
vi.spyOn(stacktraceModule, 'getFunctionName').mockImplementationOnce(() => {
597599
throw new Error('Nope');
598600
});
599601

0 commit comments

Comments
 (0)