Skip to content

test(node): Migrate to vitest #15478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@
"clean": "rimraf build coverage sentry-node-*.tgz",
"fix": "eslint . --format stylish --fix",
"lint": "eslint . --format stylish",
"test": "yarn test:jest",
"test:jest": "jest",
"test:watch": "jest --watch",
"test": "yarn test:unit",
"test:unit": "vitest run",
"test:watch": "vitest --watch",
"yalc:publish": "yalc publish --push --sig"
},
"volta": {
Expand Down
175 changes: 90 additions & 85 deletions packages/node/test/cron.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import * as SentryCore from '@sentry/core';

import { type MockInstance, afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { cron } from '../src';
import type { CronJob, CronJobParams } from '../src/cron/cron';
import type { NodeCron, NodeCronOptions } from '../src/cron/node-cron';

describe('cron check-ins', () => {
let withMonitorSpy: jest.SpyInstance;
let withMonitorSpy: MockInstance;

beforeEach(() => {
withMonitorSpy = jest.spyOn(SentryCore, 'withMonitor');
withMonitorSpy = vi.spyOn(SentryCore, 'withMonitor');
});

afterEach(() => {
jest.restoreAllMocks();
vi.restoreAllMocks();
});

describe('cron', () => {
Expand Down Expand Up @@ -48,43 +49,45 @@ describe('cron check-ins', () => {
}
}

test('new CronJob()', done => {
expect.assertions(4);

const CronJobWithCheckIn = cron.instrumentCron(CronJobMock, 'my-cron-job');

new CronJobWithCheckIn(
'* * * Jan,Sep Sun',
() => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
timezone: 'America/Los_Angeles',
});
done();
},
undefined,
true,
'America/Los_Angeles',
);
});
test('new CronJob()', () =>
new Promise<void>(done => {
expect.assertions(4);

const CronJobWithCheckIn = cron.instrumentCron(CronJobMock, 'my-cron-job');

new CronJobWithCheckIn(
'* * * Jan,Sep Sun',
() => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
timezone: 'America/Los_Angeles',
});
done();
},
undefined,
true,
'America/Los_Angeles',
);
}));

test('CronJob.from()', done => {
expect.assertions(4);
test('CronJob.from()', () =>
new Promise<void>(done => {
expect.assertions(4);

const CronJobWithCheckIn = cron.instrumentCron(CronJobMock, 'my-cron-job');
const CronJobWithCheckIn = cron.instrumentCron(CronJobMock, 'my-cron-job');

CronJobWithCheckIn.from({
cronTime: '* * * Jan,Sep Sun',
onTick: () => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
});
done();
},
});
});
CronJobWithCheckIn.from({
cronTime: '* * * Jan,Sep Sun',
onTick: () => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
});
done();
},
});
}));

test('throws with multiple jobs same name', () => {
const CronJobWithCheckIn = cron.instrumentCron(CronJobMock, 'my-cron-job');
Expand All @@ -108,32 +111,33 @@ describe('cron check-ins', () => {
});

describe('node-cron', () => {
test('calls withMonitor', done => {
expect.assertions(5);

const nodeCron: NodeCron = {
schedule: (expression: string, callback: () => void, options?: NodeCronOptions): unknown => {
expect(expression).toBe('* * * Jan,Sep Sun');
expect(callback).toBeInstanceOf(Function);
expect(options?.name).toBe('my-cron-job');
return callback();
},
};

const cronWithCheckIn = cron.instrumentNodeCron(nodeCron);

cronWithCheckIn.schedule(
'* * * Jan,Sep Sun',
() => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
});
done();
},
{ name: 'my-cron-job' },
);
});
test('calls withMonitor', () =>
new Promise<void>(done => {
expect.assertions(5);

const nodeCron: NodeCron = {
schedule: (expression: string, callback: () => void, options?: NodeCronOptions): unknown => {
expect(expression).toBe('* * * Jan,Sep Sun');
expect(callback).toBeInstanceOf(Function);
expect(options?.name).toBe('my-cron-job');
return callback();
},
};

const cronWithCheckIn = cron.instrumentNodeCron(nodeCron);

cronWithCheckIn.schedule(
'* * * Jan,Sep Sun',
() => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
});
done();
},
{ name: 'my-cron-job' },
);
}));

test('throws without supplied name', () => {
const nodeCron: NodeCron = {
Expand All @@ -154,32 +158,33 @@ describe('cron check-ins', () => {
});

describe('node-schedule', () => {
test('calls withMonitor', done => {
expect.assertions(5);

class NodeScheduleMock {
scheduleJob(
nameOrExpression: string | Date | object,
expressionOrCallback: string | Date | object | (() => void),
callback: () => void,
): unknown {
expect(nameOrExpression).toBe('my-cron-job');
expect(expressionOrCallback).toBe('* * * Jan,Sep Sun');
expect(callback).toBeInstanceOf(Function);
return callback();
test('calls withMonitor', () =>
new Promise<void>(done => {
expect.assertions(5);

class NodeScheduleMock {
scheduleJob(
nameOrExpression: string | Date | object,
expressionOrCallback: string | Date | object | (() => void),
callback: () => void,
): unknown {
expect(nameOrExpression).toBe('my-cron-job');
expect(expressionOrCallback).toBe('* * * Jan,Sep Sun');
expect(callback).toBeInstanceOf(Function);
return callback();
}
}
}

const scheduleWithCheckIn = cron.instrumentNodeSchedule(new NodeScheduleMock());
const scheduleWithCheckIn = cron.instrumentNodeSchedule(new NodeScheduleMock());

scheduleWithCheckIn.scheduleJob('my-cron-job', '* * * Jan,Sep Sun', () => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
scheduleWithCheckIn.scheduleJob('my-cron-job', '* * * Jan,Sep Sun', () => {
expect(withMonitorSpy).toHaveBeenCalledTimes(1);
expect(withMonitorSpy).toHaveBeenLastCalledWith('my-cron-job', expect.anything(), {
schedule: { type: 'crontab', value: '* * * 1,9 0' },
});
done();
});
done();
});
});
}));

test('throws without crontab string', () => {
class NodeScheduleMock {
Expand Down
3 changes: 2 additions & 1 deletion packages/node/test/helpers/conditional.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parseSemver } from '@sentry/core';
import { it, test } from 'vitest';

const NODE_VERSION = parseSemver(process.versions.node).major;

Expand All @@ -8,7 +9,7 @@ const NODE_VERSION = parseSemver(process.versions.node).major;
* @param {{ min?: number; max?: number }} allowedVersion
* @return {*} {jest.Describe}
*/
export const conditionalTest = (allowedVersion: { min?: number; max?: number }): jest.It => {
export const conditionalTest = (allowedVersion: { min?: number; max?: number }) => {
if (!NODE_VERSION) {
return it.skip;
}
Expand Down
31 changes: 16 additions & 15 deletions packages/node/test/integration/breadcrumbs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { startSpan } from '@sentry/opentelemetry';
import { getClient } from '../../src/';
import type { NodeClient } from '../../src/sdk/client';

import { afterEach, describe, expect, it, vi } from 'vitest';
import { cleanupOtel, mockSdkInit } from '../helpers/mockSdkInit';

describe('Integration | breadcrumbs', () => {
const beforeSendTransaction = jest.fn(() => null);
const beforeSendTransaction = vi.fn(() => null);

afterEach(() => {
cleanupOtel();
});

describe('without tracing', () => {
it('correctly adds & retrieves breadcrumbs', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb });

Expand Down Expand Up @@ -50,8 +51,8 @@ describe('Integration | breadcrumbs', () => {
});

it('handles parallel scopes', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb });

Expand Down Expand Up @@ -96,8 +97,8 @@ describe('Integration | breadcrumbs', () => {
});

it('correctly adds & retrieves breadcrumbs', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb, beforeSendTransaction, tracesSampleRate: 1 });

Expand Down Expand Up @@ -141,8 +142,8 @@ describe('Integration | breadcrumbs', () => {
});

it('correctly adds & retrieves breadcrumbs for the current isolation span only', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb, beforeSendTransaction, tracesSampleRate: 1 });

Expand Down Expand Up @@ -193,8 +194,8 @@ describe('Integration | breadcrumbs', () => {
});

it('ignores scopes inside of root span', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb, beforeSendTransaction, tracesSampleRate: 1 });

Expand Down Expand Up @@ -234,8 +235,8 @@ describe('Integration | breadcrumbs', () => {
});

it('handles deep nesting of scopes', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb, beforeSendTransaction, tracesSampleRate: 1 });

Expand Down Expand Up @@ -292,8 +293,8 @@ describe('Integration | breadcrumbs', () => {
});

it('correctly adds & retrieves breadcrumbs in async spans', async () => {
const beforeSend = jest.fn(() => null);
const beforeBreadcrumb = jest.fn(breadcrumb => breadcrumb);
const beforeSend = vi.fn(() => null);
const beforeBreadcrumb = vi.fn(breadcrumb => breadcrumb);

mockSdkInit({ beforeSend, beforeBreadcrumb, beforeSendTransaction, tracesSampleRate: 1 });

Expand Down
7 changes: 4 additions & 3 deletions packages/node/test/integration/console.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import * as SentryCore from '@sentry/core';
import { resetInstrumentationHandlers } from '@sentry/core';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { getClient } from '../../src';
import type { NodeClient } from '../../src';
import { consoleIntegration } from '../../src/integrations/console';

const addBreadcrumbSpy = jest.spyOn(SentryCore, 'addBreadcrumb');
const addBreadcrumbSpy = vi.spyOn(SentryCore, 'addBreadcrumb');

jest.spyOn(console, 'log').mockImplementation(() => {
vi.spyOn(console, 'log').mockImplementation(() => {
// noop so that we don't spam the logs
});

afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
resetInstrumentationHandlers();
});

Expand Down
Loading
Loading