mirror of
https://github.com/directus/directus.git
synced 2026-02-15 16:05:06 -05:00
Finish switch from Jest to Vitest in API (#16263)
* build: ➕ add vitest and update test scripts * build: 🔧 add vitest config * build: ✅ Migrate tests to vitest Remove jest references from test api test files and replace with vitest equivalents. Tests: 13 tests are failing. * build: 🚚 move vite.config.ts to api/src folder * build: 🔥 remove unused vitest.config from api root * build: ✅ import vitest modules for tests * build: ✅ add type conversion for actual object * Finish switch from Jest to Vitest in API * Replace some leftovers * Load "sharp" before tests * Try with cjs * Temporary enable verbose reporter * Try with globalSetup * Fix path to globalSetup * Provide default export in globalSetup * Final clean-up * Remove @vitest/ui & update vitest to 0.25.0 * Add vitest c8 coverage dependency * Update vitest to v0.25.1 * Replace unnecessary Vitest workaround * Rework new tests * Resolve build errors Co-authored-by: Dorian C Brown <brown.3794@gmail.com> Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
This commit is contained in:
@@ -12,28 +12,29 @@ import {
|
||||
snapshotBeforeDeleteCollection,
|
||||
} from '../__utils__/snapshots';
|
||||
import { Snapshot } from '../types';
|
||||
import { describe, afterEach, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
jest.mock('../../src/database/index', () => {
|
||||
vi.mock('../../src/database/index', () => {
|
||||
return {
|
||||
getDatabaseClient: jest.fn().mockReturnValue('postgres'),
|
||||
getDatabaseClient: vi.fn().mockReturnValue('postgres'),
|
||||
};
|
||||
});
|
||||
jest.requireMock('../../src/database/index');
|
||||
vi.mock('../../src/database/index');
|
||||
|
||||
class Client_PG extends MockClient {}
|
||||
|
||||
describe('applySnapshot', () => {
|
||||
let db: jest.Mocked<Knex>;
|
||||
let db: Knex;
|
||||
let tracker: Tracker;
|
||||
|
||||
beforeEach(() => {
|
||||
db = knex({ client: Client_PG }) as jest.Mocked<Knex>;
|
||||
db = knex({ client: Client_PG });
|
||||
tracker = getTracker();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tracker.reset();
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Creating new collection(s)', () => {
|
||||
@@ -102,12 +103,14 @@ describe('applySnapshot', () => {
|
||||
};
|
||||
|
||||
// Stop call to db later on in apply-snapshot
|
||||
jest.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
|
||||
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
|
||||
// We are not actually testing that createOne works, just that is is called correctly
|
||||
const createOneCollectionSpy = jest
|
||||
const createOneCollectionSpy = vi
|
||||
.spyOn(CollectionsService.prototype, 'createOne')
|
||||
.mockImplementation(jest.fn());
|
||||
const createFieldSpy = jest.spyOn(FieldsService.prototype, 'createField').mockImplementation(jest.fn());
|
||||
.mockImplementation(vi.fn().mockReturnValue([]));
|
||||
const createFieldSpy = vi
|
||||
.spyOn(FieldsService.prototype, 'createField')
|
||||
.mockImplementation(vi.fn().mockReturnValue([]));
|
||||
|
||||
await applySnapshot(snapshotCreateCollectionNotNested, {
|
||||
database: db,
|
||||
@@ -251,12 +254,14 @@ describe('applySnapshot', () => {
|
||||
};
|
||||
|
||||
// Stop call to db later on in apply-snapshot
|
||||
jest.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
|
||||
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
|
||||
// We are not actually testing that createOne works, just that is is called correctly
|
||||
const createOneCollectionSpy = jest
|
||||
const createOneCollectionSpy = vi
|
||||
.spyOn(CollectionsService.prototype, 'createOne')
|
||||
.mockImplementation(jest.fn());
|
||||
const createFieldSpy = jest.spyOn(FieldsService.prototype, 'createField').mockImplementation(jest.fn());
|
||||
.mockImplementation(vi.fn().mockReturnValue([]));
|
||||
const createFieldSpy = vi
|
||||
.spyOn(FieldsService.prototype, 'createField')
|
||||
.mockImplementation(vi.fn().mockReturnValue([]));
|
||||
|
||||
await applySnapshot(snapshotCreateCollection, {
|
||||
database: db,
|
||||
@@ -285,11 +290,11 @@ describe('applySnapshot', () => {
|
||||
};
|
||||
|
||||
// Stop call to db later on in apply-snapshot
|
||||
jest.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
|
||||
vi.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(snapshotApplyTestSchema));
|
||||
// We are not actually testing that deleteOne works, just that is is called correctly
|
||||
const deleteOneCollectionSpy = jest
|
||||
const deleteOneCollectionSpy = vi
|
||||
.spyOn(CollectionsService.prototype, 'deleteOne')
|
||||
.mockImplementation(jest.fn());
|
||||
.mockImplementation(vi.fn().mockReturnValue([]));
|
||||
|
||||
await applySnapshot(snapshotToApply, {
|
||||
database: db,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { RequestHandler, NextFunction, Request, Response } from 'express';
|
||||
import type { RequestHandler, Request, Response } from 'express';
|
||||
import '../../src/types/express.d.ts';
|
||||
import asyncHandler from './async-handler';
|
||||
import { expect, vi, test } from 'vitest';
|
||||
|
||||
let mockRequest: Partial<Request & { token?: string }>;
|
||||
let mockResponse: Partial<Response>;
|
||||
const nextFunction: NextFunction = jest.fn();
|
||||
const nextFunction = vi.fn();
|
||||
|
||||
test('Wraps async middleware in Promise resolve that will catch rejects and pass them to the nextFn', async () => {
|
||||
const err = new Error('testing');
|
||||
@@ -13,7 +14,7 @@ test('Wraps async middleware in Promise resolve that will catch rejects and pass
|
||||
throw err;
|
||||
};
|
||||
|
||||
await asyncHandler(middleware)(mockRequest as Request, mockResponse as Response, nextFunction as NextFunction);
|
||||
await asyncHandler(middleware)(mockRequest as Request, mockResponse as Response, nextFunction);
|
||||
|
||||
expect(nextFunction).toHaveBeenCalledWith(err);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { calculateFieldDepth } from '../../src/utils/calculate-field-depth';
|
||||
import { test, expect } from 'vitest';
|
||||
|
||||
test('Calculates basic depth', () => {
|
||||
const filter = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { filterItems } from '../../src/utils/filter-items';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
|
||||
const items = [
|
||||
{
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { describe, expect, vi, test } from 'vitest';
|
||||
import { getAuthProviders } from '../../src/utils/get-auth-providers';
|
||||
|
||||
let factoryEnv: { [k: string]: any } = {};
|
||||
|
||||
jest.mock(
|
||||
'../../src/env',
|
||||
() =>
|
||||
new Proxy(
|
||||
{},
|
||||
{
|
||||
get(target, prop) {
|
||||
return factoryEnv[prop as string];
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
import { getAuthProviders } from '../../src/utils/get-auth-providers';
|
||||
vi.mock('../../src/env', () => ({
|
||||
default: new Proxy(
|
||||
{},
|
||||
{
|
||||
get(_target, prop) {
|
||||
return factoryEnv[prop as string];
|
||||
},
|
||||
}
|
||||
),
|
||||
}));
|
||||
|
||||
const scenarios = [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Request } from 'express';
|
||||
import { getCacheKey } from '../../src/utils/get-cache-key';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
|
||||
const restUrl = 'http://localhost/items/example';
|
||||
const graphQlUrl = 'http://localhost/graphql';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { getColumnPath, ColPathProps } from '../../src/utils/get-column-path';
|
||||
import { InvalidQueryException } from '../../src/exceptions';
|
||||
import { DeepPartial } from '@directus/shared/types';
|
||||
import { test, expect } from 'vitest';
|
||||
|
||||
/*
|
||||
{
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { getConfigFromEnv } from '../../src/utils/get-config-from-env';
|
||||
import { describe, test, expect, vi } from 'vitest';
|
||||
|
||||
jest.mock('../../src/env', () => ({
|
||||
OBJECT_BRAND__COLOR: 'purple',
|
||||
OBJECT_BRAND__HEX: '#6644FF',
|
||||
CAMELCASE_OBJECT__FIRST_KEY: 'firstValue',
|
||||
CAMELCASE_OBJECT__SECOND_KEY: 'secondValue',
|
||||
vi.mock('../../src/env', () => ({
|
||||
default: {
|
||||
OBJECT_BRAND__COLOR: 'purple',
|
||||
OBJECT_BRAND__HEX: '#6644FF',
|
||||
CAMELCASE_OBJECT__FIRST_KEY: 'firstValue',
|
||||
CAMELCASE_OBJECT__SECOND_KEY: 'secondValue',
|
||||
},
|
||||
}));
|
||||
|
||||
describe('get config from env', () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getRelationInfo } from '../../src/utils/get-relation-info';
|
||||
import { Relation, DeepPartial } from '@directus/shared/types';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
describe('getRelationInfo', () => {
|
||||
it('Errors on suspiciously long implicit $FOLLOW', () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getRelationType } from '../../src/utils/get-relation-type';
|
||||
import { Relation } from '@directus/shared/types';
|
||||
import { test, expect } from 'vitest';
|
||||
|
||||
test('Returns null if no relation object is included', () => {
|
||||
const result = getRelationType({ relation: null, collection: null, field: 'test' });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { stringByteSize } from '../../src/utils/get-string-byte-size';
|
||||
import { test, expect } from 'vitest';
|
||||
|
||||
test('Returns correct byte size for given input string', () => {
|
||||
expect(stringByteSize('test')).toBe(4);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import isDirectusJWT from '../../src/utils/is-directus-jwt';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { test, expect } from 'vitest';
|
||||
|
||||
test('Returns false for non JWT string', () => {
|
||||
const result = isDirectusJWT('test');
|
||||
|
||||
@@ -2,6 +2,7 @@ import { verifyAccessJWT } from '../../src/utils/jwt';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { InvalidTokenException, ServiceUnavailableException, TokenExpiredException } from '../../src/exceptions';
|
||||
import { DirectusTokenPayload } from '../../src/types';
|
||||
import { test, expect, vi } from 'vitest';
|
||||
|
||||
const payload: DirectusTokenPayload = { role: null, app_access: false, admin_access: false };
|
||||
const secret = 'test-secret';
|
||||
@@ -32,7 +33,7 @@ Object.entries(InvalidTokenCases).forEach(([title, token]) =>
|
||||
);
|
||||
|
||||
test(`Throws ServiceUnavailableException for unexpected error from jsonwebtoken`, () => {
|
||||
jest.spyOn(jwt, 'verify').mockImplementation(() => {
|
||||
vi.spyOn(jwt, 'verify').mockImplementation(() => {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { mergePermission } from '../../src/utils/merge-permissions';
|
||||
import { Permission, Filter } from '@directus/shared/types';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
const fullFilter = {} as Filter;
|
||||
const conditionalFilter = { user: { id: { _eq: '$CURRENT_USER' } } } as Filter;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { validateKeys } from '../../src/utils/validate-keys';
|
||||
import { SchemaOverview } from '@directus/shared/types';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const schema: SchemaOverview = {
|
||||
collections: {
|
||||
|
||||
Reference in New Issue
Block a user