feat(ci): replace jest with vitest [EE-6504] (#10997)
parent
4a19871fcc
commit
69c06bc756
|
@ -116,10 +116,9 @@ overrides:
|
|||
- files:
|
||||
- app/**/*.test.*
|
||||
extends:
|
||||
- 'plugin:jest/recommended'
|
||||
- 'plugin:jest/style'
|
||||
- 'plugin:vitest/recommended'
|
||||
env:
|
||||
'jest/globals': true
|
||||
'vitest/env': true
|
||||
rules:
|
||||
'react/jsx-no-constructed-context-values': off
|
||||
- files:
|
||||
|
|
|
@ -12,7 +12,7 @@ on:
|
|||
- synchronize
|
||||
- ready_for_review
|
||||
push:
|
||||
|
||||
|
||||
jobs:
|
||||
test-client:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -27,7 +27,7 @@ jobs:
|
|||
- run: yarn --frozen-lockfile
|
||||
|
||||
- name: Run tests
|
||||
run: make test-client ARGS="--maxWorkers=2"
|
||||
run: make test-client ARGS="--maxWorkers=2 --minWorkers=1"
|
||||
test-server:
|
||||
strategy:
|
||||
matrix:
|
||||
|
|
|
@ -27,10 +27,9 @@ export function mockT(i18nKey: string, args?: Record<string, string>) {
|
|||
return key;
|
||||
}
|
||||
|
||||
const i18next: Record<string, unknown> = jest.createMockFromModule('i18next');
|
||||
i18next.t = mockT;
|
||||
i18next.language = 'en';
|
||||
i18next.changeLanguage = () => new Promise(() => {});
|
||||
i18next.use = () => i18next;
|
||||
|
||||
export default i18next;
|
||||
export default {
|
||||
t: mockT,
|
||||
language: 'en',
|
||||
changeLanguage: () => new Promise(() => {}),
|
||||
use: () => this,
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ describe('promiseSequence', () => {
|
|||
});
|
||||
|
||||
it('provided two promise functions, the second should run after the first', async () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
|
||||
function first() {
|
||||
return Promise.resolve(callback(1));
|
||||
|
|
|
@ -2,10 +2,11 @@ import toastr from 'toastr';
|
|||
|
||||
import { notifyError, notifySuccess, notifyWarning } from './notifications';
|
||||
|
||||
jest.mock('toastr');
|
||||
vi.mock('toastr');
|
||||
vi.spyOn(console, 'error').mockImplementation(() => vi.fn());
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
it('calling success should show success message', () => {
|
||||
|
@ -18,9 +19,9 @@ it('calling success should show success message', () => {
|
|||
});
|
||||
|
||||
it('calling error with Error should show error message', () => {
|
||||
const consoleErrorFn = jest
|
||||
const consoleErrorFn = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => jest.fn());
|
||||
.mockImplementation(() => vi.fn());
|
||||
const title = 'title';
|
||||
const errorMessage = 'message';
|
||||
const fallback = 'fallback';
|
||||
|
@ -37,9 +38,9 @@ it('calling error with Error should show error message', () => {
|
|||
});
|
||||
|
||||
it('calling error without Error should show fallback message', () => {
|
||||
const consoleErrorFn = jest
|
||||
const consoleErrorFn = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => jest.fn());
|
||||
.mockImplementation(() => vi.fn());
|
||||
const title = 'title';
|
||||
|
||||
const fallback = 'fallback';
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import '@testing-library/jest-dom';
|
||||
|
||||
import 'vitest-dom/extend-expect';
|
||||
import { render, RenderOptions } from '@testing-library/react';
|
||||
import { UIRouter, pushStateLocationPlugin } from '@uirouter/react';
|
||||
import { PropsWithChildren, ReactElement } from 'react';
|
||||
|
|
|
@ -11,9 +11,9 @@ import {
|
|||
|
||||
import { DashboardView } from './DashboardView';
|
||||
|
||||
jest.mock('@uirouter/react', () => ({
|
||||
...jest.requireActual('@uirouter/react'),
|
||||
useCurrentStateAndParams: jest.fn(() => ({
|
||||
vi.mock('@uirouter/react', async (importOriginal: () => Promise<object>) => ({
|
||||
...(await importOriginal()),
|
||||
useCurrentStateAndParams: vi.fn(() => ({
|
||||
params: { endpointId: 1 },
|
||||
})),
|
||||
}));
|
||||
|
@ -73,7 +73,7 @@ test('should correctly show total number of resource groups across multiple subs
|
|||
});
|
||||
|
||||
test("when only subscriptions fail to load, don't show the dashboard", async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { queryByLabelText } = await renderComponent(
|
||||
1,
|
||||
|
@ -86,7 +86,7 @@ test("when only subscriptions fail to load, don't show the dashboard", async ()
|
|||
});
|
||||
|
||||
test('when only resource groups fail to load, still show the subscriptions', async () => {
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
const { queryByLabelText, findByLabelText } = await renderComponent(
|
||||
1,
|
||||
|
|
|
@ -6,9 +6,9 @@ import { renderWithQueryClient } from '@/react-tools/test-utils';
|
|||
|
||||
import { CreateContainerInstanceForm } from './CreateContainerInstanceForm';
|
||||
|
||||
jest.mock('@uirouter/react', () => ({
|
||||
...jest.requireActual('@uirouter/react'),
|
||||
useCurrentStateAndParams: jest.fn(() => ({
|
||||
vi.mock('@uirouter/react', async (importOriginal: () => Promise<object>) => ({
|
||||
...(await importOriginal()),
|
||||
useCurrentStateAndParams: vi.fn(() => ({
|
||||
params: { endpointId: 5 },
|
||||
})),
|
||||
}));
|
||||
|
|
|
@ -44,7 +44,7 @@ test('should render with the initial value selected and call onChange when click
|
|||
},
|
||||
];
|
||||
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const { getByLabelText } = renderDefault({
|
||||
options,
|
||||
onChange,
|
||||
|
|
|
@ -37,7 +37,7 @@ test('should call onSelect when clicked with id', async () => {
|
|||
{ children: 'Content 2', id: 'option2', label: 'Option 2' },
|
||||
];
|
||||
|
||||
const onSelect = jest.fn();
|
||||
const onSelect = vi.fn();
|
||||
|
||||
const { findByText } = renderComponent(options, options[1].id, onSelect);
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ import { HeaderContainer } from './HeaderContainer';
|
|||
import { HeaderTitle } from './HeaderTitle';
|
||||
|
||||
test('should not render without a wrapping HeaderContainer', async () => {
|
||||
const consoleErrorFn = jest
|
||||
const consoleErrorFn = vi
|
||||
.spyOn(console, 'error')
|
||||
.mockImplementation(() => jest.fn());
|
||||
.mockImplementation(() => vi.fn());
|
||||
|
||||
const title = 'title';
|
||||
function renderComponent() {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`should not render without a wrapping HeaderContainer 1`] = `"Should be nested inside a HeaderContainer component"`;
|
||||
exports[`should not render without a wrapping HeaderContainer 1`] = `[Error: Should be nested inside a HeaderContainer component]`;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { http, HttpResponse } from 'msw';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
import { Tag, TagId } from '@/portainer/tags/types';
|
||||
import { renderWithQueryClient } from '@/react-tools/test-utils';
|
||||
|
@ -43,11 +44,11 @@ async function renderComponent(
|
|||
{
|
||||
value = [],
|
||||
allowCreate = false,
|
||||
onChange = jest.fn(),
|
||||
onChange = vi.fn(),
|
||||
}: {
|
||||
value?: TagId[];
|
||||
allowCreate?: boolean;
|
||||
onChange?: jest.Mock;
|
||||
onChange?: Mock;
|
||||
} = {},
|
||||
tags: Tag[] = []
|
||||
) {
|
||||
|
|
|
@ -26,7 +26,7 @@ function renderDefault({
|
|||
|
||||
test('should display a Button component and allow onClick', async () => {
|
||||
const children = 'test label';
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const { findByText } = renderDefault({ children, onClick });
|
||||
|
||||
const buttonLabel = await findByText(children);
|
||||
|
|
|
@ -15,7 +15,7 @@ test('should display a CopyButton with children', async () => {
|
|||
test('CopyButton should copy text to clipboard', async () => {
|
||||
// override navigator.clipboard.writeText (to test copy to clipboard functionality)
|
||||
let clipboardText = '';
|
||||
const writeText = jest.fn((text) => {
|
||||
const writeText = vi.fn((text) => {
|
||||
clipboardText = text;
|
||||
});
|
||||
Object.assign(navigator, {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { fireEvent, render } from '@/react-tools/test-utils';
|
|||
import { FileUploadField } from './FileUploadField';
|
||||
|
||||
test('render should make the file button clickable and fire onChange event after click', async () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const { findByText, findByLabelText } = render(
|
||||
<FileUploadField
|
||||
title="test button"
|
||||
|
|
|
@ -3,7 +3,7 @@ import { render } from '@/react-tools/test-utils';
|
|||
import { FileUploadForm } from './FileUploadForm';
|
||||
|
||||
test('render should include description', async () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const { findByText } = render(
|
||||
<FileUploadForm
|
||||
title="test button"
|
||||
|
|
|
@ -6,7 +6,7 @@ function renderDefault({
|
|||
name = 'default name',
|
||||
checked = false,
|
||||
label = 'label',
|
||||
onChange = jest.fn(),
|
||||
onChange = vi.fn(),
|
||||
index,
|
||||
}: Partial<Props> = {}) {
|
||||
return render(
|
||||
|
@ -28,7 +28,7 @@ test('should display a Switch component', async () => {
|
|||
});
|
||||
|
||||
test('clicking should emit on-change with the opposite value', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const checked = true;
|
||||
const { findByRole } = renderDefault({ onChange, checked });
|
||||
|
||||
|
@ -39,7 +39,7 @@ test('clicking should emit on-change with the opposite value', async () => {
|
|||
});
|
||||
|
||||
test('clicking should emit on-change with the opposite value and index', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const checked = true;
|
||||
const index = 3;
|
||||
const { findByRole } = renderDefault({ onChange, checked, index });
|
||||
|
|
|
@ -18,9 +18,9 @@ const networkContainers: NetworkContainer[] = [
|
|||
},
|
||||
];
|
||||
|
||||
jest.mock('@uirouter/react', () => ({
|
||||
...jest.requireActual('@uirouter/react'),
|
||||
useCurrentStateAndParams: jest.fn(() => ({
|
||||
vi.mock('@uirouter/react', async (importOriginal: () => Promise<object>) => ({
|
||||
...(await importOriginal()),
|
||||
useCurrentStateAndParams: vi.fn(() => ({
|
||||
params: { endpointId: 1 },
|
||||
})),
|
||||
}));
|
||||
|
|
|
@ -6,9 +6,9 @@ import { DockerNetwork } from '../types';
|
|||
|
||||
import { NetworkDetailsTable } from './NetworkDetailsTable';
|
||||
|
||||
jest.mock('@uirouter/react', () => ({
|
||||
...jest.requireActual('@uirouter/react'),
|
||||
useCurrentStateAndParams: jest.fn(() => ({
|
||||
vi.mock('@uirouter/react', async (importOriginal: () => Promise<object>) => ({
|
||||
...(await importOriginal()),
|
||||
useCurrentStateAndParams: vi.fn(() => ({
|
||||
params: { endpointId: 1 },
|
||||
})),
|
||||
}));
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('getValidEditorTypes', () => {
|
|||
];
|
||||
|
||||
tests.forEach((test) => {
|
||||
// eslint-disable-next-line jest/valid-title
|
||||
// eslint-disable-next-line vitest/valid-title
|
||||
it(test.title, () => {
|
||||
expect(getValidEditorTypes(test.endpointTypes)).toEqual(test.expected);
|
||||
});
|
||||
|
|
|
@ -431,7 +431,7 @@ describe('getCreateAppSummaries', () => {
|
|||
},
|
||||
];
|
||||
tests.forEach((test) => {
|
||||
// eslint-disable-next-line jest/valid-title
|
||||
// eslint-disable-next-line vitest/valid-title
|
||||
it(test.title, () => {
|
||||
expect(
|
||||
getAppResourceSummaries(test.newFormValues, test.oldFormValues)
|
||||
|
@ -507,7 +507,7 @@ describe('getUpdateAppSummaries', () => {
|
|||
},
|
||||
];
|
||||
tests.forEach((test) => {
|
||||
// eslint-disable-next-line jest/valid-title
|
||||
// eslint-disable-next-line vitest/valid-title
|
||||
it(test.title, () => {
|
||||
expect(
|
||||
getAppResourceSummaries(test.newFormValues, test.oldFormValues)
|
||||
|
|
|
@ -51,7 +51,7 @@ async function renderComponent(
|
|||
|
||||
const queries = renderWithQueryClient(
|
||||
<UserContext.Provider value={{ user }}>
|
||||
<EnvironmentList onClickBrowse={jest.fn()} onRefresh={jest.fn()} />
|
||||
<EnvironmentList onClickBrowse={vi.fn()} onRefresh={vi.fn()} />
|
||||
</UserContext.Provider>
|
||||
);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ test.each([
|
|||
async (ownership) => {
|
||||
const values = buildFormData(ownership);
|
||||
|
||||
const { findByRole } = await renderComponent(values, jest.fn(), {
|
||||
const { findByRole } = await renderComponent(values, vi.fn(), {
|
||||
isAdmin: true,
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ test.each([
|
|||
async (ownership) => {
|
||||
const values = buildFormData(ownership);
|
||||
|
||||
const { findByRole } = await renderComponent(values, jest.fn(), {
|
||||
const { findByRole } = await renderComponent(values, vi.fn(), {
|
||||
teams: [],
|
||||
isAdmin: false,
|
||||
});
|
||||
|
@ -99,7 +99,7 @@ test.each([
|
|||
async (ownership) => {
|
||||
const values = buildFormData(ownership);
|
||||
|
||||
const { findByRole } = await renderComponent(values, jest.fn(), {
|
||||
const { findByRole } = await renderComponent(values, vi.fn(), {
|
||||
teams: createMockTeams(1),
|
||||
isAdmin: false,
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ test('when ownership is public, ownership selector should be hidden', async () =
|
|||
test('when hideTitle is true, title should be hidden', async () => {
|
||||
const values = buildFormData();
|
||||
|
||||
const { queryByRole } = await renderComponent(values, jest.fn(), {
|
||||
const { queryByRole } = await renderComponent(values, vi.fn(), {
|
||||
hideTitle: true,
|
||||
});
|
||||
|
||||
|
@ -136,7 +136,7 @@ test('when isAdmin and admin ownership is selected, no extra options are visible
|
|||
|
||||
const { findByRole, queryByLabelText } = await renderComponent(
|
||||
values,
|
||||
jest.fn(),
|
||||
vi.fn(),
|
||||
{
|
||||
isAdmin: true,
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ test('when isAdmin and restricted ownership is selected, show team and users sel
|
|||
|
||||
const { findByRole, findByLabelText } = await renderComponent(
|
||||
values,
|
||||
jest.fn(),
|
||||
vi.fn(),
|
||||
{
|
||||
isAdmin: true,
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ test('when user is not an admin, there are more then 1 team and ownership is res
|
|||
|
||||
const { findByRole, findByLabelText } = await renderComponent(
|
||||
values,
|
||||
jest.fn()
|
||||
vi.fn()
|
||||
);
|
||||
|
||||
const ownershipSelector = await findByRole('radiogroup');
|
||||
|
@ -231,7 +231,7 @@ test('when user is not an admin, there is 1 team and ownership is restricted, te
|
|||
|
||||
const { findByRole, findByLabelText } = await renderComponent(
|
||||
values,
|
||||
jest.fn(),
|
||||
vi.fn(),
|
||||
{
|
||||
teams: createMockTeams(1),
|
||||
isAdmin: false,
|
||||
|
@ -266,7 +266,7 @@ test('when user is not an admin, and ownership is restricted, user selector not
|
|||
|
||||
const { findByRole, findByLabelText } = await renderComponent(
|
||||
values,
|
||||
jest.fn(),
|
||||
vi.fn(),
|
||||
{
|
||||
isAdmin: false,
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ interface AdditionalProps {
|
|||
|
||||
async function renderComponent(
|
||||
values: AccessControlFormData,
|
||||
onChange = jest.fn(),
|
||||
onChange = vi.fn(),
|
||||
{ isAdmin = false, hideTitle = false, teams, users }: AdditionalProps = {}
|
||||
) {
|
||||
const user = new UserViewModel({ Username: 'user', Role: isAdmin ? 1 : 2 });
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`when ownership is restricted and no teams or users, should be invalid 1`] = `"You must specify at least one team or user."`;
|
||||
exports[`when ownership is restricted and no teams or users, should be invalid 1`] = `[ValidationError: You must specify at least one team or user.]`;
|
||||
|
||||
exports[`when ownership is restricted and no teams or users, should be invalid 2`] = `"You must specify at least one team."`;
|
||||
exports[`when ownership is restricted and no teams or users, should be invalid 2`] = `[ValidationError: You must specify at least one team.]`;
|
||||
|
|
|
@ -7,8 +7,8 @@ import type { License } from './types';
|
|||
|
||||
describe('getLicenses', () => {
|
||||
it('on success should return the server body', async () => {
|
||||
const catchFn = jest.fn();
|
||||
const thenFn = jest.fn();
|
||||
const catchFn = vi.fn();
|
||||
const thenFn = vi.fn();
|
||||
|
||||
const data: License[] = [];
|
||||
server.use(http.get('/api/licenses', () => HttpResponse.json(data)));
|
||||
|
@ -22,8 +22,8 @@ describe('getLicenses', () => {
|
|||
});
|
||||
|
||||
it('on failure should return the server message', async () => {
|
||||
const catchFn = jest.fn();
|
||||
const thenFn = jest.fn();
|
||||
const catchFn = vi.fn();
|
||||
const thenFn = vi.fn();
|
||||
|
||||
const message = 'message';
|
||||
const details = 'details';
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/* eslint-disable import/order */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/**
|
||||
* @note The block below contains polyfills for Node.js globals
|
||||
* required for Jest to function when running JSDOM tests.
|
||||
* These HAVE to be require's and HAVE to be in this exact
|
||||
* order, since "undici" depends on the "TextEncoder" global API.
|
||||
*
|
||||
* Consider migrating to a more modern test runner if
|
||||
* you don't want to deal with this.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const { TextDecoder, TextEncoder } = require('node:util');
|
||||
|
||||
Object.defineProperties(globalThis, {
|
||||
TextDecoder: { value: TextDecoder },
|
||||
TextEncoder: { value: TextEncoder },
|
||||
});
|
||||
|
||||
const { ReadableStream } = require('node:stream/web');
|
||||
|
||||
Object.defineProperties(globalThis, {
|
||||
ReadableStream: { value: ReadableStream },
|
||||
});
|
||||
|
||||
const { Blob, File } = require('node:buffer');
|
||||
|
||||
const { fetch, Headers, FormData, Request, Response } = require('undici');
|
||||
|
||||
Object.defineProperties(globalThis, {
|
||||
fetch: { value: fetch, writable: true },
|
||||
Blob: { value: Blob },
|
||||
File: { value: File },
|
||||
Headers: { value: Headers },
|
||||
FormData: { value: FormData },
|
||||
Request: { value: Request },
|
||||
Response: { value: Response },
|
||||
});
|
||||
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
/* eslint-enable import/order */
|
|
@ -1,5 +1,3 @@
|
|||
// test/setup-env.js
|
||||
// add this to your setupFilesAfterEnv config in jest so it's imported for every test file
|
||||
import { server } from './server';
|
||||
|
||||
beforeAll(() => server.listen());
|
||||
|
|
203
jest.config.js
203
jest.config.js
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* For a detailed explanation regarding each configuration property, visit:
|
||||
* https://jestjs.io/docs/configuration
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// All imported modules in your tests should be mocked automatically
|
||||
// automock: false,
|
||||
|
||||
// Stop running tests after `n` failures
|
||||
// bail: 0,
|
||||
|
||||
// The directory where Jest should store its cached dependency information
|
||||
// cacheDirectory: "/tmp/jest_rs",
|
||||
|
||||
// Automatically clear mock calls and instances between every test
|
||||
clearMocks: true,
|
||||
|
||||
// Indicates whether the coverage information should be collected while executing the test
|
||||
// collectCoverage: false,
|
||||
|
||||
// An array of glob patterns indicating a set of files for which coverage information should be collected
|
||||
// collectCoverageFrom: undefined,
|
||||
|
||||
// The directory where Jest should output its coverage files
|
||||
// coverageDirectory: undefined,
|
||||
|
||||
// An array of regexp pattern strings used to skip coverage collection
|
||||
// coveragePathIgnorePatterns: [
|
||||
// "/node_modules/"
|
||||
// ],
|
||||
|
||||
// Indicates which provider should be used to instrument code for coverage
|
||||
coverageProvider: 'v8',
|
||||
|
||||
// A list of reporter names that Jest uses when writing coverage reports
|
||||
// coverageReporters: [
|
||||
// "json",
|
||||
// "text",
|
||||
// "lcov",
|
||||
// "clover"
|
||||
// ],
|
||||
|
||||
// An object that configures minimum threshold enforcement for coverage results
|
||||
// coverageThreshold: undefined,
|
||||
|
||||
// A path to a custom dependency extractor
|
||||
// dependencyExtractor: undefined,
|
||||
|
||||
// Make calling deprecated APIs throw helpful error messages
|
||||
// errorOnDeprecated: false,
|
||||
|
||||
// Force coverage collection from ignored files using an array of glob patterns
|
||||
// forceCoverageMatch: [],
|
||||
|
||||
// A path to a module which exports an async function that is triggered once before all test suites
|
||||
globalSetup: `<rootDir>/app/setup-tests/global-setup.js`,
|
||||
|
||||
// A path to a module which exports an async function that is triggered once after all test suites
|
||||
// globalTeardown: undefined,
|
||||
|
||||
// A set of global variables that need to be available in all test environments
|
||||
// globals: {},
|
||||
|
||||
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
|
||||
// maxWorkers: "50%",
|
||||
|
||||
// An array of directory names to be searched recursively up from the requiring module's location
|
||||
// moduleDirectories: [
|
||||
// "node_modules"
|
||||
// ],
|
||||
|
||||
// An array of file extensions your modules use
|
||||
// moduleFileExtensions: [
|
||||
// "js",
|
||||
// "jsx",
|
||||
// "ts",
|
||||
// "tsx",
|
||||
// "json",
|
||||
// "node"
|
||||
// ],
|
||||
|
||||
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
|
||||
moduleNameMapper: {
|
||||
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/app/__mocks__/fileMock.js',
|
||||
'\\.svg\\?c$': '<rootDir>/app/__mocks__/svg.tsx',
|
||||
'\\.(css|less)$': '<rootDir>/app/__mocks__/styleMock.js',
|
||||
'^@@/(.*)$': '<rootDir>/app/react/components/$1',
|
||||
'^@/(.*)$': '<rootDir>/app/$1',
|
||||
'^Agent/(.*)?': '<rootDir>/app/agent/$1',
|
||||
'^Azure/(.*)$': '<rootDir>/app/azure/$1',
|
||||
'^Docker/(.*)$': '<rootDir>/app/docker/$1',
|
||||
'^Kubernetes/(.*)$': '<rootDir>/app/kubernetes/$1',
|
||||
'^Portainer/(.*)$': '<rootDir>/app/portainer/$1',
|
||||
},
|
||||
|
||||
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
|
||||
// modulePathIgnorePatterns: [],
|
||||
|
||||
// Activates notifications for test results
|
||||
// notify: false,
|
||||
|
||||
// An enum that specifies notification mode. Requires { notify: true }
|
||||
// notifyMode: "failure-change",
|
||||
|
||||
// A preset that is used as a base for Jest's configuration
|
||||
// preset: undefined,
|
||||
|
||||
// Run tests from one or more projects
|
||||
// projects: undefined,
|
||||
|
||||
// Use this configuration option to add custom reporters to Jest
|
||||
// reporters: undefined,
|
||||
|
||||
// Automatically reset mock state between every test
|
||||
// resetMocks: false,
|
||||
|
||||
// Reset the module registry before running each individual test
|
||||
// resetModules: false,
|
||||
|
||||
// A path to a custom resolver
|
||||
// resolver: undefined,
|
||||
|
||||
// Automatically restore mock state between every test
|
||||
// restoreMocks: false,
|
||||
|
||||
// The root directory that Jest should scan for tests and modules within
|
||||
// rootDir: undefined,
|
||||
|
||||
// A list of paths to directories that Jest should use to search for files in
|
||||
roots: ['<rootDir>/app'],
|
||||
|
||||
// Allows you to use a custom runner instead of Jest's default test runner
|
||||
// runner: "jest-runner",
|
||||
|
||||
// The paths to modules that run some code to configure or set up the testing environment before each test
|
||||
setupFiles: ['<rootDir>/app/setup-tests/jest-polyfills.ts'],
|
||||
|
||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||
setupFilesAfterEnv: ['<rootDir>/app/setup-tests/setup-msw.ts'],
|
||||
|
||||
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
||||
// slowTestThreshold: 5,
|
||||
|
||||
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
|
||||
// snapshotSerializers: [],
|
||||
|
||||
// The test environment that will be used for testing
|
||||
testEnvironment: 'jsdom', //"jest-environment-node",
|
||||
|
||||
// Options that will be passed to the testEnvironment
|
||||
// testEnvironmentOptions: {},
|
||||
|
||||
// Adds a location field to test results
|
||||
// testLocationInResults: false,
|
||||
|
||||
// The glob patterns Jest uses to detect test files
|
||||
// testMatch: [
|
||||
// "**/__tests__/**/*.[jt]s?(x)",
|
||||
// "**/?(*.)+(spec|test).[tj]s?(x)"
|
||||
// ],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
|
||||
// testPathIgnorePatterns: [
|
||||
// "/node_modules/"
|
||||
// ],
|
||||
|
||||
// The regexp pattern or array of patterns that Jest uses to detect test files
|
||||
// testRegex: [],
|
||||
|
||||
// This option allows the use of a custom results processor
|
||||
// testResultsProcessor: undefined,
|
||||
|
||||
// This option allows use of a custom test runner
|
||||
// testRunner: "jest-circus/runner",
|
||||
|
||||
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
|
||||
// testURL: "http://localhost",
|
||||
|
||||
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
|
||||
// timers: "real",
|
||||
|
||||
// A map from regular expressions to paths to transformers
|
||||
// transform: undefined,
|
||||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
transformIgnorePatterns: [],
|
||||
// "/node_modules/",
|
||||
// "\\.pnp\\.[^\\/]+$"
|
||||
// ],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
|
||||
// unmockedModulePathPatterns: undefined,
|
||||
|
||||
// Indicates whether each individual test should be reported during the run
|
||||
// verbose: undefined,
|
||||
|
||||
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
|
||||
// watchPathIgnorePatterns: [],
|
||||
|
||||
// Whether to use watchman for file crawling
|
||||
// watchman: true,
|
||||
};
|
|
@ -2,19 +2,8 @@
|
|||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"allowSyntheticDefaultImports": false,
|
||||
"baseUrl": "app",
|
||||
"module": "commonjs",
|
||||
"paths": {
|
||||
"Agent/*": ["agent/*"],
|
||||
"Azure/*": ["azure/*"],
|
||||
"Docker/*": ["docker/*"],
|
||||
"Kubernetes/*": ["kubernetes/*"],
|
||||
"Portainer/*": ["portainer/*"],
|
||||
"@/*": ["../app/*"]
|
||||
}
|
||||
"module": "commonjs"
|
||||
},
|
||||
"exclude": ["api", "build", "dist", "distribution", "node_modules", "test", "webpack"],
|
||||
"typeAcquisition": {
|
||||
"include": ["jest"]
|
||||
}
|
||||
|
||||
"extends": "./tsconfig.json"
|
||||
}
|
||||
|
|
18
package.json
18
package.json
|
@ -22,7 +22,7 @@
|
|||
"build": "webpack",
|
||||
"format": "prettier --log-level warn --write \"**/*.{js,css,html,jsx,tsx,ts,json}\"",
|
||||
"lint": "eslint --cache --fix './**/*.{js,jsx,ts,tsx}'",
|
||||
"test": "jest",
|
||||
"test": "vitest",
|
||||
"sb": "yarn storybook",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"storybook:build": "storybook build -o ./dist/storybook",
|
||||
|
@ -79,6 +79,7 @@
|
|||
"babel-plugin-angularjs-annotate": "^0.10.0",
|
||||
"bootstrap": "^3.4.0",
|
||||
"buffer": "^6.0.3",
|
||||
"c8": "^9.1.0",
|
||||
"chardet": "^1.4.0",
|
||||
"chart.js": "^2.7.0",
|
||||
"clsx": "^1.1.1",
|
||||
|
@ -97,6 +98,7 @@
|
|||
"jquery": "^3.6.0",
|
||||
"js-base64": "^3.7.2",
|
||||
"js-yaml": "^3.14.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.101.0",
|
||||
"moment": "^2.29.1",
|
||||
|
@ -139,13 +141,12 @@
|
|||
"@storybook/react": "^7.0.18",
|
||||
"@storybook/react-webpack5": "^7.0.18",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@testing-library/jest-dom": "^5.16.1",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/react": "^12",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/angular": "^1.8.3",
|
||||
"@types/file-saver": "^2.0.4",
|
||||
"@types/filesize-parser": "^1.5.1",
|
||||
"@types/jest": "^27.0.3",
|
||||
"@types/jquery": "^3.5.10",
|
||||
"@types/mustache": "^4.1.2",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
|
@ -160,7 +161,6 @@
|
|||
"@typescript-eslint/parser": "^6.7.4",
|
||||
"auto-ngtemplate-loader": "^3.1.2",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"babel-jest": "^29.5.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-plugin-i18next-extract": "^0.9.0",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
|
@ -176,17 +176,16 @@
|
|||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-jest": "^27.4.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-regex": "^1.10.0",
|
||||
"eslint-plugin-storybook": "^0.6.14",
|
||||
"eslint-plugin-vitest": "^0.3.20",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^5.5.3",
|
||||
"husky": "^8.0.0",
|
||||
"jest": "^27.4.3",
|
||||
"kubernetes-types": "^1.26.0",
|
||||
"lint-staged": "^14.0.1",
|
||||
"lodash-webpack-plugin": "^0.11.6",
|
||||
|
@ -199,7 +198,6 @@
|
|||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-tailwindcss": "^0.5.4",
|
||||
"react-docgen-typescript-plugin": "^1.0.5",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"source-map-loader": "^4.0.1",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"storybook": "^7.0.18",
|
||||
|
@ -210,6 +208,10 @@
|
|||
"tsconfig-paths-webpack-plugin": "^4.1.0",
|
||||
"typescript": "^5.2.2",
|
||||
"undici": "^6.2.1",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"vite-tsconfig-paths": "^4.3.1",
|
||||
"vitest": "^1.2.1",
|
||||
"vitest-dom": "^0.1.1",
|
||||
"webpack": "^5.88.2",
|
||||
"webpack-build-notifier": "^2.3.0",
|
||||
"webpack-bundle-analyzer": "^4.9.1",
|
||||
|
|
|
@ -37,11 +37,9 @@
|
|||
"Docker/*": ["docker/*"],
|
||||
"Kubernetes/*": ["kubernetes/*"],
|
||||
"Portainer/*": ["portainer/*"]
|
||||
}
|
||||
},
|
||||
"types": ["vitest/globals"]
|
||||
},
|
||||
"exclude": ["api", "build", "dist", "distribution", "node_modules", "test", "webpack"],
|
||||
"include": ["app"],
|
||||
"typeAcquisition": {
|
||||
"include": ["jest"]
|
||||
}
|
||||
"include": ["app"]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/// <reference types="vitest" />
|
||||
import { defineConfig } from 'vite';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: [
|
||||
'./app/setup-tests/global-setup.js',
|
||||
'./app/setup-tests/setup-msw.ts',
|
||||
],
|
||||
coverage: {
|
||||
reporter: ['text', 'html'],
|
||||
exclude: ['node_modules/', 'app/setup-tests/global-setup.js'],
|
||||
},
|
||||
bail: 2,
|
||||
include: ['./app/**/*.test.ts', './app/**/*.test.tsx'],
|
||||
},
|
||||
plugins: [svgr({ include: /\?c$/ }), tsconfigPaths()],
|
||||
});
|
Loading…
Reference in New Issue