From 38592ec88826ba6ebae291cad6bbe8489e0d8720 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Mon, 24 Feb 2025 16:33:16 +0100 Subject: [PATCH 1/3] test(core): Migrate jest to vitest --- packages/core/package.json | 4 +- packages/core/src/utils-hoist/misc.ts | 3 +- packages/core/test/lib/api.test.ts | 1 + packages/core/test/lib/attachments.test.ts | 3 +- packages/core/test/lib/carrier.test.ts | 1 + packages/core/test/lib/checkin.test.ts | 2 + packages/core/test/lib/client.test.ts | 367 +++++++++--------- packages/core/test/lib/envelope.test.ts | 9 +- packages/core/test/lib/feedback.test.ts | 17 +- packages/core/test/lib/hint.test.ts | 5 +- packages/core/test/lib/integration.test.ts | 59 +-- .../lib/integrations/captureconsole.test.ts | 47 +-- .../core/test/lib/integrations/dedupe.test.ts | 2 + .../lib/integrations/extraerrordata.test.ts | 1 + .../lib/integrations/functiontostring.test.ts | 1 + .../lib/integrations/inboundfilters.test.ts | 1 + .../test/lib/integrations/metadata.test.ts | 74 ++-- .../lib/integrations/rewriteframes.test.ts | 1 + .../third-party-errors-filter.test.ts | 1 + .../test/lib/integrations/zoderrrors.test.ts | 341 ++++++++-------- packages/core/test/lib/metadata.test.ts | 1 + packages/core/test/lib/prepareEvent.test.ts | 15 +- packages/core/test/lib/scope.test.ts | 241 ++++++------ packages/core/test/lib/sdk.test.ts | 21 +- .../test/lib/server-runtime-client.test.ts | 9 +- packages/core/test/lib/session.test.ts | 1 + .../tracing/dynamicSamplingContext.test.ts | 3 +- packages/core/test/lib/tracing/errors.test.ts | 5 +- .../core/test/lib/tracing/idleSpan.test.ts | 111 +++--- .../tracing/sentryNonRecordingSpan.test.ts | 1 + .../core/test/lib/tracing/sentrySpan.test.ts | 17 +- .../core/test/lib/tracing/spanstatus.test.ts | 1 + packages/core/test/lib/tracing/trace.test.ts | 23 +- .../core/test/lib/transports/base.test.ts | 17 +- .../test/lib/transports/multiplexed.test.ts | 5 +- .../core/test/lib/transports/offline.test.ts | 1 + .../lib/utils/applyScopeDataToEvent.test.ts | 1 + packages/core/test/lib/utils/cookie.test.ts | 1 + .../lib/utils/handleCallbackErrors.test.ts | 41 +- .../test/lib/utils/hasTracingEnabled.test.ts | 1 + .../test/lib/utils/isSentryRequestUrl.test.ts | 1 + packages/core/test/lib/utils/merge.test.ts | 2 + packages/core/test/lib/utils/meta.test.ts | 7 +- .../core/test/lib/utils/parameterize.test.ts | 1 + .../test/lib/utils/parseSampleRate.test.ts | 1 + packages/core/test/lib/utils/request.test.ts | 1 + .../core/test/lib/utils/spanUtils.test.ts | 1 + .../core/test/lib/utils/traceData.test.ts | 7 +- .../test/lib/utils/transactionEvent.test.ts | 1 + .../lib/vendor/getClientIpAddress.test.ts | 1 + .../test/utils-hoist/aggregate-errors.test.ts | 1 + .../core/test/utils-hoist/baggage.test.ts | 1 + .../utils-hoist/breadcrumb-log-level.test.ts | 1 + .../core/test/utils-hoist/browser.test.ts | 1 + .../test/utils-hoist/clientreport.test.ts | 1 + packages/core/test/utils-hoist/dsn.test.ts | 9 +- .../core/test/utils-hoist/envelope.test.ts | 5 +- .../test/utils-hoist/eventbuilder.test.ts | 1 + .../core/test/utils-hoist/instrument.test.ts | 1 + .../test/utils-hoist/instrument/fetch.test.ts | 1 + packages/core/test/utils-hoist/is.test.ts | 1 + packages/core/test/utils-hoist/lru.test.ts | 1 + packages/core/test/utils-hoist/misc.test.ts | 11 +- .../test/utils-hoist/normalize-url.test.ts | 1 + .../core/test/utils-hoist/normalize.test.ts | 7 +- packages/core/test/utils-hoist/object.test.ts | 25 +- packages/core/test/utils-hoist/path.test.ts | 1 + .../test/utils-hoist/promisebuffer.test.ts | 7 +- .../core/test/utils-hoist/ratelimit.test.ts | 1 + .../core/test/utils-hoist/severity.test.ts | 1 + .../core/test/utils-hoist/stacktrace.test.ts | 3 +- packages/core/test/utils-hoist/string.test.ts | 1 + .../core/test/utils-hoist/syncpromise.test.ts | 9 +- packages/core/test/utils-hoist/testutils.ts | 5 +- .../core/test/utils-hoist/tracing.test.ts | 1 + .../test/utils-hoist/types/typedef.test.ts | 1 + packages/core/test/utils-hoist/url.test.ts | 1 + .../test/utils-hoist/vercelWaitUntil.test.ts | 3 +- .../core/test/utils-hoist/worldwide.test.ts | 1 + packages/core/tsconfig.test.json | 4 +- packages/core/vite.config.ts | 8 + 81 files changed, 845 insertions(+), 749 deletions(-) create mode 100644 packages/core/vite.config.ts diff --git a/packages/core/package.json b/packages/core/package.json index 12f0a26d24ae..571e1c7867f6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -54,8 +54,8 @@ "clean": "rimraf build coverage sentry-core-*.tgz", "fix": "eslint . --format stylish --fix", "lint": "eslint . --format stylish", - "test": "jest", - "test:watch": "jest --watch", + "test": "vitest run", + "test:watch": "vitest --watch", "yalc:publish": "yalc publish --push --sig" }, "volta": { diff --git a/packages/core/src/utils-hoist/misc.ts b/packages/core/src/utils-hoist/misc.ts index 853e11a09894..660debae219e 100644 --- a/packages/core/src/utils-hoist/misc.ts +++ b/packages/core/src/utils-hoist/misc.ts @@ -13,6 +13,7 @@ interface CryptoInternal { interface CryptoGlobal { msCrypto?: CryptoInternal; crypto?: CryptoInternal; + cryptoTest?: CryptoInternal; } /** @@ -22,7 +23,7 @@ interface CryptoGlobal { */ export function uuid4(): string { const gbl = GLOBAL_OBJ as typeof GLOBAL_OBJ & CryptoGlobal; - const crypto = gbl.crypto || gbl.msCrypto; + const crypto = gbl.cryptoTest|| gbl.crypto || gbl.msCrypto; let getRandomByte = (): number => Math.random() * 16; try { diff --git a/packages/core/test/lib/api.test.ts b/packages/core/test/lib/api.test.ts index 37e67e5a8da1..beca401e4858 100644 --- a/packages/core/test/lib/api.test.ts +++ b/packages/core/test/lib/api.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it, test } from 'vitest'; import { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint } from '../../src/api'; import type { DsnComponents, SdkInfo } from '../../src/types-hoist'; import { makeDsn } from '../../src/utils-hoist/dsn'; diff --git a/packages/core/test/lib/attachments.test.ts b/packages/core/test/lib/attachments.test.ts index 4ddd0acac6c0..78ea620d9226 100644 --- a/packages/core/test/lib/attachments.test.ts +++ b/packages/core/test/lib/attachments.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { createTransport } from '../../src/transports/base'; import { parseEnvelope } from '../../src/utils-hoist/envelope'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; @@ -9,7 +10,7 @@ describe('Attachments', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); test('actually end up in envelope', async () => { diff --git a/packages/core/test/lib/carrier.test.ts b/packages/core/test/lib/carrier.test.ts index 19ebc8117ca4..144355dc1d3b 100644 --- a/packages/core/test/lib/carrier.test.ts +++ b/packages/core/test/lib/carrier.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { getSentryCarrier } from '../../src/carrier'; import { SDK_VERSION } from '../../src/utils-hoist/version'; diff --git a/packages/core/test/lib/checkin.test.ts b/packages/core/test/lib/checkin.test.ts index 14a699ced3e6..a4cdc434ac94 100644 --- a/packages/core/test/lib/checkin.test.ts +++ b/packages/core/test/lib/checkin.test.ts @@ -2,6 +2,8 @@ import type { SerializedCheckIn } from '../../src/types-hoist'; import { createCheckInEnvelope } from '../../src/checkin'; +import { describe, expect, test } from 'vitest'; + describe('createCheckInEnvelope', () => { test('creates a check in envelope header', () => { const envelope = createCheckInEnvelope( diff --git a/packages/core/test/lib/client.test.ts b/packages/core/test/lib/client.test.ts index c415f1ceb411..9f60226c0de7 100644 --- a/packages/core/test/lib/client.test.ts +++ b/packages/core/test/lib/client.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { Scope, SentryError, @@ -27,13 +28,13 @@ const PUBLIC_DSN = 'https://username@domain/123'; // eslint-disable-next-line no-var declare var global: any; -const clientEventFromException = jest.spyOn(TestClient.prototype, 'eventFromException'); -const clientProcess = jest.spyOn(TestClient.prototype as any, '_process'); +const clientEventFromException = vi.spyOn(TestClient.prototype, 'eventFromException'); +const clientProcess = vi.spyOn(TestClient.prototype as any, '_process'); -jest.spyOn(miscModule, 'uuid4').mockImplementation(() => '12312012123120121231201212312012'); -jest.spyOn(loggerModule, 'consoleSandbox').mockImplementation(cb => cb()); -jest.spyOn(stringModule, 'truncate').mockImplementation(str => str); -jest.spyOn(timeModule, 'dateTimestampInSeconds').mockImplementation(() => 2020); +vi.spyOn(miscModule, 'uuid4').mockImplementation(() => '12312012123120121231201212312012'); +vi.spyOn(loggerModule, 'consoleSandbox').mockImplementation(cb => cb()); +vi.spyOn(stringModule, 'truncate').mockImplementation(str => str); +vi.spyOn(timeModule, 'dateTimestampInSeconds').mockImplementation(() => 2020); describe('Client', () => { beforeEach(() => { @@ -46,7 +47,7 @@ describe('Client', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('constructor() / getDsn()', () => { @@ -68,7 +69,7 @@ describe('Client', () => { test('handles being passed an invalid Dsn', () => { // Hide warning logs in the test - jest.spyOn(console, 'error').mockImplementation(() => {}); + vi.spyOn(console, 'error').mockImplementation(() => {}); const options = getDefaultTestClientOptions({ dsn: 'abc' }); const client = new TestClient(options); @@ -80,7 +81,7 @@ describe('Client', () => { describe('constructor() / warnings', () => { test('does not warn for defaults', () => { - const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => undefined); + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); new TestClient(options); @@ -167,7 +168,7 @@ describe('Client', () => { test('it records `buffer_overflow` client discard reason when buffer overflows', () => { const options = getDefaultTestClientOptions({ maxBreadcrumbs: 1 }); const client = new TestClient(options); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); setCurrentClient(client); getIsolationScope().setClient(client); client.init(); @@ -181,7 +182,7 @@ describe('Client', () => { }); test('calls `beforeBreadcrumb` and adds the breadcrumb without any changes', () => { - const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb); + const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb); const options = getDefaultTestClientOptions({ beforeBreadcrumb }); const client = new TestClient(options); setCurrentClient(client); @@ -194,7 +195,7 @@ describe('Client', () => { }); test('calls `beforeBreadcrumb` and uses the new one', () => { - const beforeBreadcrumb = jest.fn(() => ({ message: 'changed' })); + const beforeBreadcrumb = vi.fn(() => ({ message: 'changed' })); const options = getDefaultTestClientOptions({ beforeBreadcrumb }); const client = new TestClient(options); setCurrentClient(client); @@ -207,7 +208,7 @@ describe('Client', () => { }); test('calls `beforeBreadcrumb` and discards the breadcrumb when returned `null`', () => { - const beforeBreadcrumb = jest.fn(() => null); + const beforeBreadcrumb = vi.fn(() => null); const options = getDefaultTestClientOptions({ beforeBreadcrumb }); const client = new TestClient(options); setCurrentClient(client); @@ -220,7 +221,7 @@ describe('Client', () => { }); test('`beforeBreadcrumb` gets an access to a hint as a second argument', () => { - const beforeBreadcrumb = jest.fn((breadcrumb, hint) => ({ ...breadcrumb, data: hint.data })); + const beforeBreadcrumb = vi.fn((breadcrumb, hint) => ({ ...breadcrumb, data: hint.data })); const options = getDefaultTestClientOptions({ beforeBreadcrumb }); const client = new TestClient(options); setCurrentClient(client); @@ -347,7 +348,7 @@ describe('Client', () => { }); test('captures logger message', () => { - const logSpy = jest.spyOn(loggerModule.logger, 'log').mockImplementation(() => undefined); + const logSpy = vi.spyOn(loggerModule.logger, 'log').mockImplementation(() => undefined); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); @@ -392,7 +393,7 @@ describe('Client', () => { test('should call `eventFromException` if input to `captureMessage` is not a primitive', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); - const spy = jest.spyOn(TestClient.instance!, 'eventFromException'); + const spy = vi.spyOn(TestClient.instance!, 'eventFromException'); client.captureMessage('foo'); client.captureMessage(null as any); @@ -439,7 +440,7 @@ describe('Client', () => { }); test('captures logger message', () => { - const logSpy = jest.spyOn(loggerModule.logger, 'log').mockImplementation(() => undefined); + const logSpy = vi.spyOn(loggerModule.logger, 'log').mockImplementation(() => undefined); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); @@ -987,7 +988,7 @@ describe('Client', () => { test('calls `beforeSend` and uses original event without any changes', () => { expect.assertions(2); - const beforeSend = jest.fn(event => event); + const beforeSend = vi.fn(event => event); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); const client = new TestClient(options); @@ -1000,7 +1001,7 @@ describe('Client', () => { test('calls `beforeSendTransaction` and uses original event without any changes', () => { expect.assertions(2); - const beforeSendTransaction = jest.fn(event => event); + const beforeSendTransaction = vi.fn(event => event); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); const client = new TestClient(options); @@ -1013,7 +1014,7 @@ describe('Client', () => { test('calls `beforeSendSpan` and uses original spans without any changes', () => { expect.assertions(3); - const beforeSendSpan = jest.fn(span => span); + const beforeSendSpan = vi.fn(span => span); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendSpan }); const client = new TestClient(options); @@ -1046,7 +1047,7 @@ describe('Client', () => { }); test('does not modify existing contexts for root span in `beforeSendSpan`', () => { - const beforeSendSpan = jest.fn((span: SpanJSON) => { + const beforeSendSpan = vi.fn((span: SpanJSON) => { return { ...span, data: { @@ -1119,7 +1120,7 @@ describe('Client', () => { test('calls `beforeSendTransaction` and uses the modified event', () => { expect.assertions(2); - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { event.transaction = '/adopt/dont/shop'; return event; }); @@ -1133,7 +1134,7 @@ describe('Client', () => { }); test('calls `beforeSendTransaction` and drops spans', () => { - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { event.spans = [{ span_id: 'span5', trace_id: 'trace1', start_timestamp: 1234 }]; return event; }); @@ -1159,7 +1160,7 @@ describe('Client', () => { test('calls `beforeSendSpan` and uses the modified spans', () => { expect.assertions(4); - const beforeSendSpan = jest.fn(span => { + const beforeSendSpan = vi.fn(span => { span.data = { version: 'bravo' }; return span; }); @@ -1201,11 +1202,11 @@ describe('Client', () => { test('calls `beforeSend` and discards the event', () => { expect.assertions(4); - const beforeSend = jest.fn(() => null); + const beforeSend = vi.fn(() => null); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); const client = new TestClient(options); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerWarnSpy = jest.spyOn(loggerModule.logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'log'); client.captureEvent({ message: 'hello' }); @@ -1220,11 +1221,11 @@ describe('Client', () => { test('calls `beforeSendTransaction` and discards the event', () => { expect.assertions(4); - const beforeSendTransaction = jest.fn(() => null); + const beforeSendTransaction = vi.fn(() => null); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); const client = new TestClient(options); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerWarnSpy = jest.spyOn(loggerModule.logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'log'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1237,9 +1238,9 @@ describe('Client', () => { }); test('does not discard span and warn when returning null from `beforeSendSpan', () => { - const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => undefined); + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); - const beforeSendSpan = jest.fn(() => null as unknown as SpanJSON); + const beforeSendSpan = vi.fn(() => null as unknown as SpanJSON); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendSpan }); const client = new TestClient(options); @@ -1282,11 +1283,11 @@ describe('Client', () => { expect.assertions(invalidValues.length * 3); for (const val of invalidValues) { - const beforeSend = jest.fn(() => val); + const beforeSend = vi.fn(() => val); // @ts-expect-error we need to test regular-js behavior const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); const client = new TestClient(options); - const loggerWarnSpy = jest.spyOn(loggerModule.logger, 'warn'); + const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'warn'); client.captureEvent({ message: 'hello' }); @@ -1303,11 +1304,11 @@ describe('Client', () => { expect.assertions(invalidValues.length * 3); for (const val of invalidValues) { - const beforeSendTransaction = jest.fn(() => val); + const beforeSendTransaction = vi.fn(() => val); // @ts-expect-error we need to test regular-js behavior const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); const client = new TestClient(options); - const loggerWarnSpy = jest.spyOn(loggerModule.logger, 'warn'); + const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'warn'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1319,131 +1320,123 @@ describe('Client', () => { } }); - test('calls async `beforeSend` and uses original event without any changes', done => { - jest.useFakeTimers(); - expect.assertions(2); + test('calls async `beforeSend` and uses original event without any changes', () => + new Promise(done => { + vi.useFakeTimers(); + expect.assertions(2); - const beforeSend = jest.fn( - async event => - new Promise(resolve => { - setTimeout(() => { - resolve(event); - }, 1); - }), - ); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); - const client = new TestClient(options); + const beforeSend = vi.fn( + async event => + new Promise(resolve => { + setTimeout(() => { + resolve(event); + }, 1); + }), + ); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); + const client = new TestClient(options); - client.captureEvent({ message: 'hello' }); - jest.runOnlyPendingTimers(); + client.captureEvent({ message: 'hello' }); + vi.runOnlyPendingTimers(); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSend).toHaveBeenCalled(); - expect(event.message).toEqual('hello'); - }; + TestClient.sendEventCalled = (event: Event) => { + expect(beforeSend).toHaveBeenCalled(); + expect(event.message).toEqual('hello'); + done(); + }; - setTimeout(() => { - done(); - }, 5); + vi.runOnlyPendingTimers(); + })); + + test('calls async `beforeSendTransaction` and uses original event without any changes', () => + new Promise(done => { + vi.useFakeTimers(); + expect.assertions(2); + + const beforeSendTransaction = vi.fn( + async event => + new Promise(resolve => { + setTimeout(() => { + resolve(event); + }, 1); + }), + ); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); + const client = new TestClient(options); - jest.runOnlyPendingTimers(); - }); + client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); + vi.runOnlyPendingTimers(); - test('calls async `beforeSendTransaction` and uses original event without any changes', done => { - jest.useFakeTimers(); - expect.assertions(2); + TestClient.sendEventCalled = (event: Event) => { + expect(beforeSendTransaction).toHaveBeenCalled(); + expect(event.transaction).toBe('/dogs/are/great'); + done(); + }; - const beforeSendTransaction = jest.fn( - async event => - new Promise(resolve => { + vi.runOnlyPendingTimers(); + })); + + test('calls async `beforeSend` and uses the modified event', () => + new Promise(done => { + vi.useFakeTimers(); + expect.assertions(2); + + const beforeSend = vi.fn(async event => { + event.message = 'changed2'; + return new Promise(resolve => { setTimeout(() => { resolve(event); }, 1); - }), - ); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); - const client = new TestClient(options); - - client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); - jest.runOnlyPendingTimers(); - - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSendTransaction).toHaveBeenCalled(); - expect(event.transaction).toBe('/dogs/are/great'); - }; - - setTimeout(() => { - done(); - }, 5); - - jest.runOnlyPendingTimers(); - }); - - test('calls async `beforeSend` and uses the modified event', done => { - jest.useFakeTimers(); - expect.assertions(2); - - const beforeSend = jest.fn(async event => { - event.message = 'changed2'; - return new Promise(resolve => { - setTimeout(() => { - resolve(event); - }, 1); + }); }); - }); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); - const client = new TestClient(options); - - client.captureEvent({ message: 'hello' }); - jest.runOnlyPendingTimers(); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); + const client = new TestClient(options); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSend).toHaveBeenCalled(); - expect(event.message).toEqual('changed2'); - }; + client.captureEvent({ message: 'hello' }); + vi.runOnlyPendingTimers(); - setTimeout(() => { - done(); - }, 5); + TestClient.sendEventCalled = (event: Event) => { + expect(beforeSend).toHaveBeenCalled(); + expect(event.message).toEqual('changed2'); + done(); + }; - jest.runOnlyPendingTimers(); - }); + vi.runOnlyPendingTimers(); + })); - test('calls async `beforeSendTransaction` and uses the modified event', done => { - jest.useFakeTimers(); - expect.assertions(2); + test('calls async `beforeSendTransaction` and uses the modified event', () => + new Promise(done => { + vi.useFakeTimers(); + expect.assertions(2); - const beforeSendTransaction = jest.fn(async event => { - event.transaction = '/adopt/dont/shop'; - return new Promise(resolve => { - setTimeout(() => { - resolve(event); - }, 1); + const beforeSendTransaction = vi.fn(async event => { + event.transaction = '/adopt/dont/shop'; + return new Promise(resolve => { + setTimeout(() => { + resolve(event); + }, 1); + }); }); - }); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); - const client = new TestClient(options); - - client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); - jest.runOnlyPendingTimers(); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); + const client = new TestClient(options); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSendTransaction).toHaveBeenCalled(); - expect(event.transaction).toBe('/adopt/dont/shop'); - }; + client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); + vi.runOnlyPendingTimers(); - setTimeout(() => { - done(); - }, 5); + TestClient.sendEventCalled = (event: Event) => { + expect(beforeSendTransaction).toHaveBeenCalled(); + expect(event.transaction).toBe('/adopt/dont/shop'); + done(); + }; - jest.runOnlyPendingTimers(); - }); + vi.runOnlyPendingTimers(); + })); test('calls async `beforeSend` and discards the event', () => { - jest.useFakeTimers(); + vi.useFakeTimers(); expect.assertions(2); - const beforeSend = jest.fn( + const beforeSend = vi.fn( async () => new Promise(resolve => { setTimeout(() => { @@ -1455,17 +1448,17 @@ describe('Client', () => { const client = new TestClient(options); client.captureEvent({ message: 'hello' }); - jest.runAllTimers(); + vi.runAllTimers(); expect(beforeSend).toHaveBeenCalled(); expect(TestClient.instance!.event).toBeUndefined(); }); test('calls async `beforeSendTransaction` and discards the event', () => { - jest.useFakeTimers(); + vi.useFakeTimers(); expect.assertions(2); - const beforeSendTransaction = jest.fn( + const beforeSendTransaction = vi.fn( async () => new Promise(resolve => { setTimeout(() => { @@ -1477,7 +1470,7 @@ describe('Client', () => { const client = new TestClient(options); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); - jest.runAllTimers(); + vi.runAllTimers(); expect(beforeSendTransaction).toHaveBeenCalled(); expect(TestClient.instance!.event).toBeUndefined(); @@ -1486,7 +1479,7 @@ describe('Client', () => { test('`beforeSend` gets access to a hint as a second argument', () => { expect.assertions(3); - const beforeSend = jest.fn((event, hint) => ({ ...event, data: hint.data })); + const beforeSend = vi.fn((event, hint) => ({ ...event, data: hint.data })); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSend }); const client = new TestClient(options); @@ -1500,7 +1493,7 @@ describe('Client', () => { test('`beforeSendTransaction` gets access to a hint as a second argument', () => { expect.assertions(3); - const beforeSendTransaction = jest.fn((event, hint) => ({ ...event, data: hint.data })); + const beforeSendTransaction = vi.fn((event, hint) => ({ ...event, data: hint.data })); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); const client = new TestClient(options); @@ -1520,7 +1513,7 @@ describe('Client', () => { test('`beforeSend` records dropped events', () => { expect.assertions(2); - const beforeSend = jest.fn(() => null); + const beforeSend = vi.fn(() => null); const client = new TestClient( getDefaultTestClientOptions({ dsn: PUBLIC_DSN, @@ -1528,7 +1521,7 @@ describe('Client', () => { }), ); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); client.captureEvent({ message: 'hello' }, {}); @@ -1539,7 +1532,7 @@ describe('Client', () => { test('`beforeSendTransaction` records dropped events', () => { expect.assertions(2); - const beforeSendTransaction = jest.fn(() => null); + const beforeSendTransaction = vi.fn(() => null); const client = new TestClient( getDefaultTestClientOptions({ @@ -1548,7 +1541,7 @@ describe('Client', () => { }), ); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1560,8 +1553,8 @@ describe('Client', () => { expect.assertions(3); const client = new TestClient(getDefaultTestClientOptions({ dsn: PUBLIC_DSN })); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerLogSpy = jest.spyOn(loggerModule.logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerLogSpy = vi.spyOn(loggerModule.logger, 'log'); const scope = new Scope(); scope.addEventProcessor(() => null); @@ -1578,8 +1571,8 @@ describe('Client', () => { expect.assertions(3); const client = new TestClient(getDefaultTestClientOptions({ dsn: PUBLIC_DSN })); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerLogSpy = jest.spyOn(loggerModule.logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerLogSpy = vi.spyOn(loggerModule.logger, 'log'); const scope = new Scope(); scope.addEventProcessor(() => null); @@ -1598,7 +1591,7 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); const scope = new Scope(); scope.addEventProcessor(() => null); @@ -1614,7 +1607,7 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); const scope = new Scope(); scope.addEventProcessor(() => null); @@ -1650,7 +1643,7 @@ describe('Client', () => { }); test('mutating transaction name with `beforeSendTransaction` sets transaction-name-change metadata', () => { - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { event.transaction = '/adopt/dont/shop'; return event; }); @@ -1677,8 +1670,8 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerWarnSpy = jest.spyOn(loggerModule.logger, 'warn'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerWarnSpy = vi.spyOn(loggerModule.logger, 'warn'); const scope = new Scope(); const exception = new Error('sorry'); scope.addEventProcessor(() => { @@ -1707,14 +1700,14 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, sampleRate: 0 }); const client = new TestClient(options); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); client.captureEvent({ message: 'hello' }, {}); expect(recordLostEventSpy).toHaveBeenCalledWith('sample_rate', 'error'); }); test('captures logger message', () => { - const logSpy = jest.spyOn(loggerModule.logger, 'log').mockImplementation(() => undefined); + const logSpy = vi.spyOn(loggerModule.logger, 'log').mockImplementation(() => undefined); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); @@ -1776,7 +1769,7 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] }); const client = new TestClient(options); // note: not the `Client` method `setupIntegrations`, but the free-standing function which that method calls - const setupIntegrationsHelper = jest.spyOn(integrationModule, 'setupIntegrations'); + const setupIntegrationsHelper = vi.spyOn(integrationModule, 'setupIntegrations'); // it should install the first time, because integrations aren't yet installed... client.init(); @@ -1797,7 +1790,7 @@ describe('Client', () => { describe('flush/close', () => { test('flush', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(4); const { makeTransport, getSendCalled, getSentCount, delay } = makeFakeTransport(1); @@ -1822,7 +1815,7 @@ describe('Client', () => { }); test('flush with some events being processed async', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(4); const { makeTransport, getSendCalled, getSentCount, delay } = makeFakeTransport(300); @@ -1835,7 +1828,7 @@ describe('Client', () => { }), ); - const spy = jest.spyOn(TestClient.instance!, 'eventFromMessage'); + const spy = vi.spyOn(TestClient.instance!, 'eventFromMessage'); spy.mockImplementationOnce( (message, level) => new SyncPromise(resolve => { @@ -1857,7 +1850,7 @@ describe('Client', () => { }); test('close', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(4); const { makeTransport, delay, getSentCount } = makeFakeTransport(300); @@ -1881,7 +1874,7 @@ describe('Client', () => { }); test('multiple concurrent flush calls should just work', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(3); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); @@ -1903,11 +1896,11 @@ describe('Client', () => { describe('sendEvent', () => { beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it('emits `afterSendEvent` when sending an error', async () => { @@ -1919,15 +1912,15 @@ describe('Client', () => { ); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send'); + const mockSend = vi.spyOn(client._transport, 'send'); const errorEvent: Event = { message: 'error' }; - const callback = jest.fn(); + const callback = vi.fn(); client.on('afterSendEvent', callback); client.sendEvent(errorEvent); - jest.runAllTimers(); + vi.runAllTimers(); // Wait for two ticks // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang await undefined; @@ -1947,15 +1940,15 @@ describe('Client', () => { ); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send'); + const mockSend = vi.spyOn(client._transport, 'send'); const transactionEvent: Event = { type: 'transaction', event_id: 'tr1' }; - const callback = jest.fn(); + const callback = vi.fn(); client.on('afterSendEvent', callback); client.sendEvent(transactionEvent); - jest.runAllTimers(); + vi.runAllTimers(); // Wait for two ticks // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang await undefined; @@ -1977,17 +1970,17 @@ describe('Client', () => { ); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send').mockImplementation(() => { + const mockSend = vi.spyOn(client._transport, 'send').mockImplementation(() => { return Promise.reject('send error'); }); const errorEvent: Event = { message: 'error' }; - const callback = jest.fn(); + const callback = vi.fn(); client.on('afterSendEvent', callback); client.sendEvent(errorEvent); - jest.runAllTimers(); + vi.runAllTimers(); // Wait for two ticks // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang await undefined; @@ -2009,17 +2002,17 @@ describe('Client', () => { ); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send').mockImplementation(() => { + const mockSend = vi.spyOn(client._transport, 'send').mockImplementation(() => { return Promise.resolve({ statusCode: 200 }); }); const errorEvent: Event = { message: 'error' }; - const callback = jest.fn(); + const callback = vi.fn(); client.on('afterSendEvent', callback); client.sendEvent(errorEvent); - jest.runAllTimers(); + vi.runAllTimers(); // Wait for two ticks // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang await undefined; @@ -2148,7 +2141,7 @@ describe('Client', () => { describe('hook removal with `on`', () => { it('should return a cleanup function that, when executed, unregisters a hook', async () => { - jest.useFakeTimers(); + vi.useFakeTimers(); expect.assertions(8); const client = new TestClient( @@ -2158,19 +2151,19 @@ describe('Client', () => { }), ); - const mockSend = jest.spyOn(client.getTransport()!, 'send').mockImplementation(() => { + const mockSend = vi.spyOn(client.getTransport()!, 'send').mockImplementation(() => { return Promise.resolve({ statusCode: 200 }); }); const errorEvent: Event = { message: 'error' }; - const callback = jest.fn(); + const callback = vi.fn(); const removeAfterSendEventListenerFn = client.on('afterSendEvent', callback); expect(client['_hooks']['afterSendEvent']).toEqual([callback]); client.sendEvent(errorEvent); - jest.runAllTimers(); + vi.runAllTimers(); // Wait for two ticks // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang await undefined; @@ -2185,7 +2178,7 @@ describe('Client', () => { expect(client['_hooks']['afterSendEvent']).toEqual([]); client.sendEvent(errorEvent); - jest.runAllTimers(); + vi.runAllTimers(); // Wait for two ticks // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang await undefined; @@ -2202,7 +2195,7 @@ describe('Client', () => { describe('withMonitor', () => { test('handles successful synchronous operations', () => { const result = 'foo'; - const callback = jest.fn().mockReturnValue(result); + const callback = vi.fn().mockReturnValue(result); const returnedResult = withMonitor('test-monitor', callback); @@ -2212,7 +2205,7 @@ describe('Client', () => { test('handles synchronous errors', () => { const error = new Error('Test error'); - const callback = jest.fn().mockImplementation(() => { + const callback = vi.fn().mockImplementation(() => { throw error; }); @@ -2221,7 +2214,7 @@ describe('Client', () => { test('handles successful asynchronous operations', async () => { const result = 'foo'; - const callback = jest.fn().mockResolvedValue(result); + const callback = vi.fn().mockResolvedValue(result); const promise = withMonitor('test-monitor', callback); await expect(promise).resolves.toEqual(result); @@ -2236,7 +2229,7 @@ describe('Client', () => { // eslint-disable-next-line @sentry-internal/sdk/no-skipped-tests test.skip('handles asynchronous errors', async () => { const error = new Error('Test error'); - const callback = jest.fn().mockRejectedValue(error); + const callback = vi.fn().mockRejectedValue(error); const promise = await withMonitor('test-monitor', callback); await expect(promise).rejects.toThrowError(error); diff --git a/packages/core/test/lib/envelope.test.ts b/packages/core/test/lib/envelope.test.ts index 81e299ada752..5eb45a495b32 100644 --- a/packages/core/test/lib/envelope.test.ts +++ b/packages/core/test/lib/envelope.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import type { Client } from '../../src'; import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, @@ -97,11 +98,11 @@ describe('createSpanEnvelope', () => { client.init(); // We want to avoid console errors in the tests - jest.spyOn(console, 'error').mockImplementation(() => {}); + vi.spyOn(console, 'error').mockImplementation(() => {}); }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); it('creates a span envelope', () => { @@ -192,7 +193,7 @@ describe('createSpanEnvelope', () => { }); it('calls `beforeSendSpan` and uses original span without any changes', () => { - const beforeSendSpan = jest.fn(span => span); + const beforeSendSpan = vi.fn(span => span); const options = getDefaultTestClientOptions({ dsn: 'https://domain/123', beforeSendSpan }); const client = new TestClient(options); @@ -224,7 +225,7 @@ describe('createSpanEnvelope', () => { }); it('calls `beforeSendSpan` and uses the modified span', () => { - const beforeSendSpan = jest.fn(span => { + const beforeSendSpan = vi.fn(span => { span.description = `mutated description: ${span.description}`; return span; }); diff --git a/packages/core/test/lib/feedback.test.ts b/packages/core/test/lib/feedback.test.ts index 717329d0b0e0..e82814437d2b 100644 --- a/packages/core/test/lib/feedback.test.ts +++ b/packages/core/test/lib/feedback.test.ts @@ -1,3 +1,4 @@ +import { beforeEach, describe, expect, it, test, vi } from 'vitest'; import { Scope, addBreadcrumb, @@ -35,7 +36,7 @@ describe('captureFeedback', () => { setCurrentClient(client); client.init(); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); const eventId = captureFeedback({ message: 'test', @@ -90,7 +91,7 @@ describe('captureFeedback', () => { setCurrentClient(client); client.init(); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); const eventId = captureFeedback({ name: 'doe', @@ -155,7 +156,7 @@ describe('captureFeedback', () => { setCurrentClient(client); client.init(); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); const attachment1 = new Uint8Array([1, 2, 3, 4, 5]); const attachment2 = new Uint8Array([6, 7, 8, 9]); @@ -248,7 +249,7 @@ describe('captureFeedback', () => { setCurrentClient(client); client.init(); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); const traceId = '4C79F60C11214EB38604F4AE0781BFB2'; const spanId = 'FA90FDEAD5F74052'; @@ -324,7 +325,7 @@ describe('captureFeedback', () => { setCurrentClient(client); client.init(); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); let span: Span | undefined; const eventId = startSpan({ name: 'test-span' }, _span => { @@ -395,7 +396,7 @@ describe('captureFeedback', () => { setCurrentClient(client); client.init(); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); withIsolationScope(isolationScope => { isolationScope.setTag('test-1', 'tag'); @@ -481,8 +482,8 @@ describe('captureFeedback', () => { const scope = new Scope(); scope.setClient(client2); - const mockTransport = jest.spyOn(client.getTransport()!, 'send'); - const mockTransport2 = jest.spyOn(client2.getTransport()!, 'send'); + const mockTransport = vi.spyOn(client.getTransport()!, 'send'); + const mockTransport2 = vi.spyOn(client2.getTransport()!, 'send'); const eventId = captureFeedback( { diff --git a/packages/core/test/lib/hint.test.ts b/packages/core/test/lib/hint.test.ts index f7fd5ff83ae4..09e1cac8bc2c 100644 --- a/packages/core/test/lib/hint.test.ts +++ b/packages/core/test/lib/hint.test.ts @@ -1,10 +1,11 @@ +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { GLOBAL_OBJ, captureEvent, getCurrentScope } from '../../src'; import { initAndBind } from '../../src/sdk'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; import { AddAttachmentTestIntegration } from '../mocks/integration'; const PUBLIC_DSN = 'https://username@domain/123'; -const sendEvent = jest.spyOn(TestClient.prototype, 'sendEvent'); +const sendEvent = vi.spyOn(TestClient.prototype, 'sendEvent'); describe('Hint', () => { beforeEach(() => { @@ -13,7 +14,7 @@ describe('Hint', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); delete GLOBAL_OBJ.__SENTRY__; }); diff --git a/packages/core/test/lib/integration.test.ts b/packages/core/test/lib/integration.test.ts index aa4be2432699..b495c73b85e4 100644 --- a/packages/core/test/lib/integration.test.ts +++ b/packages/core/test/lib/integration.test.ts @@ -1,6 +1,7 @@ import { getCurrentScope } from '../../src/currentScopes'; import type { Integration, Options } from '../../src/types-hoist'; +import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { addIntegration, getIntegrationsToSetup, installedIntegrations, setupIntegration } from '../../src/integration'; import { setCurrentClient } from '../../src/sdk'; import { logger } from '../../src/utils-hoist/logger'; @@ -293,7 +294,7 @@ describe('setupIntegration', () => { it('works with a minimal integration', () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); + setupOnce = vi.fn(); } const client = getTestClient(); @@ -309,7 +310,7 @@ describe('setupIntegration', () => { it('only calls setupOnce a single time', () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); + setupOnce = vi.fn(); } const client1 = getTestClient(); @@ -336,8 +337,8 @@ describe('setupIntegration', () => { it('calls setup for each client', () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - setup = jest.fn(); + setupOnce = vi.fn(); + setup = vi.fn(); } const client1 = getTestClient(); @@ -374,8 +375,8 @@ describe('setupIntegration', () => { it('binds preprocessEvent for each client', () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - preprocessEvent = jest.fn(); + setupOnce = vi.fn(); + preprocessEvent = vi.fn(); } const client1 = getTestClient(); @@ -426,8 +427,8 @@ describe('setupIntegration', () => { it('allows to mutate events in preprocessEvent', async () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - preprocessEvent = jest.fn(event => { + setupOnce = vi.fn(); + preprocessEvent = vi.fn(event => { event.event_id = 'mutated'; }); } @@ -439,7 +440,7 @@ describe('setupIntegration', () => { setupIntegration(client, integration, integrationIndex); - const sendEvent = jest.fn(); + const sendEvent = vi.fn(); client.sendEvent = sendEvent; client.captureEvent({ event_id: '1a' }); @@ -454,8 +455,8 @@ describe('setupIntegration', () => { it('binds processEvent for each client', () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - processEvent = jest.fn(event => { + setupOnce = vi.fn(); + processEvent = vi.fn(event => { return event; }); } @@ -508,8 +509,8 @@ describe('setupIntegration', () => { it('allows to mutate events in processEvent', async () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - processEvent = jest.fn(_event => { + setupOnce = vi.fn(); + processEvent = vi.fn(_event => { return { event_id: 'mutated' }; }); } @@ -521,7 +522,7 @@ describe('setupIntegration', () => { setupIntegration(client, integration, integrationIndex); - const sendEvent = jest.fn(); + const sendEvent = vi.fn(); client.sendEvent = sendEvent; client.captureEvent({ event_id: '1a' }); @@ -536,8 +537,8 @@ describe('setupIntegration', () => { it('allows to drop events in processEvent', async () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - processEvent = jest.fn(_event => { + setupOnce = vi.fn(); + processEvent = vi.fn(_event => { return null; }); } @@ -549,7 +550,7 @@ describe('setupIntegration', () => { setupIntegration(client, integration, integrationIndex); - const sendEvent = jest.fn(); + const sendEvent = vi.fn(); client.sendEvent = sendEvent; client.captureEvent({ event_id: '1a' }); @@ -566,15 +567,15 @@ describe('addIntegration', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('works with a client setup', () => { - const warnings = jest.spyOn(logger, 'warn'); + const warnings = vi.spyOn(logger, 'warn'); class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); + setupOnce = vi.fn(); } const client = getTestClient(); @@ -588,10 +589,10 @@ describe('addIntegration', () => { }); it('works without a client setup', () => { - const warnings = jest.spyOn(logger, 'warn'); + const warnings = vi.spyOn(logger, 'warn'); class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); + setupOnce = vi.fn(); } getCurrentScope().setClient(undefined); @@ -605,9 +606,9 @@ describe('addIntegration', () => { }); it('triggers all hooks', () => { - const setup = jest.fn(); - const setupOnce = jest.fn(); - const setupAfterAll = jest.fn(); + const setup = vi.fn(); + const setupOnce = vi.fn(); + const setupAfterAll = vi.fn(); class CustomIntegration implements Integration { name = 'test'; @@ -629,13 +630,13 @@ describe('addIntegration', () => { }); it('does not trigger hooks if already installed', () => { - const logs = jest.spyOn(logger, 'log'); + const logs = vi.spyOn(logger, 'log'); class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); - setup = jest.fn(); - afterAllSetup = jest.fn(); + setupOnce = vi.fn(); + setup = vi.fn(); + afterAllSetup = vi.fn(); } const client = getTestClient(); diff --git a/packages/core/test/lib/integrations/captureconsole.test.ts b/packages/core/test/lib/integrations/captureconsole.test.ts index cea4075f4d5e..b64e6bdd4cac 100644 --- a/packages/core/test/lib/integrations/captureconsole.test.ts +++ b/packages/core/test/lib/integrations/captureconsole.test.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/unbound-method */ +import { type Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import type { Client } from '../../../src'; import * as CurrentScopes from '../../../src/currentScopes'; import * as SentryCore from '../../../src/exports'; @@ -10,14 +11,14 @@ import { resetInstrumentationHandlers } from '../../../src/utils-hoist/instrumen import { CONSOLE_LEVELS, originalConsoleMethods } from '../../../src/utils-hoist/logger'; import { GLOBAL_OBJ } from '../../../src/utils-hoist/worldwide'; -const mockConsole: { [key in ConsoleLevel]: jest.Mock } = { - debug: jest.fn(), - log: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - assert: jest.fn(), - info: jest.fn(), - trace: jest.fn(), +const mockConsole: { [key in ConsoleLevel]: Mock } = { + debug: vi.fn(), + log: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + assert: vi.fn(), + info: vi.fn(), + trace: vi.fn(), }; describe('CaptureConsole setup', () => { @@ -28,23 +29,23 @@ describe('CaptureConsole setup', () => { let mockClient: Client; const mockScope = { - setExtra: jest.fn(), - addEventProcessor: jest.fn(), + setExtra: vi.fn(), + addEventProcessor: vi.fn(), }; - const captureMessage = jest.fn(); - const captureException = jest.fn(); - const withScope = jest.fn(callback => { + const captureMessage = vi.fn(); + const captureException = vi.fn(); + const withScope = vi.fn(callback => { return callback(mockScope); }); beforeEach(() => { mockClient = {} as Client; - jest.spyOn(SentryCore, 'captureMessage').mockImplementation(captureMessage); - jest.spyOn(SentryCore, 'captureException').mockImplementation(captureException); - jest.spyOn(CurrentScopes, 'getClient').mockImplementation(() => mockClient); - jest.spyOn(CurrentScopes, 'withScope').mockImplementation(withScope); + vi.spyOn(SentryCore, 'captureMessage').mockImplementation(captureMessage); + vi.spyOn(SentryCore, 'captureException').mockImplementation(captureException); + vi.spyOn(CurrentScopes, 'getClient').mockImplementation(() => mockClient); + vi.spyOn(CurrentScopes, 'withScope').mockImplementation(withScope); CONSOLE_LEVELS.forEach(key => { originalConsoleMethods[key] = mockConsole[key]; @@ -52,7 +53,7 @@ describe('CaptureConsole setup', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); CONSOLE_LEVELS.forEach(key => { originalConsoleMethods[key] = _originalConsoleMethods[key]; @@ -132,7 +133,7 @@ describe('CaptureConsole setup', () => { expect(mockScope.addEventProcessor).toHaveBeenCalledTimes(1); - const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0]; + const addedEventProcessor = (mockScope.addEventProcessor as Mock).mock.calls[0]?.[0]; const someEvent: Event = {}; addedEventProcessor(someEvent); @@ -261,7 +262,7 @@ describe('CaptureConsole setup', () => { it('should call the original console function when console members are called', () => { // Mock console log to test if it was called const originalConsoleLog = GLOBAL_OBJ.console.log; - const mockConsoleLog = jest.fn(); + const mockConsoleLog = vi.fn(); GLOBAL_OBJ.console.log = mockConsoleLog; const captureConsole = captureConsoleIntegration({ levels: ['log'] }); @@ -313,7 +314,7 @@ describe('CaptureConsole setup', () => { const someError = new Error('some error'); GLOBAL_OBJ.console.error(someError); - const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0]; + const addedEventProcessor = (mockScope.addEventProcessor as Mock).mock.calls[0]?.[0]; const someEvent: Event = { exception: { values: [{}], @@ -337,7 +338,7 @@ describe('CaptureConsole setup', () => { const someError = new Error('some error'); GLOBAL_OBJ.console.error(someError); - const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0]; + const addedEventProcessor = (mockScope.addEventProcessor as Mock).mock.calls[0]?.[0]; const someEvent: Event = { exception: { values: [{}], @@ -361,7 +362,7 @@ describe('CaptureConsole setup', () => { const someError = new Error('some error'); GLOBAL_OBJ.console.error(someError); - const addedEventProcessor = (mockScope.addEventProcessor as jest.Mock).mock.calls[0][0]; + const addedEventProcessor = (mockScope.addEventProcessor as Mock).mock.calls[0]?.[0]; const someEvent: Event = { exception: { values: [{}], diff --git a/packages/core/test/lib/integrations/dedupe.test.ts b/packages/core/test/lib/integrations/dedupe.test.ts index 2e7b10fe1c4c..ea42d99ab3e5 100644 --- a/packages/core/test/lib/integrations/dedupe.test.ts +++ b/packages/core/test/lib/integrations/dedupe.test.ts @@ -2,6 +2,8 @@ import type { Event as SentryEvent, Exception, StackFrame, Stacktrace } from '.. import { _shouldDropEvent, dedupeIntegration } from '../../../src/integrations/dedupe'; +import { describe, expect, it } from 'vitest'; + type EventWithException = SentryEvent & { exception: { values: ExceptionWithStacktrace[]; diff --git a/packages/core/test/lib/integrations/extraerrordata.test.ts b/packages/core/test/lib/integrations/extraerrordata.test.ts index c4048f3122b1..33f1f1debe8e 100644 --- a/packages/core/test/lib/integrations/extraerrordata.test.ts +++ b/packages/core/test/lib/integrations/extraerrordata.test.ts @@ -2,6 +2,7 @@ import type { Event as SentryEvent, ExtendedError } from '../../../src/types-hoi import { extraErrorDataIntegration } from '../../../src/integrations/extraerrordata'; +import { beforeEach, describe, expect, it } from 'vitest'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; const extraErrorData = extraErrorDataIntegration(); diff --git a/packages/core/test/lib/integrations/functiontostring.test.ts b/packages/core/test/lib/integrations/functiontostring.test.ts index 37c12e2c2b92..09d03c1893e8 100644 --- a/packages/core/test/lib/integrations/functiontostring.test.ts +++ b/packages/core/test/lib/integrations/functiontostring.test.ts @@ -1,3 +1,4 @@ +import { afterAll, beforeEach, describe, expect, it } from 'vitest'; import { fill, getClient, getCurrentScope, setCurrentClient } from '../../../src'; import { functionToStringIntegration } from '../../../src/integrations/functiontostring'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; diff --git a/packages/core/test/lib/integrations/inboundfilters.test.ts b/packages/core/test/lib/integrations/inboundfilters.test.ts index e06c6bda0da2..d70a17a81bc7 100644 --- a/packages/core/test/lib/integrations/inboundfilters.test.ts +++ b/packages/core/test/lib/integrations/inboundfilters.test.ts @@ -1,5 +1,6 @@ import type { Event, EventProcessor } from '../../../src/types-hoist'; +import { describe, expect, it } from 'vitest'; import type { InboundFiltersOptions } from '../../../src/integrations/inboundfilters'; import { inboundFiltersIntegration } from '../../../src/integrations/inboundfilters'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; diff --git a/packages/core/test/lib/integrations/metadata.test.ts b/packages/core/test/lib/integrations/metadata.test.ts index c93f930ca273..5f685843a640 100644 --- a/packages/core/test/lib/integrations/metadata.test.ts +++ b/packages/core/test/lib/integrations/metadata.test.ts @@ -1,5 +1,6 @@ import type { Event } from '../../../src/types-hoist'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { GLOBAL_OBJ, captureException, @@ -26,49 +27,50 @@ describe('ModuleMetadata integration', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); - test('Adds and removes metadata from stack frames', done => { - const options = getDefaultTestClientOptions({ - dsn: 'https://username@domain/123', - enableSend: true, - stackParser, - integrations: [moduleMetadataIntegration()], - beforeSend: (event, _hint) => { - // copy the frames since reverse in in-place - const lastFrame = [...(event.exception?.values?.[0]?.stacktrace?.frames || [])].reverse()[0]; - // Ensure module_metadata is populated in beforeSend callback - expect(lastFrame?.module_metadata).toEqual({ team: 'frontend' }); - return event; - }, - transport: () => - createTransport({ recordDroppedEvent: () => undefined }, async req => { - const [, items] = parseEnvelope(req.body); + test('Adds and removes metadata from stack frames', () => + new Promise(done => { + const options = getDefaultTestClientOptions({ + dsn: 'https://username@domain/123', + enableSend: true, + stackParser, + integrations: [moduleMetadataIntegration()], + beforeSend: (event, _hint) => { + // copy the frames since reverse in in-place + const lastFrame = [...(event.exception?.values?.[0]?.stacktrace?.frames || [])].reverse()[0]; + // Ensure module_metadata is populated in beforeSend callback + expect(lastFrame?.module_metadata).toEqual({ team: 'frontend' }); + return event; + }, + transport: () => + createTransport({ recordDroppedEvent: () => undefined }, async req => { + const [, items] = parseEnvelope(req.body); - expect(items[0][1]).toBeDefined(); - const event = items[0][1] as Event; - const error = event.exception?.values?.[0]; + expect(items[0][1]).toBeDefined(); + const event = items[0][1] as Event; + const error = event.exception?.values?.[0]; - // Ensure we're looking at the same error we threw - expect(error?.value).toEqual('Some error'); + // Ensure we're looking at the same error we threw + expect(error?.value).toEqual('Some error'); - const lastFrame = [...(error?.stacktrace?.frames || [])].reverse()[0]; - // Ensure the last frame is in fact for this file - expect(lastFrame?.filename).toEqual(__filename); + const lastFrame = [...(error?.stacktrace?.frames || [])].reverse()[0]; + // Ensure the last frame is in fact for this file + expect(lastFrame?.filename).toEqual(__filename); - // Ensure module_metadata has been stripped from the event - expect(lastFrame?.module_metadata).toBeUndefined(); + // Ensure module_metadata has been stripped from the event + expect(lastFrame?.module_metadata).toBeUndefined(); - done(); - return {}; - }), - }); + done(); + return {}; + }), + }); - const client = new TestClient(options); - setCurrentClient(client); - client.init(); + const client = new TestClient(options); + setCurrentClient(client); + client.init(); - captureException(new Error('Some error')); - }); + captureException(new Error('Some error')); + })); }); diff --git a/packages/core/test/lib/integrations/rewriteframes.test.ts b/packages/core/test/lib/integrations/rewriteframes.test.ts index e31976ba5785..250f2bac4dc8 100644 --- a/packages/core/test/lib/integrations/rewriteframes.test.ts +++ b/packages/core/test/lib/integrations/rewriteframes.test.ts @@ -1,5 +1,6 @@ import type { Event, StackFrame } from '../../../src/types-hoist'; +import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { generateIteratee, rewriteFramesIntegration } from '../../../src/integrations/rewriteframes'; let rewriteFrames: ReturnType; diff --git a/packages/core/test/lib/integrations/third-party-errors-filter.test.ts b/packages/core/test/lib/integrations/third-party-errors-filter.test.ts index 9679cfe2b474..dd5dab174fce 100644 --- a/packages/core/test/lib/integrations/third-party-errors-filter.test.ts +++ b/packages/core/test/lib/integrations/third-party-errors-filter.test.ts @@ -1,3 +1,4 @@ +import { beforeEach, describe, expect, it } from 'vitest'; import type { Client } from '../../../src/client'; import { thirdPartyErrorFilterIntegration } from '../../../src/integrations/third-party-errors-filter'; import { addMetadataToStackFrames } from '../../../src/metadata'; diff --git a/packages/core/test/lib/integrations/zoderrrors.test.ts b/packages/core/test/lib/integrations/zoderrrors.test.ts index cd80e2347f36..b29bb09845e8 100644 --- a/packages/core/test/lib/integrations/zoderrrors.test.ts +++ b/packages/core/test/lib/integrations/zoderrrors.test.ts @@ -1,6 +1,7 @@ import { z } from 'zod'; import type { Event, EventHint } from '../../../src/types-hoist'; +import { describe, expect, it, test } from 'vitest'; import { applyZodErrorsToEvent, flattenIssue, @@ -168,27 +169,27 @@ describe('applyZodErrorsToEvent()', () => { } expect(attachment.filename).toBe('zod_issues.json'); expect(JSON.parse(attachment.data.toString())).toMatchInlineSnapshot(` -Object { - "issues": Array [ - Object { - "code": "invalid_type", - "expected": "string", - "keys": "[\\"extra\\"]", - "message": "Invalid input: expected string, received number", - "path": "names.1", - "received": "number", - }, - Object { - "code": "invalid_type", - "expected": "string", - "keys": "[\\"extra2\\"]", - "message": "Invalid input: expected string, received number", - "path": "foo.1", - "received": "number", - }, - ], -} -`); + { + "issues": [ + { + "code": "invalid_type", + "expected": "string", + "keys": "["extra"]", + "message": "Invalid input: expected string, received number", + "path": "names.1", + "received": "number", + }, + { + "code": "invalid_type", + "expected": "string", + "keys": "["extra2"]", + "message": "Invalid input: expected string, received number", + "path": "foo.1", + "received": "number", + }, + ], + } + `); }); }); @@ -213,91 +214,91 @@ describe('flattenIssue()', () => { // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "too_small", - "exact": false, - "inclusive": true, - "message": "String must contain at least 1 character(s)", - "minimum": 1, - "path": Array [ - "foo", - ], - "type": "string", - }, - Object { - "code": "invalid_literal", - "expected": "baz", - "message": "Invalid literal value, expected \\"baz\\"", - "path": Array [ - "nested", - "bar", - ], - "received": "not-baz", - }, -] -`); + [ + { + "code": "too_small", + "exact": false, + "inclusive": true, + "message": "String must contain at least 1 character(s)", + "minimum": 1, + "path": [ + "foo", + ], + "type": "string", + }, + { + "code": "invalid_literal", + "expected": "baz", + "message": "Invalid literal value, expected "baz"", + "path": [ + "nested", + "bar", + ], + "received": "not-baz", + }, + ] + `); const issues = zodError.issues; expect(issues.length).toBe(2); // Format it for use in Sentry expect(issues.map(flattenIssue)).toMatchInlineSnapshot(` -Array [ - Object { - "code": "too_small", - "exact": false, - "inclusive": true, - "keys": undefined, - "message": "String must contain at least 1 character(s)", - "minimum": 1, - "path": "foo", - "type": "string", - "unionErrors": undefined, - }, - Object { - "code": "invalid_literal", - "expected": "baz", - "keys": undefined, - "message": "Invalid literal value, expected \\"baz\\"", - "path": "nested.bar", - "received": "not-baz", - "unionErrors": undefined, - }, -] -`); + [ + { + "code": "too_small", + "exact": false, + "inclusive": true, + "keys": undefined, + "message": "String must contain at least 1 character(s)", + "minimum": 1, + "path": "foo", + "type": "string", + "unionErrors": undefined, + }, + { + "code": "invalid_literal", + "expected": "baz", + "keys": undefined, + "message": "Invalid literal value, expected "baz"", + "path": "nested.bar", + "received": "not-baz", + "unionErrors": undefined, + }, + ] + `); expect(zodError.flatten(flattenIssue)).toMatchInlineSnapshot(` -Object { - "fieldErrors": Object { - "foo": Array [ - Object { - "code": "too_small", - "exact": false, - "inclusive": true, - "keys": undefined, - "message": "String must contain at least 1 character(s)", - "minimum": 1, - "path": "foo", - "type": "string", - "unionErrors": undefined, - }, - ], - "nested": Array [ - Object { - "code": "invalid_literal", - "expected": "baz", - "keys": undefined, - "message": "Invalid literal value, expected \\"baz\\"", - "path": "nested.bar", - "received": "not-baz", - "unionErrors": undefined, - }, - ], - }, - "formErrors": Array [], -} -`); + { + "fieldErrors": { + "foo": [ + { + "code": "too_small", + "exact": false, + "inclusive": true, + "keys": undefined, + "message": "String must contain at least 1 character(s)", + "minimum": 1, + "path": "foo", + "type": "string", + "unionErrors": undefined, + }, + ], + "nested": [ + { + "code": "invalid_literal", + "expected": "baz", + "keys": undefined, + "message": "Invalid literal value, expected "baz"", + "path": "nested.bar", + "received": "not-baz", + "unionErrors": undefined, + }, + ], + }, + "formErrors": [], + } + `); }); it('flattens keys field to string', () => { @@ -317,18 +318,18 @@ Object { // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "unrecognized_keys", - "keys": Array [ - "extra_key_abc", - "extra_key_def", - ], - "message": "Unrecognized key(s) in object: 'extra_key_abc', 'extra_key_def'", - "path": Array [], - }, -] -`); + [ + { + "code": "unrecognized_keys", + "keys": [ + "extra_key_abc", + "extra_key_def", + ], + "message": "Unrecognized key(s) in object: 'extra_key_abc', 'extra_key_def'", + "path": [], + }, + ] + `); const issues = zodError.issues; expect(issues.length).toBe(1); @@ -344,14 +345,14 @@ Array [ // Note: path is an empty string because the issue is at the root. // TODO: Maybe somehow make it clearer that this is at the root? expect(formattedIssue).toMatchInlineSnapshot(` -Object { - "code": "unrecognized_keys", - "keys": "[\\"extra_key_abc\\",\\"extra_key_def\\"]", - "message": "Unrecognized key(s) in object: 'extra_key_abc', 'extra_key_def'", - "path": "", - "unionErrors": undefined, -} -`); + { + "code": "unrecognized_keys", + "keys": "["extra_key_abc","extra_key_def"]", + "message": "Unrecognized key(s) in object: 'extra_key_abc', 'extra_key_def'", + "path": "", + "unionErrors": undefined, + } + `); expect(typeof formattedIssue.keys === 'string').toBe(true); }); }); @@ -406,16 +407,16 @@ describe('formatIssueMessage()', () => { // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "invalid_type", - "expected": "object", - "message": "Expected object, received number", - "path": Array [], - "received": "number", - }, -] -`); + [ + { + "code": "invalid_type", + "expected": "object", + "message": "Expected object, received number", + "path": [], + "received": "number", + }, + ] + `); const message = formatIssueMessage(zodError); expect(message).toMatchInlineSnapshot('"Failed to validate object"'); @@ -429,16 +430,16 @@ Array [ // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "invalid_type", - "expected": "number", - "message": "Expected number, received string", - "path": Array [], - "received": "string", - }, -] -`); + [ + { + "code": "invalid_type", + "expected": "number", + "message": "Expected number, received string", + "path": [], + "received": "string", + }, + ] + `); const message = formatIssueMessage(zodError); expect(message).toMatchInlineSnapshot('"Failed to validate number"'); @@ -452,16 +453,16 @@ Array [ // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "invalid_type", - "expected": "string", - "message": "Expected string, received number", - "path": Array [], - "received": "number", - }, -] -`); + [ + { + "code": "invalid_type", + "expected": "string", + "message": "Expected string, received number", + "path": [], + "received": "number", + }, + ] + `); const message = formatIssueMessage(zodError); expect(message).toMatchInlineSnapshot('"Failed to validate string"'); @@ -475,16 +476,16 @@ Array [ // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "invalid_type", - "expected": "array", - "message": "Expected array, received string", - "path": Array [], - "received": "string", - }, -] -`); + [ + { + "code": "invalid_type", + "expected": "array", + "message": "Expected array, received string", + "path": [], + "received": "string", + }, + ] + `); const message = formatIssueMessage(zodError); expect(message).toMatchInlineSnapshot('"Failed to validate array"'); @@ -498,18 +499,18 @@ Array [ // Original zod error expect(zodError.issues).toMatchInlineSnapshot(` -Array [ - Object { - "code": "invalid_type", - "expected": "string", - "message": "Expected string, received number", - "path": Array [ - 0, - ], - "received": "number", - }, -] -`); + [ + { + "code": "invalid_type", + "expected": "string", + "message": "Expected string, received number", + "path": [ + 0, + ], + "received": "number", + }, + ] + `); const message = formatIssueMessage(zodError); expect(message).toMatchInlineSnapshot('"Failed to validate keys: "'); diff --git a/packages/core/test/lib/metadata.test.ts b/packages/core/test/lib/metadata.test.ts index 7dbbe8a0ea1b..7e402bbee0b1 100644 --- a/packages/core/test/lib/metadata.test.ts +++ b/packages/core/test/lib/metadata.test.ts @@ -1,5 +1,6 @@ import type { Event } from '../../src/types-hoist'; +import { beforeEach, describe, expect, it } from 'vitest'; import { addMetadataToStackFrames, getMetadataForUrl, stripMetadataFromStackFrames } from '../../src/metadata'; import { nodeStackLineParser } from '../../src/utils-hoist/node-stack-trace'; import { createStackParser } from '../../src/utils-hoist/stacktrace'; diff --git a/packages/core/test/lib/prepareEvent.test.ts b/packages/core/test/lib/prepareEvent.test.ts index 9806bd06bd14..2e7f5880413d 100644 --- a/packages/core/test/lib/prepareEvent.test.ts +++ b/packages/core/test/lib/prepareEvent.test.ts @@ -2,6 +2,7 @@ import type { Client, ScopeContext } from '../../src'; import { GLOBAL_OBJ, createStackParser, getGlobalScope, getIsolationScope } from '../../src'; import type { Attachment, Breadcrumb, ClientOptions, Event, EventHint, EventProcessor } from '../../src/types-hoist'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { Scope } from '../../src/scope'; import { applyClientOptions, @@ -270,7 +271,7 @@ describe('prepareEvent', () => { }); it('works without any scope data', async () => { - const eventProcessor = jest.fn((a: unknown) => a) as EventProcessor; + const eventProcessor = vi.fn((a: unknown) => a) as EventProcessor; const scope = new Scope(); @@ -315,9 +316,9 @@ describe('prepareEvent', () => { const breadcrumb3 = { message: '3', timestamp: 123 } as Breadcrumb; const breadcrumb4 = { message: '4', timestamp: 123 } as Breadcrumb; - const eventProcessor1 = jest.fn((a: unknown) => a) as EventProcessor; - const eventProcessor2 = jest.fn((b: unknown) => b) as EventProcessor; - const eventProcessor3 = jest.fn((b: unknown) => b) as EventProcessor; + const eventProcessor1 = vi.fn((a: unknown) => a) as EventProcessor; + const eventProcessor2 = vi.fn((b: unknown) => b) as EventProcessor; + const eventProcessor3 = vi.fn((b: unknown) => b) as EventProcessor; const attachment1 = { filename: '1' } as Attachment; const attachment2 = { filename: '2' } as Attachment; @@ -399,8 +400,8 @@ describe('prepareEvent', () => { const breadcrumb2 = { message: '2', timestamp: 222 } as Breadcrumb; const breadcrumb3 = { message: '3', timestamp: 333 } as Breadcrumb; - const eventProcessor1 = jest.fn((a: unknown) => a) as EventProcessor; - const eventProcessor2 = jest.fn((a: unknown) => a) as EventProcessor; + const eventProcessor1 = vi.fn((a: unknown) => a) as EventProcessor; + const eventProcessor2 = vi.fn((a: unknown) => a) as EventProcessor; const attachmentGlobal = { filename: 'global scope attachment' } as Attachment; const attachmentIsolation = { filename: 'isolation scope attachment' } as Attachment; @@ -563,7 +564,7 @@ describe('prepareEvent', () => { const captureContextScope = new Scope(); captureContextScope.setTags({ foo: 'bar' }); - const captureContext = jest.fn(passedScope => { + const captureContext = vi.fn(passedScope => { expect(passedScope).toEqual(scope); return captureContextScope; }); diff --git a/packages/core/test/lib/scope.test.ts b/packages/core/test/lib/scope.test.ts index 026d33fd54e5..4b27eff42824 100644 --- a/packages/core/test/lib/scope.test.ts +++ b/packages/core/test/lib/scope.test.ts @@ -1,3 +1,4 @@ +import { beforeEach, describe, expect, it, test, vi } from 'vitest'; import type { Client } from '../../src'; import { applyScopeDataToEvent, @@ -338,7 +339,7 @@ describe('Scope', () => { }); test('given callback function, pass it the scope and returns original or modified scope', () => { - const cb = jest + const cb = vi .fn() .mockImplementationOnce(v => v) .mockImplementationOnce(v => { @@ -356,7 +357,7 @@ describe('Scope', () => { }); test('given callback function, when it doesnt return instanceof Scope, ignore it and return original scope', () => { - const cb = jest.fn().mockImplementationOnce(_v => 'wat'); + const cb = vi.fn().mockImplementationOnce(_v => 'wat'); const updatedScope = scope.update(cb); expect(cb).toHaveBeenCalledWith(scope); expect(updatedScope).toEqual(scope); @@ -557,7 +558,7 @@ describe('Scope', () => { describe('.captureException()', () => { it('should call captureException() on client with newly generated event ID if not explicitly passed in', () => { - const fakeCaptureException = jest.fn(() => 'mock-event-id'); + const fakeCaptureException = vi.fn(() => 'mock-event-id'); const fakeClient = { captureException: fakeCaptureException, } as unknown as Client; @@ -586,7 +587,7 @@ describe('Scope', () => { }); it('should pass exception to captureException() on client', () => { - const fakeCaptureException = jest.fn(() => 'mock-event-id'); + const fakeCaptureException = vi.fn(() => 'mock-event-id'); const fakeClient = { captureException: fakeCaptureException, } as unknown as Client; @@ -601,7 +602,7 @@ describe('Scope', () => { }); it('should call captureException() on client with a synthetic exception', () => { - const fakeCaptureException = jest.fn(() => 'mock-event-id'); + const fakeCaptureException = vi.fn(() => 'mock-event-id'); const fakeClient = { captureException: fakeCaptureException, } as unknown as Client; @@ -618,7 +619,7 @@ describe('Scope', () => { }); it('should pass the original exception to captureException() on client', () => { - const fakeCaptureException = jest.fn(() => 'mock-event-id'); + const fakeCaptureException = vi.fn(() => 'mock-event-id'); const fakeClient = { captureException: fakeCaptureException, } as unknown as Client; @@ -636,7 +637,7 @@ describe('Scope', () => { }); it('should forward hint to captureException() on client', () => { - const fakeCaptureException = jest.fn(() => 'mock-event-id'); + const fakeCaptureException = vi.fn(() => 'mock-event-id'); const fakeClient = { captureException: fakeCaptureException, } as unknown as Client; @@ -655,7 +656,7 @@ describe('Scope', () => { describe('.captureMessage()', () => { it('should call captureMessage() on client with newly generated event ID if not explicitly passed in', () => { - const fakeCaptureMessage = jest.fn(() => 'mock-event-id'); + const fakeCaptureMessage = vi.fn(() => 'mock-event-id'); const fakeClient = { captureMessage: fakeCaptureMessage, } as unknown as Client; @@ -681,7 +682,7 @@ describe('Scope', () => { }); it('should pass exception to captureMessage() on client', () => { - const fakeCaptureMessage = jest.fn(() => 'mock-event-id'); + const fakeCaptureMessage = vi.fn(() => 'mock-event-id'); const fakeClient = { captureMessage: fakeCaptureMessage, } as unknown as Client; @@ -694,7 +695,7 @@ describe('Scope', () => { }); it('should call captureMessage() on client with a synthetic exception', () => { - const fakeCaptureMessage = jest.fn(() => 'mock-event-id'); + const fakeCaptureMessage = vi.fn(() => 'mock-event-id'); const fakeClient = { captureMessage: fakeCaptureMessage, } as unknown as Client; @@ -712,7 +713,7 @@ describe('Scope', () => { }); it('should pass the original exception to captureMessage() on client', () => { - const fakeCaptureMessage = jest.fn(() => 'mock-event-id'); + const fakeCaptureMessage = vi.fn(() => 'mock-event-id'); const fakeClient = { captureMessage: fakeCaptureMessage, } as unknown as Client; @@ -730,7 +731,7 @@ describe('Scope', () => { }); it('should forward level and hint to captureMessage() on client', () => { - const fakeCaptureMessage = jest.fn(() => 'mock-event-id'); + const fakeCaptureMessage = vi.fn(() => 'mock-event-id'); const fakeClient = { captureMessage: fakeCaptureMessage, } as unknown as Client; @@ -750,7 +751,7 @@ describe('Scope', () => { describe('.captureEvent()', () => { it('should call captureEvent() on client with newly generated event ID if not explicitly passed in', () => { - const fakeCaptureEvent = jest.fn(() => 'mock-event-id'); + const fakeCaptureEvent = vi.fn(() => 'mock-event-id'); const fakeClient = { captureEvent: fakeCaptureEvent, } as unknown as Client; @@ -775,7 +776,7 @@ describe('Scope', () => { }); it('should pass event to captureEvent() on client', () => { - const fakeCaptureEvent = jest.fn(() => 'mock-event-id'); + const fakeCaptureEvent = vi.fn(() => 'mock-event-id'); const fakeClient = { captureEvent: fakeCaptureEvent, } as unknown as Client; @@ -790,7 +791,7 @@ describe('Scope', () => { }); it('should forward hint to captureEvent() on client', () => { - const fakeCaptureEvent = jest.fn(() => 'mock-event-id'); + const fakeCaptureEvent = vi.fn(() => 'mock-event-id'); const fakeClient = { captureEvent: fakeCaptureEvent, } as unknown as Client; @@ -847,67 +848,73 @@ describe('withScope()', () => { getGlobalScope().clear(); }); - it('will make the passed scope the active scope within the callback', done => { - withScope(scope => { - expect(getCurrentScope()).toBe(scope); - done(); - }); - }); - - it('will pass a scope that is different from the current active isolation scope', done => { - withScope(scope => { - expect(getIsolationScope()).not.toBe(scope); - done(); - }); - }); - - it('will always make the inner most passed scope the current isolation scope when nesting calls', done => { - withIsolationScope(_scope1 => { - withIsolationScope(scope2 => { - expect(getIsolationScope()).toBe(scope2); + it('will make the passed scope the active scope within the callback', () => + new Promise(done => { + withScope(scope => { + expect(getCurrentScope()).toBe(scope); done(); }); - }); - }); - - it('forks the scope when not passing any scope', done => { - const initialScope = getCurrentScope(); - initialScope.setTag('aa', 'aa'); - - withScope(scope => { - expect(getCurrentScope()).toBe(scope); - scope.setTag('bb', 'bb'); - expect(scope).not.toBe(initialScope); - expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' }); - done(); - }); - }); - - it('forks the scope when passing undefined', done => { - const initialScope = getCurrentScope(); - initialScope.setTag('aa', 'aa'); + })); - withScope(undefined, scope => { - expect(getCurrentScope()).toBe(scope); - scope.setTag('bb', 'bb'); - expect(scope).not.toBe(initialScope); - expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' }); - done(); - }); - }); + it('will pass a scope that is different from the current active isolation scope', () => + new Promise(done => { + withScope(scope => { + expect(getIsolationScope()).not.toBe(scope); + done(); + }); + })); + + it('will always make the inner most passed scope the current isolation scope when nesting calls', () => + new Promise(done => { + withIsolationScope(_scope1 => { + withIsolationScope(scope2 => { + expect(getIsolationScope()).toBe(scope2); + done(); + }); + }); + })); + + it('forks the scope when not passing any scope', () => + new Promise(done => { + const initialScope = getCurrentScope(); + initialScope.setTag('aa', 'aa'); + + withScope(scope => { + expect(getCurrentScope()).toBe(scope); + scope.setTag('bb', 'bb'); + expect(scope).not.toBe(initialScope); + expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' }); + done(); + }); + })); + + it('forks the scope when passing undefined', () => + new Promise(done => { + const initialScope = getCurrentScope(); + initialScope.setTag('aa', 'aa'); + + withScope(undefined, scope => { + expect(getCurrentScope()).toBe(scope); + scope.setTag('bb', 'bb'); + expect(scope).not.toBe(initialScope); + expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' }); + done(); + }); + })); - it('sets the passed in scope as active scope', done => { - const initialScope = getCurrentScope(); - initialScope.setTag('aa', 'aa'); + it('sets the passed in scope as active scope', () => + new Promise(done => { + const initialScope = getCurrentScope(); + initialScope.setTag('aa', 'aa'); - const customScope = new Scope(); + const customScope = new Scope(); - withScope(customScope, scope => { - expect(getCurrentScope()).toBe(customScope); - expect(scope).toBe(customScope); - done(); - }); - }); + withScope(customScope, scope => { + expect(getCurrentScope()).toBe(customScope); + expect(scope).toBe(customScope); + done(); + }); + })); }); describe('withIsolationScope()', () => { @@ -917,58 +924,64 @@ describe('withIsolationScope()', () => { getGlobalScope().clear(); }); - it('will make the passed isolation scope the active isolation scope within the callback', done => { - withIsolationScope(scope => { - expect(getIsolationScope()).toBe(scope); - done(); - }); - }); - - it('will pass an isolation scope that is different from the current active scope', done => { - withIsolationScope(scope => { - expect(getCurrentScope()).not.toBe(scope); - done(); - }); - }); + it('will make the passed isolation scope the active isolation scope within the callback', () => + new Promise(done => { + withIsolationScope(scope => { + expect(getIsolationScope()).toBe(scope); + done(); + }); + })); - it('will always make the inner most passed scope the current scope when nesting calls', done => { - withIsolationScope(_scope1 => { - withIsolationScope(scope2 => { - expect(getIsolationScope()).toBe(scope2); + it('will pass an isolation scope that is different from the current active scope', () => + new Promise(done => { + withIsolationScope(scope => { + expect(getCurrentScope()).not.toBe(scope); done(); }); - }); - }); + })); + + it('will always make the inner most passed scope the current scope when nesting calls', () => + new Promise(done => { + withIsolationScope(_scope1 => { + withIsolationScope(scope2 => { + expect(getIsolationScope()).toBe(scope2); + done(); + }); + }); + })); // Note: This is expected! In browser, we do not actually fork this - it('does not fork isolation scope when not passing any isolation scope', done => { - const isolationScope = getIsolationScope(); + it('does not fork isolation scope when not passing any isolation scope', () => + new Promise(done => { + const isolationScope = getIsolationScope(); - withIsolationScope(scope => { - expect(getIsolationScope()).toBe(scope); - expect(scope).toBe(isolationScope); - done(); - }); - }); + withIsolationScope(scope => { + expect(getIsolationScope()).toBe(scope); + expect(scope).toBe(isolationScope); + done(); + }); + })); - it('does not fork isolation scope when passing undefined', done => { - const isolationScope = getIsolationScope(); + it('does not fork isolation scope when passing undefined', () => + new Promise(done => { + const isolationScope = getIsolationScope(); - withIsolationScope(undefined, scope => { - expect(getIsolationScope()).toBe(scope); - expect(scope).toBe(isolationScope); - done(); - }); - }); + withIsolationScope(undefined, scope => { + expect(getIsolationScope()).toBe(scope); + expect(scope).toBe(isolationScope); + done(); + }); + })); - it('ignores passed in isolation scope', done => { - const isolationScope = getIsolationScope(); - const customIsolationScope = new Scope(); + it('ignores passed in isolation scope', () => + new Promise(done => { + const isolationScope = getIsolationScope(); + const customIsolationScope = new Scope(); - withIsolationScope(customIsolationScope, scope => { - expect(getIsolationScope()).toBe(isolationScope); - expect(scope).toBe(isolationScope); - done(); - }); - }); + withIsolationScope(customIsolationScope, scope => { + expect(getIsolationScope()).toBe(isolationScope); + expect(scope).toBe(isolationScope); + done(); + }); + })); }); diff --git a/packages/core/test/lib/sdk.test.ts b/packages/core/test/lib/sdk.test.ts index 3cce0b5a9020..03404ce911f6 100644 --- a/packages/core/test/lib/sdk.test.ts +++ b/packages/core/test/lib/sdk.test.ts @@ -1,3 +1,4 @@ +import { type Mock, beforeEach, describe, expect, it, test, vi } from 'vitest'; import type { Client } from '../../src'; import { captureCheckIn, getCurrentScope, setCurrentClient } from '../../src'; import { installedIntegrations } from '../../src/integration'; @@ -12,7 +13,7 @@ const PUBLIC_DSN = 'https://username@domain/123'; export class MockIntegration implements Integration { public name: string; - public setupOnce: () => void = jest.fn(); + public setupOnce: () => void = vi.fn(); public constructor(name: string) { this.name = name; } @@ -32,8 +33,8 @@ describe('SDK', () => { ]; const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, integrations }); initAndBind(TestClient, options); - expect((integrations[0]?.setupOnce as jest.Mock).mock.calls.length).toBe(1); - expect((integrations[1]?.setupOnce as jest.Mock).mock.calls.length).toBe(1); + expect((integrations[0]?.setupOnce as Mock).mock.calls.length).toBe(1); + expect((integrations[1]?.setupOnce as Mock).mock.calls.length).toBe(1); }); test('calls hooks in the correct order', () => { @@ -41,21 +42,21 @@ describe('SDK', () => { const integration1 = { name: 'integration1', - setupOnce: jest.fn(() => list.push('setupOnce1')), - afterAllSetup: jest.fn(() => list.push('afterAllSetup1')), + setupOnce: vi.fn(() => list.push('setupOnce1')), + afterAllSetup: vi.fn(() => list.push('afterAllSetup1')), } satisfies Integration; const integration2 = { name: 'integration2', - setupOnce: jest.fn(() => list.push('setupOnce2')), - setup: jest.fn(() => list.push('setup2')), - afterAllSetup: jest.fn(() => list.push('afterAllSetup2')), + setupOnce: vi.fn(() => list.push('setupOnce2')), + setup: vi.fn(() => list.push('setup2')), + afterAllSetup: vi.fn(() => list.push('afterAllSetup2')), } satisfies Integration; const integration3 = { name: 'integration3', - setupOnce: jest.fn(() => list.push('setupOnce3')), - setup: jest.fn(() => list.push('setup3')), + setupOnce: vi.fn(() => list.push('setupOnce3')), + setup: vi.fn(() => list.push('setup3')), } satisfies Integration; const integrations: Integration[] = [integration1, integration2, integration3]; diff --git a/packages/core/test/lib/server-runtime-client.test.ts b/packages/core/test/lib/server-runtime-client.test.ts index 2eeb90083f29..bbe1e441cad4 100644 --- a/packages/core/test/lib/server-runtime-client.test.ts +++ b/packages/core/test/lib/server-runtime-client.test.ts @@ -1,5 +1,6 @@ import type { Event, EventHint } from '../../src/types-hoist'; +import { describe, expect, it, test, vi } from 'vitest'; import { Scope, createTransport } from '../../src'; import type { ServerRuntimeClientOptions } from '../../src/server-runtime-client'; import { ServerRuntimeClient } from '../../src/server-runtime-client'; @@ -80,7 +81,7 @@ describe('ServerRuntimeClient', () => { }); client = new ServerRuntimeClient(options); - const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); + const sendEnvelopeSpy = vi.spyOn(client, 'sendEnvelope'); const id = client.captureCheckIn( { monitorSlug: 'foo', status: 'in_progress' }, @@ -150,7 +151,7 @@ describe('ServerRuntimeClient', () => { const options = getDefaultClientOptions({ dsn: PUBLIC_DSN, serverName: 'bar', enabled: false }); client = new ServerRuntimeClient(options); - const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); + const sendEnvelopeSpy = vi.spyOn(client, 'sendEnvelope'); client.captureCheckIn({ monitorSlug: 'foo', status: 'in_progress' }); @@ -163,7 +164,7 @@ describe('ServerRuntimeClient', () => { const options = getDefaultClientOptions({ dsn: PUBLIC_DSN }); client = new ServerRuntimeClient(options); - const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); + const sendEnvelopeSpy = vi.spyOn(client, 'sendEnvelope'); client.captureException(new Error('foo')); @@ -187,7 +188,7 @@ describe('ServerRuntimeClient', () => { const options = getDefaultClientOptions({ dsn: PUBLIC_DSN }); client = new ServerRuntimeClient(options); - const sendEnvelopeSpy = jest.spyOn(client, 'sendEnvelope'); + const sendEnvelopeSpy = vi.spyOn(client, 'sendEnvelope'); client.captureMessage('foo'); diff --git a/packages/core/test/lib/session.test.ts b/packages/core/test/lib/session.test.ts index dfe96e135088..4864ea4623a1 100644 --- a/packages/core/test/lib/session.test.ts +++ b/packages/core/test/lib/session.test.ts @@ -1,5 +1,6 @@ import type { SessionContext } from '../../src/types-hoist'; +import { describe, expect, it, test } from 'vitest'; import { closeSession, makeSession, updateSession } from '../../src/session'; import { timestampInSeconds } from '../../src/utils-hoist/time'; diff --git a/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts b/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts index 63a6910de06b..23406908037c 100644 --- a/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts +++ b/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, @@ -18,7 +19,7 @@ describe('getDynamicSamplingContextFromSpan', () => { }); afterEach(() => { - jest.resetAllMocks(); + vi.resetAllMocks(); }); test('uses frozen DSC from span', () => { diff --git a/packages/core/test/lib/tracing/errors.test.ts b/packages/core/test/lib/tracing/errors.test.ts index 43c6e8eca0ec..46717cae2459 100644 --- a/packages/core/test/lib/tracing/errors.test.ts +++ b/packages/core/test/lib/tracing/errors.test.ts @@ -1,6 +1,7 @@ import { setCurrentClient, spanToJSON, startInactiveSpan, startSpan } from '../../../src'; import type { HandlerDataError, HandlerDataUnhandledRejection } from '../../../src/types-hoist'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; import { _resetErrorsInstrumented, registerSpanErrorInstrumentation } from '../../../src/tracing/errors'; import * as globalErrorModule from '../../../src/utils-hoist/instrument/globalError'; import * as globalUnhandledRejectionModule from '../../../src/utils-hoist/instrument/globalUnhandledRejection'; @@ -9,12 +10,12 @@ import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; let mockErrorCallback: (data: HandlerDataError) => void = () => {}; let mockUnhandledRejectionCallback: (data: HandlerDataUnhandledRejection) => void = () => {}; -const mockAddGlobalErrorInstrumentationHandler = jest +const mockAddGlobalErrorInstrumentationHandler = vi .spyOn(globalErrorModule, 'addGlobalErrorInstrumentationHandler') .mockImplementation(callback => { mockErrorCallback = callback; }); -const mockAddGlobalUnhandledRejectionInstrumentationHandler = jest +const mockAddGlobalUnhandledRejectionInstrumentationHandler = vi .spyOn(globalUnhandledRejectionModule, 'addGlobalUnhandledRejectionInstrumentationHandler') .mockImplementation(callback => { mockUnhandledRejectionCallback = callback; diff --git a/packages/core/test/lib/tracing/idleSpan.test.ts b/packages/core/test/lib/tracing/idleSpan.test.ts index 5280be561067..35f9d59063fe 100644 --- a/packages/core/test/lib/tracing/idleSpan.test.ts +++ b/packages/core/test/lib/tracing/idleSpan.test.ts @@ -1,5 +1,6 @@ import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, SentryNonRecordingSpan, @@ -23,7 +24,7 @@ const dsn = 'https://123@sentry.io/42'; describe('startIdleSpan', () => { beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); getCurrentScope().clear(); getIsolationScope().clear(); @@ -36,7 +37,7 @@ describe('startIdleSpan', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('sets & unsets the idle span on the scope', () => { @@ -47,7 +48,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); idleSpan!.end(); - jest.runAllTimers(); + vi.runAllTimers(); expect(getActiveSpan()).toBe(undefined); }); @@ -82,13 +83,13 @@ describe('startIdleSpan', () => { const childSpan = startInactiveSpan({ name: 'inner2' }); span.end(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); // Idle span is still recording expect(idleSpan.isRecording()).toBe(true); childSpan.end(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); // Now it is finished! expect(idleSpan.isRecording()).toBe(false); @@ -96,7 +97,7 @@ describe('startIdleSpan', () => { }); it('calls beforeSpanEnd callback before finishing', () => { - const beforeSpanEnd = jest.fn(); + const beforeSpanEnd = vi.fn(); const idleSpan = startIdleSpan({ name: 'foo' }, { beforeSpanEnd }); expect(idleSpan).toBeDefined(); @@ -104,14 +105,14 @@ describe('startIdleSpan', () => { startSpan({ name: 'inner' }, () => {}); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(beforeSpanEnd).toHaveBeenCalledTimes(1); expect(beforeSpanEnd).toHaveBeenLastCalledWith(idleSpan); }); it('allows to mutate idle span in beforeSpanEnd before it is sent', () => { const transactions: Event[] = []; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transactions.push(event); return null; }); @@ -127,7 +128,7 @@ describe('startIdleSpan', () => { // We want to accommodate a bit of drift there, so we ensure this starts earlier... const baseTimeInSeconds = Math.floor(Date.now() / 1000) - 9999; - const beforeSpanEnd = jest.fn((span: Span) => { + const beforeSpanEnd = vi.fn((span: Span) => { span.setAttribute('foo', 'bar'); // Try adding a child here - we do this in browser tracing... const inner = startInactiveSpan({ name: 'from beforeSpanEnd', startTime: baseTimeInSeconds }); @@ -138,8 +139,8 @@ describe('startIdleSpan', () => { expect(beforeSpanEnd).not.toHaveBeenCalled(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); - jest.runOnlyPendingTimers(); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); + vi.runOnlyPendingTimers(); expect(spanToJSON(idleSpan!).data).toEqual( expect.objectContaining({ @@ -165,7 +166,7 @@ describe('startIdleSpan', () => { it('filters spans on end', () => { const transactions: Event[] = []; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transactions.push(event); return null; }); @@ -205,8 +206,8 @@ describe('startIdleSpan', () => { regularSpan.end(baseTimeInSeconds + 4); idleSpan.end(baseTimeInSeconds + 10); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); - jest.runOnlyPendingTimers(); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout + 1); + vi.runOnlyPendingTimers(); expect(regularSpan.isRecording()).toBe(false); expect(idleSpan.isRecording()).toBe(false); @@ -245,7 +246,7 @@ describe('startIdleSpan', () => { it('Ensures idle span cannot exceed finalTimeout', () => { const transactions: Event[] = []; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transactions.push(event); return null; }); @@ -282,7 +283,7 @@ describe('startIdleSpan', () => { startTime: baseTimeInSeconds + 4, }); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(regularSpan.isRecording()).toBe(false); expect(idleSpan.isRecording()).toBe(false); @@ -334,7 +335,7 @@ describe('startIdleSpan', () => { expect(hookSpans).toEqual([{ span: idleSpan, hook: 'spanStart' }]); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); expect(hookSpans).toEqual([ @@ -352,7 +353,7 @@ describe('startIdleSpan', () => { setCurrentClient(client); client.init(); - const recordDroppedEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordDroppedEventSpy = vi.spyOn(client, 'recordDroppedEvent'); const idleSpan = startIdleSpan({ name: 'idle span' }); expect(idleSpan).toBeDefined(); @@ -364,7 +365,7 @@ describe('startIdleSpan', () => { it('sets finish reason when span is ended manually', () => { let transaction: Event | undefined; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transaction = event; return null; }); @@ -375,7 +376,7 @@ describe('startIdleSpan', () => { const span = startIdleSpan({ name: 'foo' }); span.end(); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(beforeSendTransaction).toHaveBeenCalledTimes(1); expect(transaction?.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]).toEqual( @@ -385,7 +386,7 @@ describe('startIdleSpan', () => { it('sets finish reason when span ends', () => { let transaction: Event | undefined; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transaction = event; return null; }); @@ -396,7 +397,7 @@ describe('startIdleSpan', () => { startIdleSpan({ name: 'foo' }); startSpan({ name: 'inner' }, () => {}); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(beforeSendTransaction).toHaveBeenCalledTimes(1); expect(transaction?.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]).toEqual( @@ -406,7 +407,7 @@ describe('startIdleSpan', () => { it('sets finish reason when span ends via expired heartbeat timeout', () => { let transaction: Event | undefined; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transaction = event; return null; }); @@ -417,7 +418,7 @@ describe('startIdleSpan', () => { startIdleSpan({ name: 'foo' }); startSpanManual({ name: 'inner' }, () => {}); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(beforeSendTransaction).toHaveBeenCalledTimes(1); expect(transaction?.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]).toEqual( @@ -427,7 +428,7 @@ describe('startIdleSpan', () => { it('sets finish reason when span ends via final timeout', () => { let transaction: Event | undefined; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transaction = event; return null; }); @@ -439,15 +440,15 @@ describe('startIdleSpan', () => { startIdleSpan({ name: 'foo' }, { finalTimeout: TRACING_DEFAULTS.childSpanTimeout * 2 }); const span1 = startInactiveSpan({ name: 'inner' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1); span1.end(); const span2 = startInactiveSpan({ name: 'inner2' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1); span2.end(); startInactiveSpan({ name: 'inner3' }); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(beforeSendTransaction).toHaveBeenCalledTimes(1); expect(transaction?.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]).toEqual( @@ -457,7 +458,7 @@ describe('startIdleSpan', () => { it('uses finish reason set outside when span ends', () => { let transaction: Event | undefined; - const beforeSendTransaction = jest.fn(event => { + const beforeSendTransaction = vi.fn(event => { transaction = event; return null; }); @@ -469,7 +470,7 @@ describe('startIdleSpan', () => { const span = startIdleSpan({ name: 'foo' }); span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'custom reason'); startSpan({ name: 'inner' }, () => {}); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(beforeSendTransaction).toHaveBeenCalledTimes(1); expect(transaction?.contexts?.trace?.data?.[SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON]).toEqual( @@ -482,7 +483,7 @@ describe('startIdleSpan', () => { const idleSpan = startIdleSpan({ name: 'idle span' }); expect(idleSpan).toBeDefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -492,7 +493,7 @@ describe('startIdleSpan', () => { startInactiveSpan({ name: 'span' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); }); @@ -503,11 +504,11 @@ describe('startIdleSpan', () => { startSpan({ name: 'span1' }, () => {}); - jest.advanceTimersByTime(2); + vi.advanceTimersByTime(2); startSpan({ name: 'span2' }, () => {}); - jest.advanceTimersByTime(8); + vi.advanceTimersByTime(8); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); }); @@ -519,11 +520,11 @@ describe('startIdleSpan', () => { startSpan({ name: 'span1' }, () => {}); - jest.advanceTimersByTime(2); + vi.advanceTimersByTime(2); startSpan({ name: 'span2' }, () => {}); - jest.advanceTimersByTime(10); + vi.advanceTimersByTime(10); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -541,12 +542,12 @@ describe('startIdleSpan', () => { expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Wait some time - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); expect(spanToJSON(idleSpan).status).not.toEqual('deadline_exceeded'); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Wait for timeout to exceed - jest.advanceTimersByTime(1000); + vi.advanceTimersByTime(1000); expect(spanToJSON(idleSpan).status).not.toEqual('deadline_exceeded'); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -562,26 +563,26 @@ describe('startIdleSpan', () => { expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Wait some time - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); expect(spanToJSON(idleSpan).status).not.toEqual('deadline_exceeded'); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // New span resets the timeout startInactiveSpan({ name: 'span' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); expect(spanToJSON(idleSpan).status).not.toEqual('deadline_exceeded'); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // New span resets the timeout startInactiveSpan({ name: 'span' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout - 1000); expect(spanToJSON(idleSpan).status).not.toEqual('deadline_exceeded'); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Wait for timeout to exceed - jest.advanceTimersByTime(1000); + vi.advanceTimersByTime(1000); expect(spanToJSON(idleSpan).status).not.toEqual('deadline_exceeded'); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -592,16 +593,16 @@ describe('startIdleSpan', () => { const idleSpan = startIdleSpan({ name: 'idle span' }, { disableAutoFinish: true }); expect(idleSpan).toBeDefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Now emit a signal getClient()!.emit('idleSpanEnableAutoFinish', idleSpan); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -611,16 +612,16 @@ describe('startIdleSpan', () => { startInactiveSpan({ name: 'inner' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Now emit a signal getClient()!.emit('idleSpanEnableAutoFinish', idleSpan); - jest.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.childSpanTimeout); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -628,7 +629,7 @@ describe('startIdleSpan', () => { const idleSpan = startIdleSpan({ name: 'idle span' }, { disableAutoFinish: true }); expect(idleSpan).toBeDefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.finalTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.finalTimeout); expect(spanToJSON(idleSpan).timestamp).toBeDefined(); }); @@ -637,17 +638,17 @@ describe('startIdleSpan', () => { const idleSpan = startIdleSpan({ name: 'idle span' }, { disableAutoFinish: true }); expect(idleSpan).toBeDefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); // Now emit a signal, but with a different span getClient()!.emit('idleSpanEnableAutoFinish', span); // This doesn't affect us! - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); }); }); @@ -668,7 +669,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); - jest.runAllTimers(); + vi.runAllTimers(); expect(spanToJSON(idleSpan!).timestamp).toBe(1100); }); @@ -688,7 +689,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); - jest.runAllTimers(); + vi.runAllTimers(); expect(spanToJSON(idleSpan!).timestamp).toBe(1030); }); @@ -708,7 +709,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); - jest.runAllTimers(); + vi.runAllTimers(); expect(spanToJSON(idleSpan!).timestamp).toBeLessThan(999_999_999); expect(spanToJSON(idleSpan!).timestamp).toBeGreaterThan(1060); diff --git a/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts b/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts index 71bb78738f4f..95a9591ed443 100644 --- a/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts +++ b/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { SPAN_STATUS_ERROR } from '../../../src/tracing'; import { SentryNonRecordingSpan } from '../../../src/tracing/sentryNonRecordingSpan'; import type { Span } from '../../../src/types-hoist'; diff --git a/packages/core/test/lib/tracing/sentrySpan.test.ts b/packages/core/test/lib/tracing/sentrySpan.test.ts index cfc3745f4387..eda0246bda03 100644 --- a/packages/core/test/lib/tracing/sentrySpan.test.ts +++ b/packages/core/test/lib/tracing/sentrySpan.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it, test, vi } from 'vitest'; import type { SpanJSON } from '../../../src'; import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, getCurrentScope, setCurrentClient, timestampInSeconds } from '../../../src'; import { SentrySpan } from '../../../src/tracing/sentrySpan'; @@ -130,7 +131,7 @@ describe('SentrySpan', () => { setCurrentClient(client); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send'); + const mockSend = vi.spyOn(client._transport, 'send'); const notSampledSpan = new SentrySpan({ name: 'not-sampled', @@ -154,7 +155,7 @@ describe('SentrySpan', () => { }); test('sends the span if `beforeSendSpan` does not modify the span', () => { - const beforeSendSpan = jest.fn(span => span); + const beforeSendSpan = vi.fn(span => span); const client = new TestClient( getDefaultTestClientOptions({ dsn: 'https://username@domain/123', @@ -165,7 +166,7 @@ describe('SentrySpan', () => { setCurrentClient(client); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send'); + const mockSend = vi.spyOn(client._transport, 'send'); const span = new SentrySpan({ name: 'test', isStandalone: true, @@ -178,9 +179,9 @@ describe('SentrySpan', () => { }); test('does not drop the span if `beforeSendSpan` returns null', () => { - const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => undefined); + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); - const beforeSendSpan = jest.fn(() => null as unknown as SpanJSON); + const beforeSendSpan = vi.fn(() => null as unknown as SpanJSON); const client = new TestClient( getDefaultTestClientOptions({ dsn: 'https://username@domain/123', @@ -190,9 +191,9 @@ describe('SentrySpan', () => { ); setCurrentClient(client); - const recordDroppedEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordDroppedEventSpy = vi.spyOn(client, 'recordDroppedEvent'); // @ts-expect-error Accessing private transport API - const mockSend = jest.spyOn(client._transport, 'send'); + const mockSend = vi.spyOn(client._transport, 'send'); const span = new SentrySpan({ name: 'test', isStandalone: true, @@ -220,7 +221,7 @@ describe('SentrySpan', () => { setCurrentClient(client); const scope = getCurrentScope(); - const captureEventSpy = jest.spyOn(scope, 'captureEvent').mockImplementation(() => 'testId'); + const captureEventSpy = vi.spyOn(scope, 'captureEvent').mockImplementation(() => 'testId'); const span = new SentrySpan({ name: 'test', diff --git a/packages/core/test/lib/tracing/spanstatus.test.ts b/packages/core/test/lib/tracing/spanstatus.test.ts index 2ed356b1d73e..ee6bfd59443f 100644 --- a/packages/core/test/lib/tracing/spanstatus.test.ts +++ b/packages/core/test/lib/tracing/spanstatus.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { SentrySpan, setHttpStatus, spanToJSON } from '../../../src/index'; describe('setHttpStatus', () => { diff --git a/packages/core/test/lib/tracing/trace.test.ts b/packages/core/test/lib/tracing/trace.test.ts index 00ee444d6f69..148f36ae7255 100644 --- a/packages/core/test/lib/tracing/trace.test.ts +++ b/packages/core/test/lib/tracing/trace.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, @@ -54,7 +55,7 @@ describe('startSpan', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe.each([ @@ -620,7 +621,7 @@ describe('startSpan', () => { }); it('samples with a tracesSampler', () => { - const tracesSampler = jest.fn(() => { + const tracesSampler = vi.fn(() => { return true; }); @@ -647,7 +648,7 @@ describe('startSpan', () => { }); it('includes the scope at the time the span was started when finished', async () => { - const beforeSendTransaction = jest.fn(event => event); + const beforeSendTransaction = vi.fn(event => event); const client = new TestClient( getDefaultTestClientOptions({ @@ -697,7 +698,7 @@ describe('startSpan', () => { const carrier = getMainCarrier(); - const customFn = jest.fn((_options: StartSpanOptions, callback: (span: Span) => string) => { + const customFn = vi.fn((_options: StartSpanOptions, callback: (span: Span) => string) => { callback(staticSpan); return 'aha'; }) as typeof startSpan; @@ -1188,7 +1189,7 @@ describe('startSpanManual', () => { const carrier = getMainCarrier(); - const customFn = jest.fn((_options: StartSpanOptions, callback: (span: Span) => string) => { + const customFn = vi.fn((_options: StartSpanOptions, callback: (span: Span) => string) => { callback(staticSpan); return 'aha'; }) as unknown as typeof startSpanManual; @@ -1505,7 +1506,7 @@ describe('startInactiveSpan', () => { }); it('includes the scope at the time the span was started when finished', async () => { - const beforeSendTransaction = jest.fn(event => event); + const beforeSendTransaction = vi.fn(event => event); const client = new TestClient( getDefaultTestClientOptions({ @@ -1562,7 +1563,7 @@ describe('startInactiveSpan', () => { const carrier = getMainCarrier(); - const customFn = jest.fn((_options: StartSpanOptions) => { + const customFn = vi.fn((_options: StartSpanOptions) => { return staticSpan; }) as unknown as typeof startInactiveSpan; @@ -1727,7 +1728,7 @@ describe('getActiveSpan', () => { const carrier = getMainCarrier(); - const customFn = jest.fn(() => { + const customFn = vi.fn(() => { return staticSpan; }) as typeof getActiveSpan; @@ -1794,7 +1795,7 @@ describe('withActiveSpan()', () => { const carrier = getMainCarrier(); - const customFn = jest.fn((_span: Span | null, callback: (scope: Scope) => string) => { + const customFn = vi.fn((_span: Span | null, callback: (scope: Scope) => string) => { callback(staticScope); return 'aha'; }) as typeof withActiveSpan; @@ -1826,7 +1827,7 @@ describe('span hooks', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('correctly emits span hooks', () => { @@ -1877,7 +1878,7 @@ describe('suppressTracing', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('works for a root span', () => { diff --git a/packages/core/test/lib/transports/base.test.ts b/packages/core/test/lib/transports/base.test.ts index 70179f535efe..3d9ba19e0455 100644 --- a/packages/core/test/lib/transports/base.test.ts +++ b/packages/core/test/lib/transports/base.test.ts @@ -1,5 +1,6 @@ import type { AttachmentItem, EventEnvelope, EventItem, TransportMakeRequestResponse } from '../../../src/types-hoist'; +import { describe, expect, it, vi } from 'vitest'; import { createTransport } from '../../../src/transports/base'; import { createEnvelope, serializeEnvelope } from '../../../src/utils-hoist/envelope'; import type { PromiseBuffer } from '../../../src/utils-hoist/promisebuffer'; @@ -38,8 +39,8 @@ describe('createTransport', () => { it('flushes the buffer', async () => { const mockBuffer: PromiseBuffer = { $: [], - add: jest.fn(), - drain: jest.fn(), + add: vi.fn(), + drain: vi.fn(), }; const transport = createTransport(transportOptions, _ => resolvedSyncPromise({}), mockBuffer); /* eslint-disable @typescript-eslint/unbound-method */ @@ -94,11 +95,11 @@ describe('createTransport', () => { transportResponse = res; } - const mockRequestExecutor = jest.fn(_ => { + const mockRequestExecutor = vi.fn(_ => { return resolvedSyncPromise(transportResponse); }); - const mockRecordDroppedEventCallback = jest.fn(); + const mockRecordDroppedEventCallback = vi.fn(); const transport = createTransport({ recordDroppedEvent: mockRecordDroppedEventCallback }, mockRequestExecutor); @@ -109,7 +110,7 @@ describe('createTransport', () => { const { retryAfterSeconds, beforeLimit, withinLimit, afterLimit } = setRateLimitTimes(); const [transport, setTransportResponse, requestExecutor, recordDroppedEventCallback] = createTestTransport({}); - const dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => beforeLimit); + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => beforeLimit); await transport.send(ERROR_ENVELOPE); expect(requestExecutor).toHaveBeenCalledTimes(1); @@ -156,7 +157,7 @@ describe('createTransport', () => { }, }); - const dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => beforeLimit); + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => beforeLimit); await transport.send(ERROR_ENVELOPE); expect(requestExecutor).toHaveBeenCalledTimes(1); @@ -204,7 +205,7 @@ describe('createTransport', () => { }, }); - const dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => beforeLimit); + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => beforeLimit); await transport.send(ERROR_ENVELOPE); expect(requestExecutor).toHaveBeenCalledTimes(1); @@ -264,7 +265,7 @@ describe('createTransport', () => { }, }); - const dateNowSpy = jest.spyOn(Date, 'now').mockImplementation(() => beforeLimit); + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => beforeLimit); await transport.send(ERROR_ENVELOPE); expect(requestExecutor).toHaveBeenCalledTimes(1); diff --git a/packages/core/test/lib/transports/multiplexed.test.ts b/packages/core/test/lib/transports/multiplexed.test.ts index 024ea7e4bd8a..99e150f8bc66 100644 --- a/packages/core/test/lib/transports/multiplexed.test.ts +++ b/packages/core/test/lib/transports/multiplexed.test.ts @@ -8,6 +8,7 @@ import type { Transport, } from '../../../src/types-hoist'; +import { describe, expect, it, vi } from 'vitest'; import { createClientReportEnvelope, createEnvelope, @@ -95,7 +96,7 @@ describe('makeMultiplexedTransport', () => { it('Falls back to options DSN when a matched DSN is invalid', async () => { // Hide warning logs in the test - jest.spyOn(console, 'error').mockImplementation(() => {}); + vi.spyOn(console, 'error').mockImplementation(() => {}); expect.assertions(1); @@ -109,7 +110,7 @@ describe('makeMultiplexedTransport', () => { const transport = makeTransport({ url: DSN1_URL, ...transportOptions }); await transport.send(ERROR_ENVELOPE); - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('DSN can be overridden via match callback', async () => { diff --git a/packages/core/test/lib/transports/offline.test.ts b/packages/core/test/lib/transports/offline.test.ts index 2f4df73ddae9..0dfc550fcd38 100644 --- a/packages/core/test/lib/transports/offline.test.ts +++ b/packages/core/test/lib/transports/offline.test.ts @@ -9,6 +9,7 @@ import type { TransportMakeRequestResponse, } from '../../../src/types-hoist'; +import { describe, expect, it } from 'vitest'; import { createClientReportEnvelope, createEnvelope, diff --git a/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts b/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts index 077190670aba..2fb8b2f93d16 100644 --- a/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts +++ b/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import type { ScopeData } from '../../../src'; import { startInactiveSpan } from '../../../src'; import type { Attachment, Breadcrumb, Event, EventProcessor, EventType } from '../../../src/types-hoist'; diff --git a/packages/core/test/lib/utils/cookie.test.ts b/packages/core/test/lib/utils/cookie.test.ts index b41d2a4fe112..ccec4a9a26dd 100644 --- a/packages/core/test/lib/utils/cookie.test.ts +++ b/packages/core/test/lib/utils/cookie.test.ts @@ -28,6 +28,7 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +import { describe, expect, it } from 'vitest'; import { parseCookie } from '../../../src/utils/cookie'; describe('parseCookie(str)', function () { diff --git a/packages/core/test/lib/utils/handleCallbackErrors.test.ts b/packages/core/test/lib/utils/handleCallbackErrors.test.ts index 08c116e50ceb..6c4815f35680 100644 --- a/packages/core/test/lib/utils/handleCallbackErrors.test.ts +++ b/packages/core/test/lib/utils/handleCallbackErrors.test.ts @@ -1,10 +1,11 @@ +import { describe, expect, it, vi } from 'vitest'; import { handleCallbackErrors } from '../../../src/utils/handleCallbackErrors'; describe('handleCallbackErrors', () => { it('works with a simple callback', () => { - const onError = jest.fn(); + const onError = vi.fn(); - const fn = jest.fn(() => 'aa'); + const fn = vi.fn(() => 'aa'); const res = handleCallbackErrors(fn, onError); @@ -16,9 +17,9 @@ describe('handleCallbackErrors', () => { it('triggers onError when callback has sync error', () => { const error = new Error('test error'); - const onError = jest.fn(); + const onError = vi.fn(); - const fn = jest.fn(() => { + const fn = vi.fn(() => { throw error; }); @@ -30,9 +31,9 @@ describe('handleCallbackErrors', () => { }); it('works with an async callback', async () => { - const onError = jest.fn(); + const onError = vi.fn(); - const fn = jest.fn(async () => 'aa'); + const fn = vi.fn(async () => 'aa'); const res = handleCallbackErrors(fn, onError); @@ -46,11 +47,11 @@ describe('handleCallbackErrors', () => { }); it('triggers onError when callback returns promise that rejects', async () => { - const onError = jest.fn(); + const onError = vi.fn(); const error = new Error('test error'); - const fn = jest.fn(async () => { + const fn = vi.fn(async () => { await new Promise(resolve => setTimeout(resolve, 10)); throw error; }); @@ -70,10 +71,10 @@ describe('handleCallbackErrors', () => { describe('onFinally', () => { it('triggers after successful sync callback', () => { - const onError = jest.fn(); - const onFinally = jest.fn(); + const onError = vi.fn(); + const onFinally = vi.fn(); - const fn = jest.fn(() => 'aa'); + const fn = vi.fn(() => 'aa'); const res = handleCallbackErrors(fn, onError, onFinally); @@ -86,10 +87,10 @@ describe('handleCallbackErrors', () => { it('triggers after error in sync callback', () => { const error = new Error('test error'); - const onError = jest.fn(); - const onFinally = jest.fn(); + const onError = vi.fn(); + const onFinally = vi.fn(); - const fn = jest.fn(() => { + const fn = vi.fn(() => { throw error; }); @@ -102,10 +103,10 @@ describe('handleCallbackErrors', () => { }); it('triggers after successful async callback', async () => { - const onError = jest.fn(); - const onFinally = jest.fn(); + const onError = vi.fn(); + const onFinally = vi.fn(); - const fn = jest.fn(async () => 'aa'); + const fn = vi.fn(async () => 'aa'); const res = handleCallbackErrors(fn, onError, onFinally); @@ -122,12 +123,12 @@ describe('handleCallbackErrors', () => { }); it('triggers after error in async callback', async () => { - const onError = jest.fn(); - const onFinally = jest.fn(); + const onError = vi.fn(); + const onFinally = vi.fn(); const error = new Error('test error'); - const fn = jest.fn(async () => { + const fn = vi.fn(async () => { await new Promise(resolve => setTimeout(resolve, 10)); throw error; }); diff --git a/packages/core/test/lib/utils/hasTracingEnabled.test.ts b/packages/core/test/lib/utils/hasTracingEnabled.test.ts index 99062b437ec8..ef6ff6f26624 100644 --- a/packages/core/test/lib/utils/hasTracingEnabled.test.ts +++ b/packages/core/test/lib/utils/hasTracingEnabled.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { hasSpansEnabled } from '../../../src'; import { hasTracingEnabled } from '../../../src'; diff --git a/packages/core/test/lib/utils/isSentryRequestUrl.test.ts b/packages/core/test/lib/utils/isSentryRequestUrl.test.ts index c20f8bc011fa..7a07a6041293 100644 --- a/packages/core/test/lib/utils/isSentryRequestUrl.test.ts +++ b/packages/core/test/lib/utils/isSentryRequestUrl.test.ts @@ -1,5 +1,6 @@ import type { Client } from '../../../src/client'; +import { describe, expect, it } from 'vitest'; import { isSentryRequestUrl } from '../../../src'; describe('isSentryRequestUrl', () => { diff --git a/packages/core/test/lib/utils/merge.test.ts b/packages/core/test/lib/utils/merge.test.ts index b0a215231bfb..e89ff2e86561 100644 --- a/packages/core/test/lib/utils/merge.test.ts +++ b/packages/core/test/lib/utils/merge.test.ts @@ -1,5 +1,7 @@ import { merge } from '../../../src/utils/merge'; +import { describe, expect, it } from 'vitest'; + describe('merge', () => { it('works with empty objects', () => { const oldData = {}; diff --git a/packages/core/test/lib/utils/meta.test.ts b/packages/core/test/lib/utils/meta.test.ts index 3d78247b8951..28d21eeb54b1 100644 --- a/packages/core/test/lib/utils/meta.test.ts +++ b/packages/core/test/lib/utils/meta.test.ts @@ -1,9 +1,10 @@ +import { describe, expect, it, vi } from 'vitest'; import { getTraceMetaTags } from '../../../src/utils/meta'; import * as TraceDataModule from '../../../src/utils/traceData'; describe('getTraceMetaTags', () => { it('renders baggage and sentry-trace values to stringified Html meta tags', () => { - jest.spyOn(TraceDataModule, 'getTraceData').mockReturnValueOnce({ + vi.spyOn(TraceDataModule, 'getTraceData').mockReturnValueOnce({ 'sentry-trace': '12345678901234567890123456789012-1234567890123456-1', baggage: 'sentry-environment=production', }); @@ -13,7 +14,7 @@ describe('getTraceMetaTags', () => { }); it('renders just sentry-trace values to stringified Html meta tags', () => { - jest.spyOn(TraceDataModule, 'getTraceData').mockReturnValueOnce({ + vi.spyOn(TraceDataModule, 'getTraceData').mockReturnValueOnce({ 'sentry-trace': '12345678901234567890123456789012-1234567890123456-1', }); @@ -23,7 +24,7 @@ describe('getTraceMetaTags', () => { }); it('returns an empty string if neither sentry-trace nor baggage values are available', () => { - jest.spyOn(TraceDataModule, 'getTraceData').mockReturnValueOnce({}); + vi.spyOn(TraceDataModule, 'getTraceData').mockReturnValueOnce({}); expect(getTraceMetaTags()).toBe(''); }); diff --git a/packages/core/test/lib/utils/parameterize.test.ts b/packages/core/test/lib/utils/parameterize.test.ts index c772c2a410c3..e79e48e84afa 100644 --- a/packages/core/test/lib/utils/parameterize.test.ts +++ b/packages/core/test/lib/utils/parameterize.test.ts @@ -1,5 +1,6 @@ import type { ParameterizedString } from '../../../src/types-hoist'; +import { describe, expect, test } from 'vitest'; import { parameterize } from '../../../src/utils/parameterize'; describe('parameterize()', () => { diff --git a/packages/core/test/lib/utils/parseSampleRate.test.ts b/packages/core/test/lib/utils/parseSampleRate.test.ts index 9c0d91b1810e..fae94a6cc354 100644 --- a/packages/core/test/lib/utils/parseSampleRate.test.ts +++ b/packages/core/test/lib/utils/parseSampleRate.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { parseSampleRate } from '../../../src/utils/parseSampleRate'; describe('parseSampleRate', () => { diff --git a/packages/core/test/lib/utils/request.test.ts b/packages/core/test/lib/utils/request.test.ts index f1d62a7f2a73..44682e6e9b0f 100644 --- a/packages/core/test/lib/utils/request.test.ts +++ b/packages/core/test/lib/utils/request.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { extractQueryParamsFromUrl, headersToDict, diff --git a/packages/core/test/lib/utils/spanUtils.test.ts b/packages/core/test/lib/utils/spanUtils.test.ts index acbac2b35dbd..55d54c3d269e 100644 --- a/packages/core/test/lib/utils/spanUtils.test.ts +++ b/packages/core/test/lib/utils/spanUtils.test.ts @@ -1,3 +1,4 @@ +import { beforeEach, describe, expect, it, test } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, diff --git a/packages/core/test/lib/utils/traceData.test.ts b/packages/core/test/lib/utils/traceData.test.ts index 78c8d806be2a..a7a0c218f069 100644 --- a/packages/core/test/lib/utils/traceData.test.ts +++ b/packages/core/test/lib/utils/traceData.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import type { Client } from '../../../src/'; import { SentrySpan, @@ -48,7 +49,7 @@ describe('getTraceData', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('uses the ACS implementation, if available', () => { @@ -56,7 +57,7 @@ describe('getTraceData', () => { const carrier = getMainCarrier(); - const customFn = jest.fn((options?: { span?: Span }) => { + const customFn = vi.fn((options?: { span?: Span }) => { expect(options).toEqual({ span: undefined }); return { 'sentry-trace': 'abc', @@ -97,7 +98,7 @@ describe('getTraceData', () => { sampled: true, }); - const customFn = jest.fn((options?: { span?: Span }) => { + const customFn = vi.fn((options?: { span?: Span }) => { expect(options).toEqual({ span }); return { 'sentry-trace': 'abc', diff --git a/packages/core/test/lib/utils/transactionEvent.test.ts b/packages/core/test/lib/utils/transactionEvent.test.ts index cd5a3cd750c5..fb49067ff273 100644 --- a/packages/core/test/lib/utils/transactionEvent.test.ts +++ b/packages/core/test/lib/utils/transactionEvent.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_PROFILE_ID } from '../../../src/semanticAttributes'; import type { SpanJSON, TransactionEvent } from '../../../src/types-hoist'; import {} from '../../../src/types-hoist'; diff --git a/packages/core/test/lib/vendor/getClientIpAddress.test.ts b/packages/core/test/lib/vendor/getClientIpAddress.test.ts index 91c5b1961485..ee530566ad60 100644 --- a/packages/core/test/lib/vendor/getClientIpAddress.test.ts +++ b/packages/core/test/lib/vendor/getClientIpAddress.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { getClientIPAddress } from '../../../src/vendor/getIpAddress'; describe('getClientIPAddress', () => { diff --git a/packages/core/test/utils-hoist/aggregate-errors.test.ts b/packages/core/test/utils-hoist/aggregate-errors.test.ts index 535325bd0491..bc6aa2a99d19 100644 --- a/packages/core/test/utils-hoist/aggregate-errors.test.ts +++ b/packages/core/test/utils-hoist/aggregate-errors.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import type { Event, EventHint, Exception, ExtendedError, StackParser } from '../../src/types-hoist'; import { applyAggregateErrorsToEvent } from '../../src/utils-hoist/aggregate-errors'; import { createStackParser } from '../../src/utils-hoist/stacktrace'; diff --git a/packages/core/test/utils-hoist/baggage.test.ts b/packages/core/test/utils-hoist/baggage.test.ts index 9268e178b3a6..d24b11c9f62e 100644 --- a/packages/core/test/utils-hoist/baggage.test.ts +++ b/packages/core/test/utils-hoist/baggage.test.ts @@ -1,3 +1,4 @@ +import { expect, test } from 'vitest'; import { baggageHeaderToDynamicSamplingContext, dynamicSamplingContextToSentryBaggageHeader, diff --git a/packages/core/test/utils-hoist/breadcrumb-log-level.test.ts b/packages/core/test/utils-hoist/breadcrumb-log-level.test.ts index 6be625bb0a63..86062e025f37 100644 --- a/packages/core/test/utils-hoist/breadcrumb-log-level.test.ts +++ b/packages/core/test/utils-hoist/breadcrumb-log-level.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { getBreadcrumbLogLevelFromHttpStatusCode } from '../../src/utils-hoist/breadcrumb-log-level'; describe('getBreadcrumbLogLevelFromHttpStatusCode()', () => { diff --git a/packages/core/test/utils-hoist/browser.test.ts b/packages/core/test/utils-hoist/browser.test.ts index 01a0d5eee747..58b9a0a34ee5 100644 --- a/packages/core/test/utils-hoist/browser.test.ts +++ b/packages/core/test/utils-hoist/browser.test.ts @@ -1,5 +1,6 @@ import { JSDOM } from 'jsdom'; +import { beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { htmlTreeAsString } from '../../src/utils-hoist/browser'; beforeAll(() => { diff --git a/packages/core/test/utils-hoist/clientreport.test.ts b/packages/core/test/utils-hoist/clientreport.test.ts index f925d74fa50c..371047b2ebad 100644 --- a/packages/core/test/utils-hoist/clientreport.test.ts +++ b/packages/core/test/utils-hoist/clientreport.test.ts @@ -1,5 +1,6 @@ import type { ClientReport } from '../../src/types-hoist'; +import { describe, expect, it } from 'vitest'; import { createClientReportEnvelope } from '../../src/utils-hoist/clientreport'; import { parseEnvelope, serializeEnvelope } from '../../src/utils-hoist/envelope'; diff --git a/packages/core/test/utils-hoist/dsn.test.ts b/packages/core/test/utils-hoist/dsn.test.ts index 6f70c83d0c60..86d7eb0a9552 100644 --- a/packages/core/test/utils-hoist/dsn.test.ts +++ b/packages/core/test/utils-hoist/dsn.test.ts @@ -1,17 +1,18 @@ +import { beforeEach, describe, expect, test, vi } from 'vitest'; import { DEBUG_BUILD } from '../../src/utils-hoist/debug-build'; import { dsnToString, makeDsn } from '../../src/utils-hoist/dsn'; import { logger } from '../../src/utils-hoist/logger'; -function testIf(condition: boolean): jest.It { +function testIf(condition: boolean) { return condition ? test : test.skip; } -const loggerErrorSpy = jest.spyOn(logger, 'error').mockImplementation(() => {}); -const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); +const loggerErrorSpy = vi.spyOn(logger, 'error').mockImplementation(() => {}); +const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {}); describe('Dsn', () => { beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('fromComponents', () => { diff --git a/packages/core/test/utils-hoist/envelope.test.ts b/packages/core/test/utils-hoist/envelope.test.ts index 6da22c1869a9..f80244d3d34d 100644 --- a/packages/core/test/utils-hoist/envelope.test.ts +++ b/packages/core/test/utils-hoist/envelope.test.ts @@ -7,6 +7,7 @@ import { spanToJSON, } from '@sentry/core'; import { SentrySpan } from '@sentry/core'; +import { describe, expect, it, test, vi } from 'vitest'; import { getSentryCarrier } from '../../src/carrier'; import { addItemToEnvelope, @@ -110,10 +111,10 @@ describe('envelope', () => { before: () => { GLOBAL_OBJ.__SENTRY__ = {}; - getSentryCarrier(GLOBAL_OBJ).encodePolyfill = jest.fn((input: string) => + getSentryCarrier(GLOBAL_OBJ).encodePolyfill = vi.fn((input: string) => new TextEncoder().encode(input), ); - getSentryCarrier(GLOBAL_OBJ).decodePolyfill = jest.fn((input: Uint8Array) => + getSentryCarrier(GLOBAL_OBJ).decodePolyfill = vi.fn((input: Uint8Array) => new TextDecoder().decode(input), ); }, diff --git a/packages/core/test/utils-hoist/eventbuilder.test.ts b/packages/core/test/utils-hoist/eventbuilder.test.ts index 2994fb5520f6..877df25d8fed 100644 --- a/packages/core/test/utils-hoist/eventbuilder.test.ts +++ b/packages/core/test/utils-hoist/eventbuilder.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it, test } from 'vitest'; import type { Client } from '../../src/client'; import { eventFromMessage, eventFromUnknownInput } from '../../src/utils-hoist/eventbuilder'; import { nodeStackLineParser } from '../../src/utils-hoist/node-stack-trace'; diff --git a/packages/core/test/utils-hoist/instrument.test.ts b/packages/core/test/utils-hoist/instrument.test.ts index 938ba8f17e3e..b6917994c96b 100644 --- a/packages/core/test/utils-hoist/instrument.test.ts +++ b/packages/core/test/utils-hoist/instrument.test.ts @@ -1,3 +1,4 @@ +import { describe, test } from 'vitest'; import { maybeInstrument } from '../../src/utils-hoist/instrument/handlers'; describe('maybeInstrument', () => { diff --git a/packages/core/test/utils-hoist/instrument/fetch.test.ts b/packages/core/test/utils-hoist/instrument/fetch.test.ts index fc6102d6b617..0f08d9f03c6e 100644 --- a/packages/core/test/utils-hoist/instrument/fetch.test.ts +++ b/packages/core/test/utils-hoist/instrument/fetch.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { parseFetchArgs } from '../../../src/utils-hoist/instrument/fetch'; describe('instrument > parseFetchArgs', () => { diff --git a/packages/core/test/utils-hoist/is.test.ts b/packages/core/test/utils-hoist/is.test.ts index 44feba601d04..09fac86fcf12 100644 --- a/packages/core/test/utils-hoist/is.test.ts +++ b/packages/core/test/utils-hoist/is.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it, test } from 'vitest'; import { isDOMError, isDOMException, diff --git a/packages/core/test/utils-hoist/lru.test.ts b/packages/core/test/utils-hoist/lru.test.ts index 39c83a1fbf8f..28259a2700ad 100644 --- a/packages/core/test/utils-hoist/lru.test.ts +++ b/packages/core/test/utils-hoist/lru.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import { LRUMap } from '../../src/utils-hoist/lru'; describe('LRUMap', () => { diff --git a/packages/core/test/utils-hoist/misc.test.ts b/packages/core/test/utils-hoist/misc.test.ts index 05f8736bc443..10942b85ce87 100644 --- a/packages/core/test/utils-hoist/misc.test.ts +++ b/packages/core/test/utils-hoist/misc.test.ts @@ -1,5 +1,6 @@ import type { Event, Mechanism, StackFrame } from '../../src/types-hoist'; +import { describe, expect, it, test } from 'vitest'; import { addContextToFrame, addExceptionMechanism, @@ -302,7 +303,7 @@ describe('uuid4 generation', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires const cryptoMod = require('crypto'); - (global as any).crypto = { getRandomValues: cryptoMod.getRandomValues }; + (global as any).cryptoTest = { getRandomValues: cryptoMod.getRandomValues }; for (let index = 0; index < 1_000; index++) { expect(uuid4()).toMatch(uuid4Regex); @@ -313,7 +314,7 @@ describe('uuid4 generation', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires const cryptoMod = require('crypto'); - (global as any).crypto = { randomUUID: cryptoMod.randomUUID }; + (global as any).cryptoTest = { randomUUID: cryptoMod.randomUUID }; for (let index = 0; index < 1_000; index++) { expect(uuid4()).toMatch(uuid4Regex); @@ -321,7 +322,7 @@ describe('uuid4 generation', () => { }); it("return valid uuid v4 even if crypto doesn't exists", () => { - (global as any).crypto = { getRandomValues: undefined, randomUUID: undefined }; + (global as any).cryptoTest = { getRandomValues: undefined, randomUUID: undefined }; for (let index = 0; index < 1_000; index++) { expect(uuid4()).toMatch(uuid4Regex); @@ -329,7 +330,7 @@ describe('uuid4 generation', () => { }); it('return valid uuid v4 even if crypto invoked causes an error', () => { - (global as any).crypto = { + (global as any).cryptoTest = { getRandomValues: () => { throw new Error('yo'); }, @@ -355,7 +356,7 @@ describe('uuid4 generation', () => { } }; - (global as any).crypto = { getRandomValues }; + (global as any).cryptoTest = { getRandomValues }; for (let index = 0; index < 1_000; index++) { expect(uuid4()).toMatch(uuid4Regex); diff --git a/packages/core/test/utils-hoist/normalize-url.test.ts b/packages/core/test/utils-hoist/normalize-url.test.ts index 080905058e1d..0e8b5d787601 100644 --- a/packages/core/test/utils-hoist/normalize-url.test.ts +++ b/packages/core/test/utils-hoist/normalize-url.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { normalizeUrlToBase } from '../../src/utils-hoist/normalize'; describe('normalizeUrlToBase()', () => { diff --git a/packages/core/test/utils-hoist/normalize.test.ts b/packages/core/test/utils-hoist/normalize.test.ts index 985c0dbf8963..fb1cc75099e8 100644 --- a/packages/core/test/utils-hoist/normalize.test.ts +++ b/packages/core/test/utils-hoist/normalize.test.ts @@ -2,6 +2,7 @@ * @jest-environment jsdom */ +import { describe, expect, test, vi } from 'vitest'; import { addNonEnumerableProperty, normalize } from '../../src'; import * as isModule from '../../src/utils-hoist/is'; import * as stacktraceModule from '../../src/utils-hoist/stacktrace'; @@ -48,8 +49,8 @@ describe('normalize()', () => { }); }); - describe('extracts data from `Event` objects', () => { - const isElement = jest.spyOn(isModule, 'isElement').mockReturnValue(true); + test('extracts data from `Event` objects', () => { + const isElement = vi.spyOn(isModule, 'isElement').mockReturnValue(true); const getAttribute = () => undefined; const parkElement = { tagName: 'PARK', getAttribute }; @@ -594,7 +595,7 @@ describe('normalize()', () => { describe('handles serialization errors', () => { test('restricts effect of error to problematic node', () => { - jest.spyOn(stacktraceModule, 'getFunctionName').mockImplementationOnce(() => { + vi.spyOn(stacktraceModule, 'getFunctionName').mockImplementationOnce(() => { throw new Error('Nope'); }); diff --git a/packages/core/test/utils-hoist/object.test.ts b/packages/core/test/utils-hoist/object.test.ts index 6ccfd71f2218..668d071108f9 100644 --- a/packages/core/test/utils-hoist/object.test.ts +++ b/packages/core/test/utils-hoist/object.test.ts @@ -4,6 +4,7 @@ import type { WrappedFunction } from '../../src/types-hoist'; +import { describe, expect, it, test, vi } from 'vitest'; import { addNonEnumerableProperty, dropUndefinedKeys, @@ -22,7 +23,7 @@ describe('fill()', () => { }, }; const name = 'foo'; - const replacement = jest.fn().mockImplementationOnce(cb => cb); + const replacement = vi.fn().mockImplementationOnce(cb => cb); fill(source, name, replacement); @@ -43,7 +44,7 @@ describe('fill()', () => { expect(source.prop()).toEqual(41); - const replacement = jest.fn().mockImplementation(() => { + const replacement = vi.fn().mockImplementation(() => { return () => 42; }); fill(source, 'prop', replacement); @@ -58,7 +59,7 @@ describe('fill()', () => { foo: (): number => 42, }; const name = 'foo'; - const replacement = jest.fn().mockImplementationOnce(cb => { + const replacement = vi.fn().mockImplementationOnce(cb => { expect(cb).toBe(source.foo); return () => 1337; }); @@ -75,12 +76,12 @@ describe('fill()', () => { foo: (): number => 42, }; const name = 'foo'; - const replacement = jest.fn().mockImplementationOnce(cb => { + const replacement = vi.fn().mockImplementationOnce(cb => { expect(cb).toBe(source.foo); return () => 1337; }); - const replacement2 = jest.fn().mockImplementationOnce(cb => { + const replacement2 = vi.fn().mockImplementationOnce(cb => { expect(cb).toBe(source.foo); return () => 1338; }); @@ -374,7 +375,7 @@ describe('addNonEnumerableProperty', () => { }); it('works with a function', () => { - const func = jest.fn(); + const func = vi.fn(); addNonEnumerableProperty(func as any, 'foo', 'bar'); expect((func as any).foo).toBe('bar'); func(); @@ -409,8 +410,8 @@ describe('addNonEnumerableProperty', () => { describe('markFunctionWrapped', () => { it('works with a function', () => { - const originalFunc = jest.fn(); - const wrappedFunc = jest.fn(); + const originalFunc = vi.fn(); + const wrappedFunc = vi.fn(); markFunctionWrapped(wrappedFunc, originalFunc); expect((wrappedFunc as WrappedFunction).__sentry_original__).toBe(originalFunc); @@ -422,8 +423,8 @@ describe('markFunctionWrapped', () => { }); it('works with a frozen original function', () => { - const originalFunc = Object.freeze(jest.fn()); - const wrappedFunc = jest.fn(); + const originalFunc = Object.freeze(vi.fn()); + const wrappedFunc = vi.fn(); markFunctionWrapped(wrappedFunc, originalFunc); // cannot wrap because it is frozen, but we do not error! @@ -436,8 +437,8 @@ describe('markFunctionWrapped', () => { }); it('works with a frozen wrapped function', () => { - const originalFunc = Object.freeze(jest.fn()); - const wrappedFunc = Object.freeze(jest.fn()); + const originalFunc = Object.freeze(vi.fn()); + const wrappedFunc = Object.freeze(vi.fn()); markFunctionWrapped(wrappedFunc, originalFunc); // Skips adding the property, but also doesn't error diff --git a/packages/core/test/utils-hoist/path.test.ts b/packages/core/test/utils-hoist/path.test.ts index 64dd5caf20ca..6cd760ac84aa 100644 --- a/packages/core/test/utils-hoist/path.test.ts +++ b/packages/core/test/utils-hoist/path.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import { basename, dirname } from '../../src/utils-hoist/path'; describe('path', () => { diff --git a/packages/core/test/utils-hoist/promisebuffer.test.ts b/packages/core/test/utils-hoist/promisebuffer.test.ts index 3357a06e820c..6b0b81d1588e 100644 --- a/packages/core/test/utils-hoist/promisebuffer.test.ts +++ b/packages/core/test/utils-hoist/promisebuffer.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test, vi } from 'vitest'; import { makePromiseBuffer } from '../../src/utils-hoist/promisebuffer'; import { SyncPromise } from '../../src/utils-hoist/syncpromise'; @@ -5,7 +6,7 @@ describe('PromiseBuffer', () => { describe('add()', () => { test('no limit', () => { const buffer = makePromiseBuffer(); - const p = jest.fn(() => new SyncPromise(resolve => setTimeout(resolve))); + const p = vi.fn(() => new SyncPromise(resolve => setTimeout(resolve))); void buffer.add(p); expect(buffer.$.length).toEqual(1); }); @@ -13,11 +14,11 @@ describe('PromiseBuffer', () => { test('with limit', () => { const buffer = makePromiseBuffer(1); let task1; - const producer1 = jest.fn(() => { + const producer1 = vi.fn(() => { task1 = new SyncPromise(resolve => setTimeout(resolve)); return task1; }); - const producer2 = jest.fn(() => new SyncPromise(resolve => setTimeout(resolve))); + const producer2 = vi.fn(() => new SyncPromise(resolve => setTimeout(resolve))); expect(buffer.add(producer1)).toEqual(task1); void expect(buffer.add(producer2)).rejects.toThrowError(); expect(buffer.$.length).toEqual(1); diff --git a/packages/core/test/utils-hoist/ratelimit.test.ts b/packages/core/test/utils-hoist/ratelimit.test.ts index 9a3f37bcf845..556280b93ba4 100644 --- a/packages/core/test/utils-hoist/ratelimit.test.ts +++ b/packages/core/test/utils-hoist/ratelimit.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import type { RateLimits } from '../../src/utils-hoist/ratelimit'; import { DEFAULT_RETRY_AFTER, diff --git a/packages/core/test/utils-hoist/severity.test.ts b/packages/core/test/utils-hoist/severity.test.ts index 65388428b65c..2f5595dfc9f0 100644 --- a/packages/core/test/utils-hoist/severity.test.ts +++ b/packages/core/test/utils-hoist/severity.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import { severityLevelFromString } from '../../src/utils-hoist/severity'; describe('severityLevelFromString()', () => { diff --git a/packages/core/test/utils-hoist/stacktrace.test.ts b/packages/core/test/utils-hoist/stacktrace.test.ts index 1732c35d02bc..cfcc70819fa0 100644 --- a/packages/core/test/utils-hoist/stacktrace.test.ts +++ b/packages/core/test/utils-hoist/stacktrace.test.ts @@ -1,3 +1,4 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; import { nodeStackLineParser } from '../../src/utils-hoist/node-stack-trace'; import { stripSentryFramesAndReverse } from '../../src/utils-hoist/stacktrace'; @@ -119,7 +120,7 @@ describe('Stacktrace', () => { }); describe('node', () => { - const mockGetModule = jest.fn(); + const mockGetModule = vi.fn(); const parser = nodeStackLineParser(mockGetModule); const node = parser[1]; diff --git a/packages/core/test/utils-hoist/string.test.ts b/packages/core/test/utils-hoist/string.test.ts index bf959965cb45..364d29223a66 100644 --- a/packages/core/test/utils-hoist/string.test.ts +++ b/packages/core/test/utils-hoist/string.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import { isMatchingPattern, stringMatchesSomePattern, truncate } from '../../src/utils-hoist/string'; describe('truncate()', () => { diff --git a/packages/core/test/utils-hoist/syncpromise.test.ts b/packages/core/test/utils-hoist/syncpromise.test.ts index 9dce11645b25..862f1e3c8a01 100644 --- a/packages/core/test/utils-hoist/syncpromise.test.ts +++ b/packages/core/test/utils-hoist/syncpromise.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test, vi } from 'vitest'; import { SyncPromise, rejectedSyncPromise, resolvedSyncPromise } from '../../src/utils-hoist/syncpromise'; describe('SyncPromise', () => { @@ -120,14 +121,14 @@ describe('SyncPromise', () => { }); test('with setTimeout', async () => { - jest.useFakeTimers(); + vi.useFakeTimers(); expect.assertions(1); return new SyncPromise(resolve => { setTimeout(() => { resolve(12); }, 10); - jest.runAllTimers(); + vi.runAllTimers(); }).then(val => { expect(val).toEqual(12); }); @@ -146,7 +147,7 @@ describe('SyncPromise', () => { }); test('calling the callback not immediately', () => { - jest.useFakeTimers(); + vi.useFakeTimers(); expect.assertions(4); const qp = new SyncPromise(resolve => @@ -169,7 +170,7 @@ describe('SyncPromise', () => { .then(null, () => { // no-empty }); - jest.runAllTimers(); + vi.runAllTimers(); expect(qp).toHaveProperty('_value'); }); diff --git a/packages/core/test/utils-hoist/testutils.ts b/packages/core/test/utils-hoist/testutils.ts index 6130ee7ca365..b830095d3393 100644 --- a/packages/core/test/utils-hoist/testutils.ts +++ b/packages/core/test/utils-hoist/testutils.ts @@ -1,4 +1,7 @@ -export const testOnlyIfNodeVersionAtLeast = (minVersion: number): jest.It => { +import { it } from 'vitest'; + +// eslint-disable-next-line @typescript-eslint/ban-types +export const testOnlyIfNodeVersionAtLeast = (minVersion: number): Function => { const currentNodeVersion = process.env.NODE_VERSION; try { diff --git a/packages/core/test/utils-hoist/tracing.test.ts b/packages/core/test/utils-hoist/tracing.test.ts index 75b39a573437..851ee7b109c4 100644 --- a/packages/core/test/utils-hoist/tracing.test.ts +++ b/packages/core/test/utils-hoist/tracing.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it, test } from 'vitest'; import { extractTraceparentData, propagationContextFromHeaders } from '../../src/utils-hoist/tracing'; const EXAMPLE_SENTRY_TRACE = '12312012123120121231201212312012-1121201211212012-1'; diff --git a/packages/core/test/utils-hoist/types/typedef.test.ts b/packages/core/test/utils-hoist/types/typedef.test.ts index 45719e13181c..fbf3ffcbb558 100644 --- a/packages/core/test/utils-hoist/types/typedef.test.ts +++ b/packages/core/test/utils-hoist/types/typedef.test.ts @@ -1,5 +1,6 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; +import { test } from 'vitest'; const testStrings = ['/// ']; diff --git a/packages/core/test/utils-hoist/url.test.ts b/packages/core/test/utils-hoist/url.test.ts index a16c72dc1cd2..5126c2647bb7 100644 --- a/packages/core/test/utils-hoist/url.test.ts +++ b/packages/core/test/utils-hoist/url.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { getSanitizedUrlString, parseUrl, stripUrlQueryAndFragment } from '../../src/utils-hoist/url'; describe('stripQueryStringAndFragment', () => { diff --git a/packages/core/test/utils-hoist/vercelWaitUntil.test.ts b/packages/core/test/utils-hoist/vercelWaitUntil.test.ts index b8b6452cbac2..c35b5f076cd4 100644 --- a/packages/core/test/utils-hoist/vercelWaitUntil.test.ts +++ b/packages/core/test/utils-hoist/vercelWaitUntil.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it, vi } from 'vitest'; import { vercelWaitUntil } from '../../src/utils-hoist/vercelWaitUntil'; import { GLOBAL_OBJ } from '../../src/utils-hoist/worldwide'; @@ -27,7 +28,7 @@ describe('vercelWaitUntil', () => { }); it('should call waitUntil method if it is defined', () => { - const waitUntilMock = jest.fn(); + const waitUntilMock = vi.fn(); // @ts-expect-error - Not typed GLOBAL_OBJ[Symbol.for('@vercel/request-context')] = { get: () => ({ waitUntil: waitUntilMock }), diff --git a/packages/core/test/utils-hoist/worldwide.test.ts b/packages/core/test/utils-hoist/worldwide.test.ts index a3106e953861..efd8a152a0ab 100644 --- a/packages/core/test/utils-hoist/worldwide.test.ts +++ b/packages/core/test/utils-hoist/worldwide.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import { GLOBAL_OBJ } from '../../src/utils-hoist/worldwide'; describe('GLOBAL_OBJ', () => { diff --git a/packages/core/tsconfig.test.json b/packages/core/tsconfig.test.json index 6fde53bec436..c2b522d04ee1 100644 --- a/packages/core/tsconfig.test.json +++ b/packages/core/tsconfig.test.json @@ -1,12 +1,12 @@ { "extends": "./tsconfig.json", - "include": ["test/**/*"], + "include": ["test/**/*", "vite.config.ts"], "compilerOptions": { "lib": ["DOM", "ES2018"], // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["node", "jest"] + "types": ["node"] // other package-specific, test-specific options } diff --git a/packages/core/vite.config.ts b/packages/core/vite.config.ts new file mode 100644 index 000000000000..f18ec92095bc --- /dev/null +++ b/packages/core/vite.config.ts @@ -0,0 +1,8 @@ +import baseConfig from '../../vite/vite.config'; + +export default { + ...baseConfig, + test: { + ...baseConfig.test, + }, +}; From 54eba8a7bdac99b0063ea37a990e18d2d94dcfad Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Mon, 24 Feb 2025 16:39:10 +0100 Subject: [PATCH 2/3] Lint --- packages/core/src/utils-hoist/misc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/utils-hoist/misc.ts b/packages/core/src/utils-hoist/misc.ts index 660debae219e..5df836314c1c 100644 --- a/packages/core/src/utils-hoist/misc.ts +++ b/packages/core/src/utils-hoist/misc.ts @@ -23,7 +23,7 @@ interface CryptoGlobal { */ export function uuid4(): string { const gbl = GLOBAL_OBJ as typeof GLOBAL_OBJ & CryptoGlobal; - const crypto = gbl.cryptoTest|| gbl.crypto || gbl.msCrypto; + const crypto = gbl.cryptoTest || gbl.crypto || gbl.msCrypto; let getRandomByte = (): number => Math.random() * 16; try { From 1e50684394c9e1ab7def291db4ef76b1ed25fa5e Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Mon, 24 Feb 2025 17:17:03 +0100 Subject: [PATCH 3/3] Use dependency injection for uuid4 --- packages/core/src/utils-hoist/misc.ts | 13 ++++++------ packages/core/test/utils-hoist/misc.test.ts | 22 +++++++++++---------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/core/src/utils-hoist/misc.ts b/packages/core/src/utils-hoist/misc.ts index 5df836314c1c..8a7d26775462 100644 --- a/packages/core/src/utils-hoist/misc.ts +++ b/packages/core/src/utils-hoist/misc.ts @@ -13,18 +13,19 @@ interface CryptoInternal { interface CryptoGlobal { msCrypto?: CryptoInternal; crypto?: CryptoInternal; - cryptoTest?: CryptoInternal; +} + +function getCrypto(): CryptoInternal | undefined { + const gbl = GLOBAL_OBJ as typeof GLOBAL_OBJ & CryptoGlobal; + return gbl.crypto || gbl.msCrypto; } /** * UUID4 generator - * + * @param crypto Object that provides the crypto API. * @returns string Generated UUID4. */ -export function uuid4(): string { - const gbl = GLOBAL_OBJ as typeof GLOBAL_OBJ & CryptoGlobal; - const crypto = gbl.cryptoTest || gbl.crypto || gbl.msCrypto; - +export function uuid4(crypto = getCrypto()): string { let getRandomByte = (): number => Math.random() * 16; try { if (crypto?.randomUUID) { diff --git a/packages/core/test/utils-hoist/misc.test.ts b/packages/core/test/utils-hoist/misc.test.ts index 10942b85ce87..ea2d03992fe8 100644 --- a/packages/core/test/utils-hoist/misc.test.ts +++ b/packages/core/test/utils-hoist/misc.test.ts @@ -303,10 +303,10 @@ describe('uuid4 generation', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires const cryptoMod = require('crypto'); - (global as any).cryptoTest = { getRandomValues: cryptoMod.getRandomValues }; + const crypto = { getRandomValues: cryptoMod.getRandomValues }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(uuid4Regex); + expect(uuid4(crypto)).toMatch(uuid4Regex); } }); @@ -314,23 +314,23 @@ describe('uuid4 generation', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires const cryptoMod = require('crypto'); - (global as any).cryptoTest = { randomUUID: cryptoMod.randomUUID }; + const crypto = { getRandomValues: cryptoMod.getRandomValues, randomUUID: cryptoMod.randomUUID }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(uuid4Regex); + expect(uuid4(crypto)).toMatch(uuid4Regex); } }); it("return valid uuid v4 even if crypto doesn't exists", () => { - (global as any).cryptoTest = { getRandomValues: undefined, randomUUID: undefined }; + const crypto = { getRandomValues: undefined, randomUUID: undefined }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(uuid4Regex); + expect(uuid4(crypto)).toMatch(uuid4Regex); } }); it('return valid uuid v4 even if crypto invoked causes an error', () => { - (global as any).cryptoTest = { + const crypto = { getRandomValues: () => { throw new Error('yo'); }, @@ -340,7 +340,7 @@ describe('uuid4 generation', () => { }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(uuid4Regex); + expect(uuid4(crypto)).toMatch(uuid4Regex); } }); @@ -356,10 +356,12 @@ describe('uuid4 generation', () => { } }; - (global as any).cryptoTest = { getRandomValues }; + const crypto = { getRandomValues }; for (let index = 0; index < 1_000; index++) { - expect(uuid4()).toMatch(uuid4Regex); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore - we are testing a corner case + expect(uuid4(crypto)).toMatch(uuid4Regex); } }); });