Skip to content

Commit

Permalink
chore: Migrate from jest to vitest
Browse files Browse the repository at this point in the history
Approximately x2 speedup in execution and more modern API ^^
  • Loading branch information
MorevM committed Mar 23, 2024
1 parent 64a76c3 commit 2325013
Show file tree
Hide file tree
Showing 42 changed files with 1,084 additions and 1,323 deletions.
11 changes: 10 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
module.exports = {
root: true,
extends: ['@morev/eslint-config/preset/common'],
extends: [
'@morev/eslint-config/preset/common',
'@morev/eslint-config/preset/vitest',
],
rules: {},
overrides: [
{
files: ['*.cjs'],
extends: ['@morev/eslint-config/node'],
},
],
};
21 changes: 0 additions & 21 deletions jest.config.ts

This file was deleted.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
"prepare": "lefthook install",
"vscode-settings": "cp .vscode/settings.template.json .vscode/settings.json",
"build": "rm -rf dist && tsup",
"test": "jest",
"test:dev": "jest --watch",
"test": "vitest",
"test:dev": "vitest --watch",
"lint": "eslint \"**/*.{js,ts,json,json5,jsonc,yml,yaml,md}\"",
"lint:fix": "eslint \"**/*.{js,ts,json,json5,jsonc,yml,yaml,md}\" --fix",
"release": "release-it --disable-metrics"
Expand All @@ -63,20 +63,20 @@
},
"devDependencies": {
"@morev/commitlint-config": "^0.2.2",
"@morev/eslint-config": "^29.0.0",
"@morev/eslint-config": "^31.0.0",
"@release-it/conventional-changelog": "^8.0.1",
"@total-typescript/ts-reset": "^0.5.1",
"@types/jest": "^29.5.11",
"@types/node": "^20.11.24",
"@vitest/coverage-v8": "^1.4.0",
"eslint": "^8.57.0",
"jest": "^29.7.0",
"jest-date": "^1.1.6",
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^24.0.0",
"lefthook": "^1.6.4",
"release-it": "^17.1.1",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"tsup": "^8.0.2",
"typescript": "^5.3.3"
"typescript": "^5.3.3",
"vitest": "^1.4.0"
}
}
1 change: 0 additions & 1 deletion src/arrays/array-sample/array-sample.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/require-array-sort-compare */
/* eslint-disable jest/no-conditional-in-test */
import { randomInteger } from '../../numbers';
import { deepEqual } from '../../objects';
import { arrayOfLength } from '../array-of-length/array-of-length';
Expand Down
4 changes: 2 additions & 2 deletions src/arrays/array-shuffle/array-shuffle.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/* eslint-disable @typescript-eslint/require-array-sort-compare */
import { deepEqual } from '../../objects';
import { arrayOfLength } from '../array-of-length/array-of-length';
import { arrayShuffle } from './array-shuffle';

const input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

describe('array-shuffle', () => {
it('Returns the shuffled array', () => {
const TIMES = 100000;
const result = callTimes(TIMES, () => arrayShuffle(input));
const result = arrayOfLength(TIMES, () => arrayShuffle(input));

const sameOrderCount = result.reduce((acc, curr) => {
// eslint-disable-next-line jest/no-conditional-in-test
return acc + (deepEqual(input, curr) ? 1 : 0);
}, 0);

Expand Down
1 change: 0 additions & 1 deletion src/colors/rgb-to-hex/rgb-to-hex.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable jest/max-nested-describe */
import { rgbToHex } from './rgb-to-hex';

describe('rgb-to-hex', () => {
Expand Down
6 changes: 3 additions & 3 deletions src/dates/days-in-month/days-in-month.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { daysInMonth } from './days-in-month';

describe('days-in-month', () => {
beforeAll(() => {
jest.useFakeTimers({ now: new Date(2020, 1, 1) });
vi.useFakeTimers({ now: new Date(2020, 1, 1) });
});

it('Returns correct count of days in month with `year` passed', () => {
Expand All @@ -13,11 +13,11 @@ describe('days-in-month', () => {
});

it('Returns correct count of days in month with no `year` passed', () => {
jest.useFakeTimers({ now: new Date(2020, 1, 1) });
vi.useFakeTimers({ now: new Date(2020, 1, 1) });

expect(daysInMonth(0)).toBe(31);
expect(daysInMonth(1)).toBe(29);

jest.useRealTimers();
vi.useRealTimers();
});
});
2 changes: 1 addition & 1 deletion src/dates/parse-date/parse-date.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { parseDate } from './parse-date';

// There is a static timezone offset defined in `utils/jest.global-setup.ts`.
// There is a static timezone offset defined in `utils/vitest.global-setup.ts`.
const TIMEZONE_OFFSET_AS_HOURS = 3;

describe('parse-date', () => {
Expand Down
78 changes: 26 additions & 52 deletions src/dates/random-date/random-date.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable jest/no-conditional-in-test */
import { isDate } from '../../guards';
import { randomDate } from './random-date';

Expand All @@ -7,46 +6,31 @@ const DEATHDATE = new Date(2094, 5, 11); // <-- Pretty optimistic

describe('random-date', () => {
describe('Negative scenarios', () => {
it('Replaces invalid arguments with defaults and returns a Date', () => {
const result = callTimes(
100,
() => randomDate(
Math.random() > .5 ? new Date('foo') : null,
Math.random() > .5 ? new Date('foo') : null,
),
it('Replaces invalid arguments with defaults and returns a Date', { repeats: 1000 }, () => {
const date = randomDate(
Math.random() > .5 ? new Date('foo') : null,
Math.random() > .5 ? new Date('foo') : null,
);

for (let i = 0, l = result.length; i < l; i++) {
expect(isDate(result[i], true)).toBe(true);
expect(result[i]).toBeAfter(new Date(0));
expect(result[i]).toBeBefore(new Date());
}
expect(isDate(date, true)).toBe(true);
expect(date).toBeAfter(new Date(0));
expect(date).toBeBefore(new Date());
});

it('Replaces the first invalid / nulled argument with default and returns a Date', () => {
const result = callTimes(
100,
() => randomDate(Math.random() > .5 ? new Date('foo') : null, new Date(BIRTHDATE)),
);
it('Replaces the first invalid / nulled argument with default and returns a Date', { repeats: 1000 }, () => {
const date = randomDate(Math.random() > .5 ? new Date('foo') : null, new Date(BIRTHDATE));

for (let i = 0, l = result.length; i < l; i++) {
expect(isDate(result[i], true)).toBe(true);
expect(result[i]).toBeAfter(new Date(0));
expect(result[i]).toBeBefore(BIRTHDATE);
}
expect(isDate(date, true)).toBe(true);
expect(date).toBeAfter(new Date(0));
expect(date).toBeBefore(BIRTHDATE);
});

it('Replaces the second invalid / nulled argument with default and returns a Date', () => {
const result = callTimes(
100,
() => randomDate(new Date(BIRTHDATE), Math.random() > .5 ? new Date('foo') : null),
);
it('Replaces the second invalid / nulled argument with default and returns a Date', { repeats: 1000 }, () => {
const date = randomDate(new Date(BIRTHDATE), Math.random() > .5 ? new Date('foo') : null);

for (let i = 0, l = result.length; i < l; i++) {
expect(isDate(result[i], true)).toBe(true);
expect(result[i]).toBeAfter(BIRTHDATE);
expect(result[i]).toBeBefore(new Date());
}
expect(isDate(date, true)).toBe(true);
expect(date).toBeAfter(BIRTHDATE);
expect(date).toBeBefore(new Date());
});

describe('time (as tuple)', () => {
Expand Down Expand Up @@ -98,31 +82,21 @@ describe('random-date', () => {
});
});

it('Works propertly if `start` and `end` dates are equal', () => {
const result = callTimes(
100,
() => randomDate(BIRTHDATE, BIRTHDATE),
);
it('Works propertly if `start` and `end` dates are equal', { repeats: 1000 }, () => {
const date = randomDate(BIRTHDATE, BIRTHDATE);

for (let i = 0, l = result.length; i < l; i++) {
expect(isDate(result[i], true)).toBe(true);
expect(result[i].getTime()).toBeCloseTo(BIRTHDATE.getTime());
}
expect(isDate(date, true)).toBe(true);
expect(date.getTime()).toBeCloseTo(BIRTHDATE.getTime());
});
});

describe('Positive scenarios', () => {
it('Returns a random date between `start` and `end` dates', () => {
const result = callTimes(
100,
() => randomDate(BIRTHDATE, DEATHDATE),
);
it('Returns a random date between `start` and `end` dates', { repeats: 1000 }, () => {
const date = randomDate(BIRTHDATE, DEATHDATE);

for (let i = 0, l = result.length; i < l; i++) {
expect(isDate(result[i], true)).toBe(true);
expect(result[i]).toBeAfter(BIRTHDATE);
expect(result[i]).toBeBefore(DEATHDATE);
}
expect(isDate(date, true)).toBe(true);
expect(date).toBeAfter(BIRTHDATE);
expect(date).toBeBefore(DEATHDATE);
});

describe('time (as tuple)', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/dates/to-date/to-date.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { toDate } from './to-date';
// The utility function is actually a little wrapper under `parseDate` utility,
// so most tests are defined in `parseDate.test.ts`

// There is a static timezone offset defined in `utils/jest.global-setup.ts`.
// There is a static timezone offset defined in `utils/vitest.global-setup.ts`.
const TIMEZONE_OFFSET_AS_HOURS = 3;
const hours = 20;

Expand Down
4 changes: 2 additions & 2 deletions src/dom/get-document-size/get-document-size.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { getDocumentSize } from './get-document-size';

describe('get-document-size', () => {
beforeEach(() => {
jest.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 3000);
jest.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);
vi.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 3000);
vi.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);
});

it('Returns the document scroll width if `axis` argument value is `x`', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/dom/get-element-offset/get-element-offset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const mockGetBoundingClientRect = (el: Element, _options: { x: number; y: number
right: 0,
toJSON: () => {},
};
jest.spyOn(el, 'getBoundingClientRect')
vi.spyOn(el, 'getBoundingClientRect')
.mockImplementation(() => pseudoRect);
};

Expand Down
14 changes: 7 additions & 7 deletions src/dom/get-scroll-limit/get-scroll-limit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,34 @@ describe('get-scroll-limit', () => {
});

it('Returns the maximum scroll value by x-axis if `axis` argument value is `x`', () => {
jest.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 3000);
vi.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 3000);

expect(getScrollLimit('x')).toBe(3000 - 1920);
});

it('Returns the maximum scroll value by y-axis if `axis` argument value is `y`', () => {
jest.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);
vi.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);

expect(getScrollLimit('y')).toBe(6000 - 1080);
});

it('Returns the maximum scroll value by y-axis if `axis` argument is omitted', () => {
jest.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);
vi.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);

expect(getScrollLimit()).toBe(6000 - 1080);
});

it('Returns `0` if document scroll size is less than window size (typically because of scrollbar)', () => {
jest.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 1903);
jest.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 1063);
vi.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 1903);
vi.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 1063);

expect(getScrollLimit('x')).toBe(0);
expect(getScrollLimit('y')).toBe(0);
});

it('Returns both scroll limits if `axis` argument value is `both`', () => {
jest.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 3000);
jest.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);
vi.spyOn(document.body, 'scrollWidth', 'get').mockImplementation(() => 3000);
vi.spyOn(document.body, 'scrollHeight', 'get').mockImplementation(() => 6000);

expect(getScrollLimit('both')).toStrictEqual({ x: 3000 - 1920, y: 6000 - 1080 });
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('get-scrollable-ancestor', () => {
</div>
`);

// Jest won't parse `overflow`, so it's defined separately
// Vitest won't parse `overflow`, so it's defined separately
const style = document.createElement('style');
style.innerHTML = `
.scrollable-x { overflow-x: auto; }
Expand Down
2 changes: 1 addition & 1 deletion src/environment/is-dev/is-dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe('is-dev', () => {
const OLD_ENV = process.env;

beforeEach(() => {
jest.resetModules();
vi.resetModules();
process.env = { ...OLD_ENV };
});

Expand Down
4 changes: 2 additions & 2 deletions src/environment/is-firefox/is-firefox.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { isFirefox } from './is-firefox';

describe('is-firefox', () => {
it('Returns `true` if a Firefox browser is being used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0');

expect(isFirefox()).toBe(true);
});

it('Returns `false` if not a Firefox browser used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36');

expect(isFirefox()).toBe(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@ import { isInternetExplorer } from './is-internet-explorer';

describe('is-internet-explorer', () => {
it('Returns `true` if IE 11 is being used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko');

expect(isInternetExplorer()).toBe(true);
});

it('Returns `true` if IE 10 is being used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');

expect(isInternetExplorer()).toBe(true);
});

it('Returns `true` if IE 9 is being used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)');

expect(isInternetExplorer()).toBe(true);
});

it('Returns `true` if IE 8 is being used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue(' Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)');

expect(isInternetExplorer()).toBe(true);
});

it('Returns `false` if not a legacy Internet Explorer browser used', () => {
jest.spyOn(window.navigator, 'userAgent', 'get')
vi.spyOn(window.navigator, 'userAgent', 'get')
.mockReturnValue('Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36');

expect(isInternetExplorer()).toBe(false);
Expand Down
Loading

0 comments on commit 2325013

Please sign in to comment.