diff --git a/packages/core/jest.config.js b/packages/core/jest.config.js deleted file mode 100644 index 24f49ab59a4c..000000000000 --- a/packages/core/jest.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('../../jest/jest.config.js'); diff --git a/packages/core/package.json b/packages/core/package.json index 8f140bfbb09c..01ef17a2a787 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -58,8 +58,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/test/lib/api.test.ts b/packages/core/test/lib/api.test.ts index d2e500776228..38530771890a 100644 --- a/packages/core/test/lib/api.test.ts +++ b/packages/core/test/lib/api.test.ts @@ -1,6 +1,7 @@ import type { DsnComponents, SdkInfo } from '@sentry/types'; import { makeDsn } from '@sentry/utils'; +import { describe, expect, it, test } from 'vitest'; import { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint } from '../../src/api'; const ingestDsn = 'https://abc@xxxx.ingest.sentry.io:1234/subpath/123'; diff --git a/packages/core/test/lib/attachments.test.ts b/packages/core/test/lib/attachments.test.ts index 4f43f86a6451..2afe4e40fc31 100644 --- a/packages/core/test/lib/attachments.test.ts +++ b/packages/core/test/lib/attachments.test.ts @@ -1,5 +1,6 @@ import { parseEnvelope } from '@sentry/utils'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { createTransport } from '../../src/transports/base'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; @@ -10,7 +11,7 @@ describe('Attachments', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); test('actually end up in envelope', async () => { diff --git a/packages/core/test/lib/base.test.ts b/packages/core/test/lib/base.test.ts index 026b2b3479bc..31c5254809e0 100644 --- a/packages/core/test/lib/base.test.ts +++ b/packages/core/test/lib/base.test.ts @@ -1,5 +1,6 @@ import type { Client, Envelope, ErrorEvent, Event, TransactionEvent } from '@sentry/types'; import { SentryError, SyncPromise, dsnToString, logger } from '@sentry/utils'; +import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { Scope, @@ -20,11 +21,11 @@ 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.mock('@sentry/utils', () => { - const original = jest.requireActual('@sentry/utils'); +vi.mock('@sentry/utils', async () => { + const original = await vi.importActual('@sentry/utils'); return { ...original, @@ -67,7 +68,7 @@ describe('BaseClient', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('constructor() / getDsn()', () => { @@ -89,7 +90,7 @@ describe('BaseClient', () => { 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); @@ -174,7 +175,7 @@ describe('BaseClient', () => { }); 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); @@ -187,7 +188,7 @@ describe('BaseClient', () => { }); 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); @@ -200,7 +201,7 @@ describe('BaseClient', () => { }); 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); @@ -213,7 +214,7 @@ describe('BaseClient', () => { }); 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); @@ -369,7 +370,7 @@ describe('BaseClient', () => { 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); @@ -955,7 +956,7 @@ describe('BaseClient', () => { 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); @@ -968,7 +969,7 @@ describe('BaseClient', () => { 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); @@ -981,7 +982,7 @@ describe('BaseClient', () => { test('calls `beforeSendSpan` and uses original spans without any changes', () => { expect.assertions(2); - const beforeSendSpan = jest.fn(span => span); + const beforeSendSpan = vi.fn(span => span); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendSpan }); const client = new TestClient(options); @@ -1013,7 +1014,7 @@ describe('BaseClient', () => { test('calls `beforeSend` and uses the modified event', () => { expect.assertions(2); - const beforeSend = jest.fn(event => { + const beforeSend = vi.fn(event => { event.message = 'changed1'; return event; }); @@ -1029,7 +1030,7 @@ describe('BaseClient', () => { 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; }); @@ -1043,7 +1044,7 @@ describe('BaseClient', () => { }); 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; }); @@ -1069,7 +1070,7 @@ describe('BaseClient', () => { test('calls `beforeSendSpan` and uses the modified spans', () => { expect.assertions(3); - const beforeSendSpan = jest.fn(span => { + const beforeSendSpan = vi.fn(span => { span.data = { version: 'bravo' }; return span; }); @@ -1108,11 +1109,11 @@ describe('BaseClient', () => { 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(logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerWarnSpy = vi.spyOn(logger, 'log'); client.captureEvent({ message: 'hello' }); @@ -1127,11 +1128,11 @@ describe('BaseClient', () => { 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(logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerWarnSpy = vi.spyOn(logger, 'log'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1144,7 +1145,7 @@ describe('BaseClient', () => { }); test('calls `beforeSendSpan` and discards the span', () => { - const beforeSendSpan = jest.fn(() => null); + const beforeSendSpan = vi.fn(() => null); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendSpan }); const client = new TestClient(options); @@ -1179,11 +1180,11 @@ describe('BaseClient', () => { 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(logger, 'warn'); + const loggerWarnSpy = vi.spyOn(logger, 'warn'); client.captureEvent({ message: 'hello' }); @@ -1200,11 +1201,11 @@ describe('BaseClient', () => { 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(logger, 'warn'); + const loggerWarnSpy = vi.spyOn(logger, 'warn'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1216,11 +1217,10 @@ describe('BaseClient', () => { } }); - 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', async () => { + vi.useFakeTimers(); - const beforeSend = jest.fn( + const beforeSend = vi.fn( async event => new Promise(resolve => { setTimeout(() => { @@ -1232,25 +1232,26 @@ describe('BaseClient', () => { const client = new TestClient(options); client.captureEvent({ message: 'hello' }); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSend).toHaveBeenCalled(); - expect(event.message).toEqual('hello'); - }; + expect(beforeSend).toHaveBeenCalled(); + + const event = await new Promise(resolve => { + TestClient.sendEventCalled = (event: Event) => { + expect(event.message).toEqual('hello'); + resolve(event); + }; + }); - setTimeout(() => { - done(); - }, 5); + expect(event.message).toEqual('hello'); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); }); - test('calls async `beforeSendTransaction` and uses original event without any changes', done => { - jest.useFakeTimers(); - expect.assertions(2); + test('calls async `beforeSendTransaction` and uses original event without any changes', async () => { + vi.useFakeTimers(); - const beforeSendTransaction = jest.fn( + const beforeSendTransaction = vi.fn( async event => new Promise(resolve => { setTimeout(() => { @@ -1261,26 +1262,33 @@ describe('BaseClient', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendTransaction }); const client = new TestClient(options); + vi.runOnlyPendingTimers(); + client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); - jest.runOnlyPendingTimers(); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSendTransaction).toHaveBeenCalled(); - expect(event.transaction).toBe('/dogs/are/great'); - }; + vi.runOnlyPendingTimers(); - setTimeout(() => { - done(); - }, 5); + expect(beforeSendTransaction).toHaveBeenCalledWith( + expect.objectContaining({ type: 'transaction', transaction: '/dogs/are/great' }), + expect.any(Object), + ); + + vi.runOnlyPendingTimers(); + + const event = await new Promise(resolve => { + TestClient.sendEventCalled = (event: Event) => { + resolve(event); + }; + }); - jest.runOnlyPendingTimers(); + expect(event.transaction).toBe('/dogs/are/great'); }); - test('calls async `beforeSend` and uses the modified event', done => { - jest.useFakeTimers(); + test('calls async `beforeSend` and uses the modified event', async () => { + vi.useFakeTimers(); expect.assertions(2); - const beforeSend = jest.fn(async event => { + const beforeSend = vi.fn(async event => { event.message = 'changed2'; return new Promise(resolve => { setTimeout(() => { @@ -1292,25 +1300,23 @@ describe('BaseClient', () => { const client = new TestClient(options); client.captureEvent({ message: 'hello' }); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSend).toHaveBeenCalled(); - expect(event.message).toEqual('changed2'); - }; + expect(beforeSend).toHaveBeenCalledTimes(1); - setTimeout(() => { - done(); - }, 5); + const event = await new Promise(resolve => { + TestClient.sendEventCalled = (event: Event) => { + resolve(event); + }; + }); - jest.runOnlyPendingTimers(); + expect(event.message).toEqual('changed2'); }); - test('calls async `beforeSendTransaction` and uses the modified event', done => { - jest.useFakeTimers(); - expect.assertions(2); + test('calls async `beforeSendTransaction` and uses the modified event', async () => { + vi.useFakeTimers(); - const beforeSendTransaction = jest.fn(async event => { + const beforeSendTransaction = vi.fn(async event => { event.transaction = '/adopt/dont/shop'; return new Promise(resolve => { setTimeout(() => { @@ -1322,25 +1328,24 @@ describe('BaseClient', () => { const client = new TestClient(options); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); - TestClient.sendEventCalled = (event: Event) => { - expect(beforeSendTransaction).toHaveBeenCalled(); - expect(event.transaction).toBe('/adopt/dont/shop'); - }; + expect(beforeSendTransaction).toHaveBeenCalledTimes(1); - setTimeout(() => { - done(); - }, 5); + const event = await new Promise(resolve => { + TestClient.sendEventCalled = (event: Event) => { + resolve(event); + }; + }); - jest.runOnlyPendingTimers(); + expect(event.transaction).toBe('/adopt/dont/shop'); }); 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(() => { @@ -1352,17 +1357,17 @@ describe('BaseClient', () => { 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(() => { @@ -1374,7 +1379,7 @@ describe('BaseClient', () => { 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(); @@ -1383,7 +1388,7 @@ describe('BaseClient', () => { 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); @@ -1397,7 +1402,7 @@ describe('BaseClient', () => { 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); @@ -1417,7 +1422,7 @@ describe('BaseClient', () => { 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, @@ -1425,7 +1430,7 @@ describe('BaseClient', () => { }), ); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); client.captureEvent({ message: 'hello' }, {}); @@ -1438,7 +1443,7 @@ describe('BaseClient', () => { test('`beforeSendTransaction` records dropped events', () => { expect.assertions(2); - const beforeSendTransaction = jest.fn(() => null); + const beforeSendTransaction = vi.fn(() => null); const client = new TestClient( getDefaultTestClientOptions({ @@ -1447,7 +1452,7 @@ describe('BaseClient', () => { }), ); - const recordLostEventSpy = jest.spyOn(client, 'recordDroppedEvent'); + const recordLostEventSpy = vi.spyOn(client, 'recordDroppedEvent'); client.captureEvent({ transaction: '/dogs/are/great', type: 'transaction' }); @@ -1462,8 +1467,8 @@ describe('BaseClient', () => { expect.assertions(3); const client = new TestClient(getDefaultTestClientOptions({ dsn: PUBLIC_DSN })); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerLogSpy = jest.spyOn(logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerLogSpy = vi.spyOn(logger, 'log'); const scope = new Scope(); scope.addEventProcessor(() => null); @@ -1480,8 +1485,8 @@ describe('BaseClient', () => { expect.assertions(3); const client = new TestClient(getDefaultTestClientOptions({ dsn: PUBLIC_DSN })); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerLogSpy = jest.spyOn(logger, 'log'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerLogSpy = vi.spyOn(logger, 'log'); const scope = new Scope(); scope.addEventProcessor(() => null); @@ -1500,7 +1505,7 @@ describe('BaseClient', () => { 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); @@ -1518,7 +1523,7 @@ describe('BaseClient', () => { 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); @@ -1557,7 +1562,7 @@ describe('BaseClient', () => { }); 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; }); @@ -1584,8 +1589,8 @@ describe('BaseClient', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); - const captureExceptionSpy = jest.spyOn(client, 'captureException'); - const loggerWarnSpy = jest.spyOn(logger, 'warn'); + const captureExceptionSpy = vi.spyOn(client, 'captureException'); + const loggerWarnSpy = vi.spyOn(logger, 'warn'); const scope = new Scope(); const exception = new Error('sorry'); scope.addEventProcessor(() => { @@ -1614,7 +1619,7 @@ describe('BaseClient', () => { 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', { @@ -1669,7 +1674,7 @@ describe('BaseClient', () => { 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(); @@ -1690,7 +1695,7 @@ describe('BaseClient', () => { describe('flush/close', () => { test('flush', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(4); const { makeTransport, getSendCalled, getSentCount, delay } = makeFakeTransport(1); @@ -1715,7 +1720,7 @@ describe('BaseClient', () => { }); test('flush with some events being processed async', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(4); const { makeTransport, getSendCalled, getSentCount, delay } = makeFakeTransport(300); @@ -1728,7 +1733,7 @@ describe('BaseClient', () => { }), ); - const spy = jest.spyOn(TestClient.instance!, 'eventFromMessage'); + const spy = vi.spyOn(TestClient.instance!, 'eventFromMessage'); spy.mockImplementationOnce( (message, level) => new SyncPromise(resolve => { @@ -1750,7 +1755,7 @@ describe('BaseClient', () => { }); test('close', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(4); const { makeTransport, delay, getSentCount } = makeFakeTransport(300); @@ -1774,7 +1779,7 @@ describe('BaseClient', () => { }); test('multiple concurrent flush calls should just work', async () => { - jest.useRealTimers(); + vi.useRealTimers(); expect.assertions(3); const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); @@ -1796,11 +1801,11 @@ describe('BaseClient', () => { describe('sendEvent', () => { beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); }); afterEach(() => { - jest.useRealTimers(); + vi.useRealTimers(); }); it('emits `afterSendEvent` when sending an error', async () => { @@ -1812,15 +1817,15 @@ describe('BaseClient', () => { ); // @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; @@ -1840,15 +1845,15 @@ describe('BaseClient', () => { ); // @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; @@ -1870,21 +1875,17 @@ describe('BaseClient', () => { ); // @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(); - // Wait for two ticks - // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang - await undefined; - await undefined; + await vi.runAllTimersAsync(); expect(mockSend).toBeCalledTimes(1); expect(callback).toBeCalledTimes(1); @@ -1902,24 +1903,20 @@ describe('BaseClient', () => { ); // @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(); - // Wait for two ticks - // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang - await undefined; - await undefined; + await vi.runAllTimersAsync(); expect(mockSend).toBeCalledTimes(1); - expect(callback).toBeCalledTimes(1); + expect(callback).toHaveBeenCalledTimes(1); expect(callback).toBeCalledWith(errorEvent, { statusCode: 200 }); }); }); @@ -2040,7 +2037,7 @@ describe('BaseClient', () => { 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( @@ -2050,23 +2047,19 @@ describe('BaseClient', () => { }), ); - 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(); - // Wait for two ticks - // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang - await undefined; - await undefined; + await vi.runAllTimersAsync(); expect(mockSend).toBeCalledTimes(1); expect(callback).toBeCalledTimes(1); @@ -2077,11 +2070,7 @@ describe('BaseClient', () => { expect(client['_hooks']['afterSendEvent']).toEqual([]); client.sendEvent(errorEvent); - jest.runAllTimers(); - // Wait for two ticks - // note that for whatever reason, await new Promise(resolve => setTimeout(resolve, 0)) causes the test to hang - await undefined; - await undefined; + await vi.runAllTimersAsync(); expect(mockSend).toBeCalledTimes(2); // Note that the `callback` has still been called only once and not twice, diff --git a/packages/core/test/lib/carrier.test.ts b/packages/core/test/lib/carrier.test.ts index 3c94c96b98c1..721874a7e17e 100644 --- a/packages/core/test/lib/carrier.test.ts +++ b/packages/core/test/lib/carrier.test.ts @@ -1,4 +1,5 @@ import { SDK_VERSION } from '@sentry/utils'; +import { describe, expect, it } from 'vitest'; import { getSentryCarrier } from '../../src/carrier'; describe('getSentryCarrier', () => { diff --git a/packages/core/test/lib/checkin.test.ts b/packages/core/test/lib/checkin.test.ts index 5ae6bac6b5f3..203207b95222 100644 --- a/packages/core/test/lib/checkin.test.ts +++ b/packages/core/test/lib/checkin.test.ts @@ -1,5 +1,6 @@ import type { SerializedCheckIn } from '@sentry/types'; +import { describe, expect, test } from 'vitest'; import { createCheckInEnvelope } from '../../src/checkin'; describe('createCheckInEnvelope', () => { diff --git a/packages/core/test/lib/envelope.test.ts b/packages/core/test/lib/envelope.test.ts index 74e764c1d938..bd9a6d8c3a13 100644 --- a/packages/core/test/lib/envelope.test.ts +++ b/packages/core/test/lib/envelope.test.ts @@ -11,6 +11,8 @@ import { import { createEventEnvelope, createSpanEnvelope } from '../../src/envelope'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + const testDsn: DsnComponents = { protocol: 'https', projectId: 'abc', host: 'testry.io', publicKey: 'pubKey123' }; describe('createEventEnvelope', () => { @@ -185,7 +187,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); @@ -217,7 +219,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 cd9e99e43bdb..4d49b7541bcb 100644 --- a/packages/core/test/lib/feedback.test.ts +++ b/packages/core/test/lib/feedback.test.ts @@ -1,4 +1,5 @@ import type { Span } from '@sentry/types'; +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'; @@ -322,7 +323,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 => { @@ -392,7 +393,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'); @@ -478,8 +479,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 c5a31a944663..96ff73dc302b 100644 --- a/packages/core/test/lib/hint.test.ts +++ b/packages/core/test/lib/hint.test.ts @@ -5,8 +5,10 @@ import { initAndBind } from '../../src/sdk'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; import { AddAttachmentTestIntegration } from '../mocks/integration'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; + const PUBLIC_DSN = 'https://username@domain/123'; -const sendEvent = jest.spyOn(TestClient.prototype, 'sendEvent'); +const sendEvent = vi.spyOn(TestClient.prototype, 'sendEvent'); describe('Hint', () => { beforeEach(() => { @@ -15,7 +17,7 @@ describe('Hint', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); // @ts-expect-error for testing delete GLOBAL_OBJ.__SENTRY__; }); diff --git a/packages/core/test/lib/integration.test.ts b/packages/core/test/lib/integration.test.ts index 18b9d1791bc8..d7ba64481f28 100644 --- a/packages/core/test/lib/integration.test.ts +++ b/packages/core/test/lib/integration.test.ts @@ -2,6 +2,7 @@ import type { Integration, Options } from '@sentry/types'; import { logger } from '@sentry/utils'; import { getCurrentScope } from '../../src/currentScopes'; +import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'; import { addIntegration, getIntegrationsToSetup, installedIntegrations, setupIntegration } from '../../src/integration'; import { setCurrentClient } from '../../src/sdk'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; @@ -339,7 +340,7 @@ describe('setupIntegration', () => { it('works with a minimal integration', () => { class CustomIntegration implements Integration { name = 'test'; - setupOnce = jest.fn(); + setupOnce = vi.fn(); } const client = getTestClient(); @@ -355,7 +356,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(); @@ -382,8 +383,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(); @@ -420,8 +421,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(); @@ -472,8 +473,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'; }); } @@ -485,7 +486,7 @@ describe('setupIntegration', () => { setupIntegration(client, integration, integrationIndex); - const sendEvent = jest.fn(); + const sendEvent = vi.fn(); client.sendEvent = sendEvent; client.captureEvent({ event_id: '1a' }); @@ -500,8 +501,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; }); } @@ -554,8 +555,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' }; }); } @@ -567,7 +568,7 @@ describe('setupIntegration', () => { setupIntegration(client, integration, integrationIndex); - const sendEvent = jest.fn(); + const sendEvent = vi.fn(); client.sendEvent = sendEvent; client.captureEvent({ event_id: '1a' }); @@ -582,8 +583,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; }); } @@ -595,7 +596,7 @@ describe('setupIntegration', () => { setupIntegration(client, integration, integrationIndex); - const sendEvent = jest.fn(); + const sendEvent = vi.fn(); client.sendEvent = sendEvent; client.captureEvent({ event_id: '1a' }); @@ -612,15 +613,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(); @@ -634,10 +635,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); @@ -651,9 +652,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'; @@ -675,13 +676,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 ce913642b123..23d400ad0025 100644 --- a/packages/core/test/lib/integrations/captureconsole.test.ts +++ b/packages/core/test/lib/integrations/captureconsole.test.ts @@ -13,14 +13,17 @@ import * as SentryCore from '../../../src/exports'; import { captureConsoleIntegration } from '../../../src/integrations/captureconsole'; -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(), +import type { Mock } from 'vitest'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +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', () => { @@ -31,23 +34,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]; @@ -55,7 +58,7 @@ describe('CaptureConsole setup', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); CONSOLE_LEVELS.forEach(key => { originalConsoleMethods[key] = _originalConsoleMethods[key]; @@ -135,7 +138,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); @@ -264,7 +267,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'] }); @@ -309,7 +312,7 @@ describe('CaptureConsole setup', () => { }); it("marks captured exception's mechanism as unhandled", () => { - // const addExceptionMechanismSpy = jest.spyOn(utils, 'addExceptionMechanism'); + // const addExceptionMechanismSpy = vi.spyOn(utils, 'addExceptionMechanism'); const captureConsole = captureConsoleIntegration({ levels: ['error'] }); captureConsole.setup?.(mockClient); @@ -317,7 +320,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/debug.test.ts b/packages/core/test/lib/integrations/debug.test.ts index c391d3057f0e..a403eceab51d 100644 --- a/packages/core/test/lib/integrations/debug.test.ts +++ b/packages/core/test/lib/integrations/debug.test.ts @@ -1,5 +1,6 @@ import type { Client, Event, EventHint } from '@sentry/types'; +import { afterAll, afterEach, describe, expect, it, vi } from 'vitest'; import { debugIntegration } from '../../../src/integrations/debug'; function testEventLogged( @@ -26,7 +27,7 @@ function testEventLogged( } // Replace console log with a mock so we can check for invocations -const mockConsoleLog = jest.fn(); +const mockConsoleLog = vi.fn(); // eslint-disable-next-line @typescript-eslint/unbound-method const originalConsoleLog = global.console.log; global.console.log = mockConsoleLog; @@ -38,7 +39,7 @@ describe('Debug integration setup should register an event processor that', () = }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('logs an event', () => { diff --git a/packages/core/test/lib/integrations/dedupe.test.ts b/packages/core/test/lib/integrations/dedupe.test.ts index 9478f41a6492..aeb02cba1bb1 100644 --- a/packages/core/test/lib/integrations/dedupe.test.ts +++ b/packages/core/test/lib/integrations/dedupe.test.ts @@ -1,5 +1,6 @@ import type { Event as SentryEvent, Exception, StackFrame, Stacktrace } from '@sentry/types'; +import { describe, expect, it } from 'vitest'; import { _shouldDropEvent, dedupeIntegration } from '../../../src/integrations/dedupe'; type EventWithException = SentryEvent & { diff --git a/packages/core/test/lib/integrations/extraerrordata.test.ts b/packages/core/test/lib/integrations/extraerrordata.test.ts index d38f8fff25ee..66ee8376b3c3 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 '@sentry/types'; 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 87a85744c7ce..fb875564fdbb 100644 --- a/packages/core/test/lib/integrations/functiontostring.test.ts +++ b/packages/core/test/lib/integrations/functiontostring.test.ts @@ -1,4 +1,5 @@ import { fill } from '@sentry/utils'; +import { afterAll, beforeEach, describe, expect, it } from 'vitest'; import { 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 eb68c8c14d3b..a91330eee382 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 '@sentry/types'; +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 2fb06bd6081d..a2fe55b645c0 100644 --- a/packages/core/test/lib/integrations/metadata.test.ts +++ b/packages/core/test/lib/integrations/metadata.test.ts @@ -1,6 +1,7 @@ import type { Event } from '@sentry/types'; import { GLOBAL_OBJ, createStackParser, nodeStackLineParser, parseEnvelope } from '@sentry/utils'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { captureException, createTransport, moduleMetadataIntegration, setCurrentClient } from '../../../src'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; @@ -18,7 +19,7 @@ describe('ModuleMetadata integration', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); test('Adds and removes metadata from stack frames', done => { diff --git a/packages/core/test/lib/integrations/requestdata.test.ts b/packages/core/test/lib/integrations/requestdata.test.ts index 648d47e4faf5..b21ff8023167 100644 --- a/packages/core/test/lib/integrations/requestdata.test.ts +++ b/packages/core/test/lib/integrations/requestdata.test.ts @@ -4,9 +4,10 @@ import * as sentryUtils from '@sentry/utils'; import type { RequestDataIntegrationOptions } from '../../../src'; import { requestDataIntegration, setCurrentClient } from '../../../src'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; -const addRequestDataToEventSpy = jest.spyOn(sentryUtils, 'addRequestDataToEvent'); +const addRequestDataToEventSpy = vi.spyOn(sentryUtils, 'addRequestDataToEvent'); const headers = { ears: 'furry', nose: 'wet', tongue: 'spotted', cookie: 'favorite=zukes' }; const method = 'wagging'; @@ -53,7 +54,7 @@ describe('`RequestData` integration', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe('option conversion', () => { diff --git a/packages/core/test/lib/integrations/rewriteframes.test.ts b/packages/core/test/lib/integrations/rewriteframes.test.ts index f3ea865b459d..d14cdd2ee58b 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 '@sentry/types'; +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/sessiontiming.test.ts b/packages/core/test/lib/integrations/sessiontiming.test.ts index 6213d7cae9c1..4f14febb41ec 100644 --- a/packages/core/test/lib/integrations/sessiontiming.test.ts +++ b/packages/core/test/lib/integrations/sessiontiming.test.ts @@ -1,4 +1,5 @@ import type { Event } from '@sentry/types'; +import { describe, expect, it } from 'vitest'; import { sessionTimingIntegration } from '../../../src/integrations/sessiontiming'; const sessionTiming = sessionTimingIntegration(); 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 b11b93498b02..b1440de17195 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 @@ -3,6 +3,8 @@ import { GLOBAL_OBJ, createStackParser, nodeStackLineParser } from '@sentry/util import { thirdPartyErrorFilterIntegration } from '../../../src/integrations/third-party-errors-filter'; import { addMetadataToStackFrames } from '../../../src/metadata'; +import { beforeEach, describe, expect, it } from 'vitest'; + function clone(data: T): T { return JSON.parse(JSON.stringify(data)); } diff --git a/packages/core/test/lib/integrations/zoderrrors.test.ts b/packages/core/test/lib/integrations/zoderrrors.test.ts index 33dc2609ac09..9523c8806c52 100644 --- a/packages/core/test/lib/integrations/zoderrrors.test.ts +++ b/packages/core/test/lib/integrations/zoderrrors.test.ts @@ -1,5 +1,6 @@ import type { Event, EventHint } from '@sentry/types'; +import { describe, expect, test } from 'vitest'; import { applyZodErrorsToEvent } from '../../../src/integrations/zoderrors'; // Simplified type definition diff --git a/packages/core/test/lib/metadata.test.ts b/packages/core/test/lib/metadata.test.ts index 378bb51e6562..9fe22a238a5a 100644 --- a/packages/core/test/lib/metadata.test.ts +++ b/packages/core/test/lib/metadata.test.ts @@ -1,6 +1,7 @@ import type { Event } from '@sentry/types'; import { GLOBAL_OBJ, createStackParser, nodeStackLineParser } from '@sentry/utils'; +import { beforeEach, describe, expect, it } from 'vitest'; import { addMetadataToStackFrames, getMetadataForUrl, stripMetadataFromStackFrames } from '../../src/metadata'; const parser = createStackParser(nodeStackLineParser()); diff --git a/packages/core/test/lib/metrics/aggregator.test.ts b/packages/core/test/lib/metrics/aggregator.test.ts index 2a471d12bb04..1dfa93c7eedb 100644 --- a/packages/core/test/lib/metrics/aggregator.test.ts +++ b/packages/core/test/lib/metrics/aggregator.test.ts @@ -1,3 +1,4 @@ +import { beforeEach, describe, expect, it, test, vi } from 'vitest'; import { MetricsAggregator } from '../../../src/metrics/aggregator'; import { MAX_WEIGHT } from '../../../src/metrics/constants'; import { CounterMetric } from '../../../src/metrics/instance'; @@ -10,7 +11,7 @@ describe('MetricsAggregator', () => { const options = getDefaultTestClientOptions({ tracesSampleRate: 0.0 }); beforeEach(() => { - jest.useFakeTimers('legacy'); + vi.useFakeTimers(); testClient = new TestClient(options); }); @@ -81,12 +82,13 @@ describe('MetricsAggregator', () => { describe('close', () => { test('should flush immediately', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); + const clearIntervalSpy = vi.spyOn(global, 'clearInterval'); + const capture = vi.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); aggregator.add('c', 'requests', 1); aggregator.close(); // It should clear the interval. - expect(clearInterval).toHaveBeenCalled(); + expect(clearIntervalSpy).toHaveBeenCalledTimes(1); expect(capture).toBeCalled(); expect(capture).toBeCalledTimes(1); }); @@ -94,7 +96,8 @@ describe('MetricsAggregator', () => { describe('flush', () => { test('should flush immediately', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); + const clearIntervalSpy = vi.spyOn(global, 'clearInterval'); + const capture = vi.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); aggregator.add('c', 'requests', 1); aggregator.flush(); @@ -104,14 +107,14 @@ describe('MetricsAggregator', () => { capture.mockReset(); aggregator.close(); // It should clear the interval. - expect(clearInterval).toHaveBeenCalled(); + expect(clearIntervalSpy).toHaveBeenCalledTimes(1); // It shouldn't be called since it's been already flushed. expect(capture).toBeCalledTimes(0); }); test('should not capture if empty', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); + const capture = vi.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); aggregator.add('c', 'requests', 1); aggregator.flush(); @@ -124,7 +127,7 @@ describe('MetricsAggregator', () => { describe('add', () => { test('it should respect the max weight and flush if exceeded', () => { - const capture = jest.spyOn(testClient, 'sendEnvelope'); + const capture = vi.spyOn(testClient, 'sendEnvelope'); const aggregator = new MetricsAggregator(testClient); for (let i = 0; i < MAX_WEIGHT; i++) { diff --git a/packages/core/test/lib/metrics/browser-aggregator.test.ts b/packages/core/test/lib/metrics/browser-aggregator.test.ts index 669959a03e05..de0668f6021c 100644 --- a/packages/core/test/lib/metrics/browser-aggregator.test.ts +++ b/packages/core/test/lib/metrics/browser-aggregator.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { BrowserMetricsAggregator } from '../../../src/metrics/browser-aggregator'; import { CounterMetric } from '../../../src/metrics/instance'; import { serializeMetricBuckets } from '../../../src/metrics/utils'; diff --git a/packages/core/test/lib/metrics/timing.test.ts b/packages/core/test/lib/metrics/timing.test.ts index fa7c9f88da77..066d06790e91 100644 --- a/packages/core/test/lib/metrics/timing.test.ts +++ b/packages/core/test/lib/metrics/timing.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { getCurrentScope, getIsolationScope, setCurrentClient } from '../../../src'; import { MetricsAggregator } from '../../../src/metrics/aggregator'; import { metrics as metricsCore } from '../../../src/metrics/exports'; @@ -28,7 +29,7 @@ describe('metrics.timing', () => { const res = metricsDefault.timing('t1', 10); expect(res).toStrictEqual(undefined); - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); + const sendSpy = vi.spyOn(testClient.getTransport()!, 'send'); metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); @@ -43,7 +44,7 @@ describe('metrics.timing', () => { const res = metricsDefault.timing('t1', 10, 'hour'); expect(res).toStrictEqual(undefined); - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); + const sendSpy = vi.spyOn(testClient.getTransport()!, 'send'); metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); @@ -60,7 +61,7 @@ describe('metrics.timing', () => { }); expect(res).toStrictEqual(undefined); - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); + const sendSpy = vi.spyOn(testClient.getTransport()!, 'send'); metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); @@ -83,7 +84,7 @@ describe('metrics.timing', () => { }); expect(res).toStrictEqual('oho'); - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); + const sendSpy = vi.spyOn(testClient.getTransport()!, 'send'); metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); @@ -102,7 +103,7 @@ describe('metrics.timing', () => { expect(res).toBeInstanceOf(Promise); expect(await res).toStrictEqual('oho'); - const sendSpy = jest.spyOn(testClient.getTransport()!, 'send'); + const sendSpy = vi.spyOn(testClient.getTransport()!, 'send'); metricsCore.getMetricsAggregatorForClient(testClient, MetricsAggregator)!.flush(); diff --git a/packages/core/test/lib/metrics/utils.test.ts b/packages/core/test/lib/metrics/utils.test.ts index e25014715748..7885f828080b 100644 --- a/packages/core/test/lib/metrics/utils.test.ts +++ b/packages/core/test/lib/metrics/utils.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, @@ -15,7 +16,7 @@ describe('getBucketKey', () => { [DISTRIBUTION_METRIC_TYPE, 'lcp', 'second', { a: '1', b: '2', c: '3' }, 'dlcpseconda,1,b,2,c,3'], [DISTRIBUTION_METRIC_TYPE, 'lcp', 'second', { numericKey: '2' }, 'dlcpsecondnumericKey,2'], [SET_METRIC_TYPE, 'important_org_ids', 'none', { numericKey: '2' }, 'simportant_org_idsnonenumericKey,2'], - ])('should return', (metricType, name, unit, tags, expected) => { + ])('should return (%s, %s, %s, %s) -> %s', (metricType, name, unit, tags, expected) => { expect(getBucketKey(metricType, name, unit, tags)).toEqual(expected); }); diff --git a/packages/core/test/lib/prepareEvent.test.ts b/packages/core/test/lib/prepareEvent.test.ts index 0698aa15e447..0da220b07dcb 100644 --- a/packages/core/test/lib/prepareEvent.test.ts +++ b/packages/core/test/lib/prepareEvent.test.ts @@ -11,6 +11,7 @@ import type { import { GLOBAL_OBJ, createStackParser } from '@sentry/utils'; import { getGlobalScope, getIsolationScope } from '../../src'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { Scope } from '../../src/scope'; import { applyDebugIds, @@ -197,7 +198,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(); @@ -242,9 +243,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; @@ -326,8 +327,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; @@ -490,7 +491,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 33c89a2e9eb5..0836546664bd 100644 --- a/packages/core/test/lib/scope.test.ts +++ b/packages/core/test/lib/scope.test.ts @@ -8,6 +8,7 @@ import { withScope, } from '../../src'; +import { beforeEach, describe, expect, it, test, vi } from 'vitest'; import { Scope } from '../../src/scope'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; import { clearGlobalScope } from './clear-global-scope'; @@ -347,7 +348,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 => { @@ -365,7 +366,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); @@ -571,7 +572,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; @@ -600,7 +601,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; @@ -615,7 +616,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; @@ -632,7 +633,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; @@ -650,7 +651,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; @@ -669,7 +670,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; @@ -695,7 +696,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; @@ -708,7 +709,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; @@ -726,7 +727,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; @@ -744,7 +745,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; @@ -764,7 +765,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; @@ -789,7 +790,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; @@ -804,7 +805,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; @@ -861,30 +862,35 @@ describe('withScope()', () => { getGlobalScope().clear(); }); - it('will make the passed scope the active scope within the callback', done => { + it('makes the passed scope the active scope within the callback', () => { + expect.assertions(1); + withScope(scope => { expect(getCurrentScope()).toBe(scope); - done(); }); }); - it('will pass a scope that is different from the current active isolation scope', done => { + it('passes a scope that is different from the current active isolation scope', () => { + expect.assertions(1); + 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 => { + it('always makes the inner most passed scope the current isolation scope when nesting calls', () => { + expect.assertions(1); + withIsolationScope(_scope1 => { withIsolationScope(scope2 => { expect(getIsolationScope()).toBe(scope2); - done(); }); }); }); - it('forks the scope when not passing any scope', done => { + it('forks the scope when not passing any scope', () => { + expect.assertions(3); + const initialScope = getCurrentScope(); initialScope.setTag('aa', 'aa'); @@ -893,11 +899,12 @@ describe('withScope()', () => { 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 => { + it('forks the scope when passing undefined', () => { + expect.assertions(3); + const initialScope = getCurrentScope(); initialScope.setTag('aa', 'aa'); @@ -906,11 +913,12 @@ describe('withScope()', () => { 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 => { + it('sets the passed in scope as active scope', () => { + expect.assertions(2); + const initialScope = getCurrentScope(); initialScope.setTag('aa', 'aa'); @@ -919,7 +927,6 @@ describe('withScope()', () => { withScope(customScope, scope => { expect(getCurrentScope()).toBe(customScope); expect(scope).toBe(customScope); - done(); }); }); }); @@ -931,58 +938,64 @@ describe('withIsolationScope()', () => { getGlobalScope().clear(); }); - it('will make the passed isolation scope the active isolation scope within the callback', done => { + it('makes the passed isolation scope the active isolation scope within the callback', () => { + expect.assertions(1); + withIsolationScope(scope => { expect(getIsolationScope()).toBe(scope); - done(); }); }); - it('will pass an isolation scope that is different from the current active scope', done => { + it('passes an isolation scope that is different from the current active scope', () => { + expect.assertions(1); + withIsolationScope(scope => { expect(getCurrentScope()).not.toBe(scope); - done(); }); }); - it('will always make the inner most passed scope the current scope when nesting calls', done => { + it('always makes the inner most passed scope the current scope when nesting calls', () => { + expect.assertions(1); + 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 => { + it('does not fork the isolation scope when not passing any isolation scope', () => { + expect.assertions(2); + const isolationScope = getIsolationScope(); withIsolationScope(scope => { expect(getIsolationScope()).toBe(scope); expect(scope).toBe(isolationScope); - done(); }); }); - it('does not fork isolation scope when passing undefined', done => { + it('does not fork isolation scope when passing undefined', () => { + expect.assertions(2); + const isolationScope = getIsolationScope(); withIsolationScope(undefined, scope => { expect(getIsolationScope()).toBe(scope); expect(scope).toBe(isolationScope); - done(); }); }); - it('ignores passed in isolation scope', done => { + it('ignores passed in isolation scope', () => { + expect.assertions(2); + const isolationScope = getIsolationScope(); const customIsolationScope = new Scope(); 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 74213cd8d99f..6a486397405e 100644 --- a/packages/core/test/lib/sdk.test.ts +++ b/packages/core/test/lib/sdk.test.ts @@ -1,6 +1,8 @@ import type { Client, Integration } from '@sentry/types'; import { captureCheckIn, getCurrentScope, setCurrentClient } from '../../src'; +import type { Mock } from 'vitest'; +import { beforeEach, describe, expect, it, test, vi } from 'vitest'; import { installedIntegrations } from '../../src/integration'; import { initAndBind } from '../../src/sdk'; import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; @@ -12,7 +14,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 +34,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 +43,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/serverruntimeclient.test.ts b/packages/core/test/lib/serverruntimeclient.test.ts index 8b149f7f2aaa..a73d9fe8bc08 100644 --- a/packages/core/test/lib/serverruntimeclient.test.ts +++ b/packages/core/test/lib/serverruntimeclient.test.ts @@ -1,5 +1,6 @@ import type { Event, EventHint } from '@sentry/types'; +import { describe, expect, it, test, vi } from 'vitest'; import { createTransport } from '../../src'; import type { ServerRuntimeClientOptions } from '../../src/server-runtime-client'; import { ServerRuntimeClient } from '../../src/server-runtime-client'; @@ -77,7 +78,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' }, @@ -147,7 +148,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' }); diff --git a/packages/core/test/lib/session.test.ts b/packages/core/test/lib/session.test.ts index 41eb0c234d13..09b07bf047b9 100644 --- a/packages/core/test/lib/session.test.ts +++ b/packages/core/test/lib/session.test.ts @@ -3,6 +3,8 @@ import { timestampInSeconds } from '@sentry/utils'; import { closeSession, makeSession, updateSession } from '../../src/session'; +import { describe, expect, it, test } from 'vitest'; + describe('Session', () => { it('initializes with the proper defaults', () => { const newSession = makeSession(); diff --git a/packages/core/test/lib/sessionflusher.test.ts b/packages/core/test/lib/sessionflusher.test.ts index 808ba6308069..13bf1ef7a628 100644 --- a/packages/core/test/lib/sessionflusher.test.ts +++ b/packages/core/test/lib/sessionflusher.test.ts @@ -2,20 +2,23 @@ import type { Client } from '@sentry/types'; import { SessionFlusher } from '../../src/sessionflusher'; +import type { Mock } from 'vitest'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; + describe('Session Flusher', () => { - let sendSession: jest.Mock; + let sendSession: Mock; let mockClient: Client; beforeEach(() => { - jest.useFakeTimers(); - sendSession = jest.fn(() => Promise.resolve({ status: 'success' })); + vi.useFakeTimers(); + sendSession = vi.fn(() => Promise.resolve({ status: 'success' })); mockClient = { sendSession, } as unknown as Client; }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); test('test incrementSessionStatusCount updates the internal SessionFlusher state', () => { @@ -56,27 +59,27 @@ describe('Session Flusher', () => { test('flush is called every 60 seconds after initialisation of an instance of SessionFlusher', () => { const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' }); - const flusherFlushFunc = jest.spyOn(flusher, 'flush'); - jest.advanceTimersByTime(59000); + const flusherFlushFunc = vi.spyOn(flusher, 'flush'); + vi.advanceTimersByTime(59000); expect(flusherFlushFunc).toHaveBeenCalledTimes(0); - jest.advanceTimersByTime(2000); + vi.advanceTimersByTime(2000); expect(flusherFlushFunc).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(58000); + vi.advanceTimersByTime(58000); expect(flusherFlushFunc).toHaveBeenCalledTimes(1); - jest.advanceTimersByTime(2000); + vi.advanceTimersByTime(2000); expect(flusherFlushFunc).toHaveBeenCalledTimes(2); }); test('sendSessions is called on flush if sessions were captured', () => { const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' }); - const flusherFlushFunc = jest.spyOn(flusher, 'flush'); + const flusherFlushFunc = vi.spyOn(flusher, 'flush'); const date = new Date('2021-04-08T12:18:23.043Z'); (flusher as any)._incrementSessionStatusCount('ok', date); (flusher as any)._incrementSessionStatusCount('ok', date); expect(sendSession).toHaveBeenCalledTimes(0); - jest.advanceTimersByTime(61000); + vi.advanceTimersByTime(61000); expect(flusherFlushFunc).toHaveBeenCalledTimes(1); expect(sendSession).toHaveBeenCalledWith( @@ -89,10 +92,10 @@ describe('Session Flusher', () => { test('sendSessions is not called on flush if no sessions were captured', () => { const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' }); - const flusherFlushFunc = jest.spyOn(flusher, 'flush'); + const flusherFlushFunc = vi.spyOn(flusher, 'flush'); expect(sendSession).toHaveBeenCalledTimes(0); - jest.advanceTimersByTime(61000); + vi.advanceTimersByTime(61000); expect(flusherFlushFunc).toHaveBeenCalledTimes(1); expect(sendSession).toHaveBeenCalledTimes(0); }); @@ -105,7 +108,7 @@ describe('Session Flusher', () => { test('calling close on SessionFlusher will force call flush', () => { const flusher = new SessionFlusher(mockClient, { release: '1.0.x' }); - const flusherFlushFunc = jest.spyOn(flusher, 'flush'); + const flusherFlushFunc = vi.spyOn(flusher, 'flush'); const date = new Date('2021-04-08T12:18:23.043Z'); (flusher as any)._incrementSessionStatusCount('ok', date); (flusher as any)._incrementSessionStatusCount('ok', date); diff --git a/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts b/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts index 095416d929df..4ec61a45d50d 100644 --- a/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts +++ b/packages/core/test/lib/tracing/dynamicSamplingContext.test.ts @@ -1,4 +1,5 @@ import type { Span, SpanContextData, TransactionSource } from '@sentry/types'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, @@ -17,7 +18,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 3e3f85ef73b7..005968413412 100644 --- a/packages/core/test/lib/tracing/errors.test.ts +++ b/packages/core/test/lib/tracing/errors.test.ts @@ -1,16 +1,17 @@ import type { HandlerDataError, HandlerDataUnhandledRejection } from '@sentry/types'; import { setCurrentClient, spanToJSON, startInactiveSpan, startSpan } from '../../../src'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; import { _resetErrorsInstrumented, registerSpanErrorInstrumentation } from '../../../src/tracing/errors'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; -const mockAddGlobalErrorInstrumentationHandler = jest.fn(); -const mockAddGlobalUnhandledRejectionInstrumentationHandler = jest.fn(); +const mockAddGlobalErrorInstrumentationHandler = vi.fn(); +const mockAddGlobalUnhandledRejectionInstrumentationHandler = vi.fn(); let mockErrorCallback: (data: HandlerDataError) => void = () => {}; let mockUnhandledRejectionCallback: (data: HandlerDataUnhandledRejection) => void = () => {}; -jest.mock('@sentry/utils', () => { - const actual = jest.requireActual('@sentry/utils'); +vi.mock('@sentry/utils', async () => { + const actual = await vi.importActual('@sentry/utils'); return { ...actual, addGlobalErrorInstrumentationHandler: (callback: () => void) => { diff --git a/packages/core/test/lib/tracing/idleSpan.test.ts b/packages/core/test/lib/tracing/idleSpan.test.ts index ff45938646a1..c3044916df96 100644 --- a/packages/core/test/lib/tracing/idleSpan.test.ts +++ b/packages/core/test/lib/tracing/idleSpan.test.ts @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; import type { Event, Span } from '@sentry/types'; @@ -22,7 +23,7 @@ const dsn = 'https://123@sentry.io/42'; describe('startIdleSpan', () => { beforeEach(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); getCurrentScope().clear(); getIsolationScope().clear(); @@ -35,7 +36,7 @@ describe('startIdleSpan', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('sets & unsets the idle span on the scope', () => { @@ -46,7 +47,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); idleSpan!.end(); - jest.runAllTimers(); + vi.runAllTimers(); expect(getActiveSpan()).toBe(undefined); }); @@ -73,13 +74,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); @@ -87,7 +88,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(); @@ -95,14 +96,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; }); @@ -118,7 +119,7 @@ describe('startIdleSpan', () => { // We want to accomodate 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 }); @@ -129,8 +130,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({ @@ -156,7 +157,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; }); @@ -196,8 +197,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); @@ -236,7 +237,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; }); @@ -273,7 +274,7 @@ describe('startIdleSpan', () => { startTime: baseTimeInSeconds + 4, }); - jest.runOnlyPendingTimers(); + vi.runOnlyPendingTimers(); expect(regularSpan.isRecording()).toBe(false); expect(idleSpan.isRecording()).toBe(false); @@ -325,7 +326,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([ @@ -343,7 +344,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(); @@ -355,7 +356,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; }); @@ -366,7 +367,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( @@ -376,7 +377,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; }); @@ -387,7 +388,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( @@ -397,7 +398,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; }); @@ -408,7 +409,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( @@ -418,7 +419,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; }); @@ -430,15 +431,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( @@ -448,7 +449,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; }); @@ -460,7 +461,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( @@ -473,7 +474,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(); }); @@ -483,7 +484,7 @@ describe('startIdleSpan', () => { startInactiveSpan({ name: 'span' }); - jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + vi.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); expect(spanToJSON(idleSpan).timestamp).toBeUndefined(); }); @@ -494,11 +495,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(); }); @@ -510,11 +511,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(); }); @@ -532,12 +533,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(); }); @@ -553,26 +554,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(); }); @@ -583,16 +584,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(); }); @@ -602,16 +603,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(); }); @@ -619,7 +620,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(); }); @@ -628,17 +629,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(); }); }); @@ -659,7 +660,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); - jest.runAllTimers(); + vi.runAllTimers(); expect(spanToJSON(idleSpan!).timestamp).toBe(1100); }); @@ -679,7 +680,7 @@ describe('startIdleSpan', () => { expect(getActiveSpan()).toBe(idleSpan); - jest.runAllTimers(); + vi.runAllTimers(); expect(spanToJSON(idleSpan!).timestamp).toBe(1030); }); @@ -699,7 +700,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 d5643c3d3651..dc10b7567e6b 100644 --- a/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts +++ b/packages/core/test/lib/tracing/sentryNonRecordingSpan.test.ts @@ -1,4 +1,5 @@ import type { Span } from '@sentry/types'; +import { describe, expect, it } from 'vitest'; import { SPAN_STATUS_ERROR } from '../../../src/tracing'; import { SentryNonRecordingSpan } from '../../../src/tracing/sentryNonRecordingSpan'; import { TRACE_FLAG_NONE, spanIsSampled, spanToJSON } from '../../../src/utils/spanUtils'; diff --git a/packages/core/test/lib/tracing/sentrySpan.test.ts b/packages/core/test/lib/tracing/sentrySpan.test.ts index 9698ab5e3398..48cd8dc7ed48 100644 --- a/packages/core/test/lib/tracing/sentrySpan.test.ts +++ b/packages/core/test/lib/tracing/sentrySpan.test.ts @@ -1,4 +1,5 @@ import { timestampInSeconds } from '@sentry/utils'; +import { describe, expect, it, test, vi } from 'vitest'; import { setCurrentClient } from '../../../src'; import { SentrySpan } from '../../../src/tracing/sentrySpan'; import { SPAN_STATUS_ERROR } from '../../../src/tracing/spanstatus'; @@ -101,7 +102,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', @@ -125,7 +126,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', @@ -136,7 +137,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, @@ -149,7 +150,7 @@ describe('SentrySpan', () => { }); test('does not send the span if `beforeSendSpan` drops the span', () => { - const beforeSendSpan = jest.fn(() => null); + const beforeSendSpan = vi.fn(() => null); const client = new TestClient( getDefaultTestClientOptions({ dsn: 'https://username@domain/123', @@ -159,9 +160,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, 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 fe58ce6f9f7d..82dac553bf7d 100644 --- a/packages/core/test/lib/tracing/trace.test.ts +++ b/packages/core/test/lib/tracing/trace.test.ts @@ -1,4 +1,5 @@ import type { Event, Span, StartSpanOptions } from '@sentry/types'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, @@ -12,6 +13,7 @@ import { spanToJSON, withScope, } from '../../../src'; + import { getAsyncContextStrategy } from '../../../src/asyncContext'; import { SentrySpan, @@ -53,7 +55,7 @@ describe('startSpan', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); describe.each([ @@ -476,7 +478,7 @@ describe('startSpan', () => { }); it('samples with a tracesSampler', () => { - const tracesSampler = jest.fn(() => { + const tracesSampler = vi.fn(() => { return true; }); @@ -503,7 +505,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({ @@ -553,7 +555,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; @@ -929,7 +931,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; @@ -1238,7 +1240,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({ @@ -1295,7 +1297,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; @@ -1458,7 +1460,7 @@ describe('getActiveSpan', () => { const carrier = getMainCarrier(); - const customFn = jest.fn(() => { + const customFn = vi.fn(() => { return staticSpan; }) as typeof getActiveSpan; @@ -1525,7 +1527,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; @@ -1557,7 +1559,7 @@ describe('span hooks', () => { }); afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); it('correctly emits span hooks', () => { @@ -1608,7 +1610,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 a8198ce38b3d..4fb3773d8249 100644 --- a/packages/core/test/lib/transports/base.test.ts +++ b/packages/core/test/lib/transports/base.test.ts @@ -1,6 +1,7 @@ import type { AttachmentItem, EventEnvelope, EventItem, TransportMakeRequestResponse } from '@sentry/types'; import type { PromiseBuffer } from '@sentry/utils'; import { createEnvelope, resolvedSyncPromise, serializeEnvelope } from '@sentry/utils'; +import { describe, expect, it, vi } from 'vitest'; import { createTransport } from '../../../src/transports/base'; @@ -37,8 +38,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 */ @@ -93,11 +94,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); @@ -108,7 +109,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); @@ -157,7 +158,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); @@ -207,7 +208,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); @@ -271,7 +272,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 4ddde08437f2..0323f2ee3e49 100644 --- a/packages/core/test/lib/transports/multiplexed.test.ts +++ b/packages/core/test/lib/transports/multiplexed.test.ts @@ -12,6 +12,8 @@ import { createClientReportEnvelope, createEnvelope, dsnFromString, parseEnvelop import { createTransport, getEnvelopeEndpointWithUrlEncodedAuth, makeMultiplexedTransport } from '../../../src'; import { eventFromEnvelope } from '../../../src/transports/multiplexed'; +import { describe, expect, it, vi } from 'vitest'; + const DSN1 = 'https://1234@5678.ingest.sentry.io/4321'; const DSN1_URL = getEnvelopeEndpointWithUrlEncodedAuth(dsnFromString(DSN1)!); @@ -88,7 +90,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); @@ -102,7 +104,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 ea3fa13ffd69..736002a95d7e 100644 --- a/packages/core/test/lib/transports/offline.test.ts +++ b/packages/core/test/lib/transports/offline.test.ts @@ -17,6 +17,7 @@ import { parseEnvelope, } from '@sentry/utils'; +import { describe, expect, it } from 'vitest'; import { createTransport } from '../../../src'; import type { CreateOfflineStore, OfflineTransportOptions } from '../../../src/transports/offline'; import { START_DELAY, makeOfflineTransport } from '../../../src/transports/offline'; @@ -410,7 +411,6 @@ describe('makeOfflineTransport', () => { START_DELAY + 2_000, ); - // eslint-disable-next-line jest/no-disabled-tests it.skip( 'Follows the Retry-After header', async () => { diff --git a/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts b/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts index e6370931f4cf..5bd797255ec0 100644 --- a/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts +++ b/packages/core/test/lib/utils/applyScopeDataToEvent.test.ts @@ -7,6 +7,8 @@ import { mergeScopeData, } from '../../../src/utils/applyScopeDataToEvent'; +import { describe, expect, it } from 'vitest'; + describe('mergeArray', () => { it.each([ [[], [], undefined], diff --git a/packages/core/test/lib/utils/handleCallbackErrors.test.ts b/packages/core/test/lib/utils/handleCallbackErrors.test.ts index 3c6bb1e19302..efa632d62a4a 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 successfuly 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 a03ff25c9be9..bfec89fc74af 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 { hasTracingEnabled } from '../../../src'; describe('hasTracingEnabled', () => { diff --git a/packages/core/test/lib/utils/isSentryRequestUrl.test.ts b/packages/core/test/lib/utils/isSentryRequestUrl.test.ts index b223f856b95e..1c4c059beead 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 '@sentry/types'; +import { describe, expect, it } from 'vitest'; import { isSentryRequestUrl } from '../../../src'; describe('isSentryRequestUrl', () => { 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 413ba8043c49..4c5538f1854a 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 '@sentry/types'; +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/spanUtils.test.ts b/packages/core/test/lib/utils/spanUtils.test.ts index 2a4850947e80..ec03d4cb5e88 100644 --- a/packages/core/test/lib/utils/spanUtils.test.ts +++ b/packages/core/test/lib/utils/spanUtils.test.ts @@ -16,6 +16,8 @@ import type { OpenTelemetrySdkTraceBaseSpan } from '../../../src/utils/spanUtils import { getRootSpan, spanIsSampled, spanTimeInputToSeconds, spanToJSON } from '../../../src/utils/spanUtils'; import { TestClient, getDefaultTestClientOptions } from '../../mocks/client'; +import { beforeEach, describe, expect, it, test } from 'vitest'; + describe('spanToTraceHeader', () => { test('simple', () => { const span = new SentrySpan(); diff --git a/packages/core/test/lib/utils/traceData.test.ts b/packages/core/test/lib/utils/traceData.test.ts index a6fb3c57814e..0f16fc881a40 100644 --- a/packages/core/test/lib/utils/traceData.test.ts +++ b/packages/core/test/lib/utils/traceData.test.ts @@ -3,6 +3,7 @@ import * as SentryCoreCurrentScopes from '../../../src/currentScopes'; import * as SentryCoreTracing from '../../../src/tracing'; import * as SentryCoreSpanUtils from '../../../src/utils/spanUtils'; +import { describe, expect, it, vi } from 'vitest'; import { isValidBaggageString } from '../../../src/utils/traceData'; const TRACE_FLAG_SAMPLED = 1; @@ -24,11 +25,11 @@ const mockedScope = { describe('getTraceData', () => { it('returns the tracing data from the span, if a span is available', () => { { - jest.spyOn(SentryCoreTracing, 'getDynamicSamplingContextFromSpan').mockReturnValueOnce({ + vi.spyOn(SentryCoreTracing, 'getDynamicSamplingContextFromSpan').mockReturnValueOnce({ environment: 'production', }); - jest.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => mockedSpan); - jest.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce(() => mockedScope); + vi.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => mockedSpan); + vi.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce(() => mockedScope); const data = getTraceData(); @@ -40,8 +41,8 @@ describe('getTraceData', () => { }); it('returns propagationContext DSC data if no span is available', () => { - jest.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => undefined); - jest.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce( + vi.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => undefined); + vi.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce( () => ({ getPropagationContext: () => ({ @@ -56,7 +57,7 @@ describe('getTraceData', () => { }), }) as any, ); - jest.spyOn(SentryCoreCurrentScopes, 'getClient').mockImplementationOnce(() => mockedClient); + vi.spyOn(SentryCoreCurrentScopes, 'getClient').mockImplementationOnce(() => mockedClient); const traceData = getTraceData(); @@ -67,13 +68,13 @@ describe('getTraceData', () => { }); it('returns only the `sentry-trace` value if no DSC is available', () => { - jest.spyOn(SentryCoreTracing, 'getDynamicSamplingContextFromClient').mockReturnValueOnce({ + vi.spyOn(SentryCoreTracing, 'getDynamicSamplingContextFromClient').mockReturnValueOnce({ trace_id: '', public_key: undefined, }); // @ts-expect-error - we don't need to provide all the properties - jest.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => ({ + vi.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => ({ isRecording: () => true, spanContext: () => { return { @@ -84,8 +85,8 @@ describe('getTraceData', () => { }, })); - jest.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce(() => mockedScope); - jest.spyOn(SentryCoreCurrentScopes, 'getClient').mockImplementationOnce(() => mockedClient); + vi.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce(() => mockedScope); + vi.spyOn(SentryCoreCurrentScopes, 'getClient').mockImplementationOnce(() => mockedClient); const traceData = getTraceData(); @@ -95,13 +96,13 @@ describe('getTraceData', () => { }); it('returns only the `sentry-trace` tag if no DSC is available without a client', () => { - jest.spyOn(SentryCoreTracing, 'getDynamicSamplingContextFromClient').mockReturnValueOnce({ + vi.spyOn(SentryCoreTracing, 'getDynamicSamplingContextFromClient').mockReturnValueOnce({ trace_id: '', public_key: undefined, }); // @ts-expect-error - we don't need to provide all the properties - jest.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => ({ + vi.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => ({ isRecording: () => true, spanContext: () => { return { @@ -111,8 +112,8 @@ describe('getTraceData', () => { }; }, })); - jest.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce(() => mockedScope); - jest.spyOn(SentryCoreCurrentScopes, 'getClient').mockImplementationOnce(() => undefined); + vi.spyOn(SentryCoreCurrentScopes, 'getCurrentScope').mockImplementationOnce(() => mockedScope); + vi.spyOn(SentryCoreCurrentScopes, 'getClient').mockImplementationOnce(() => undefined); const traceData = getTraceData(); @@ -124,7 +125,7 @@ describe('getTraceData', () => { it('returns an empty object if the `sentry-trace` value is invalid', () => { // @ts-expect-error - we don't need to provide all the properties - jest.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => ({ + vi.spyOn(SentryCoreSpanUtils, 'getActiveSpan').mockImplementationOnce(() => ({ isRecording: () => true, spanContext: () => { return { diff --git a/packages/core/tsconfig.test.json b/packages/core/tsconfig.test.json index 6fde53bec436..dddd57894b34 100644 --- a/packages/core/tsconfig.test.json +++ b/packages/core/tsconfig.test.json @@ -6,8 +6,6 @@ "compilerOptions": { "lib": ["DOM", "ES2018"], // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["node", "jest"] - - // other package-specific, test-specific options + "types": ["node"] } } diff --git a/packages/core/vite.config.ts b/packages/core/vite.config.ts new file mode 100644 index 000000000000..6383ee08a19d --- /dev/null +++ b/packages/core/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vitest/config'; +import baseConfig from '../../vite/vite.config'; + +export default defineConfig({ + ...baseConfig, + test: { + ...baseConfig.test, + typecheck: { + tsconfig: './tsconfig.test.json', + }, + }, +});