Skip to content

Commit 4f5b1ef

Browse files
Боровский ДмитрийБоровский Дмитрий
authored andcommitted
feat(*): add support vitest
1 parent 5ec767c commit 4f5b1ef

10 files changed

Lines changed: 1090 additions & 4 deletions

File tree

.changeset/smart-planes-greet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'arui-scripts': minor
3+
---
4+
5+
добавлена возможность запускать тесты c помощью vitest

packages/arui-scripts/docs/commands.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,40 @@ _package.json_
5757
arui-scripts test
5858
```
5959

60+
### test:vitest
61+
Команда `arui-scripts test:vitest` запускает unit тесты через [Vitest](https://vitest.dev/).
62+
63+
Если в корне проекта есть `vitest.config.ts` (или `.js`, `.mjs`, `.cjs`), то используется он.
64+
Иначе применяется конфигурация arui-scripts.
65+
66+
**Рекомендуемый способ настройки** - создать `vitest.config.js` с `mergeConfig`:
67+
68+
```javascript
69+
import { defineConfig, mergeConfig } from 'vitest/config';
70+
import aruiConfig from 'arui-scripts/vitest';
71+
72+
export default mergeConfig(aruiConfig, defineConfig({
73+
test: {
74+
setupFiles: ['./__tests__/setup.js'],
75+
// другие настройки Vitest
76+
},
77+
}));
78+
```
79+
80+
Базовый конфиг arui-scripts включает:
81+
- API Vitest - используйте явные импорты: `import { describe, it, expect } from 'vitest'` (без глобальных переменных)
82+
- Замену импортов `.css` на пустые модули, ассетов (svg, png, шрифты и др.) - на строку с именем файла
83+
- Маппинг путей из `tsconfig.json` (paths) через [vite-tsconfig-paths](https://www.npmjs.com/package/vite-tsconfig-paths)
84+
- Маски для тестов: `src/**/__tests__/**/*`, `src/**/__test__/**/*`, `src/**/*.{test,spec,tests}.*`
85+
86+
**Обратная совместимость**: при отсутствии `vitest.config.*` по-прежнему читается `jest.setupFiles` из `package.json`.
87+
88+
**Как запустить?**
89+
90+
```bash
91+
arui-scripts test:vitest
92+
```
93+
6094
### docker-build
6195
Собирает клиентский и серверный код в production-режиме, создает docker-образ и пушит его в docker-репозиторий.
6296

packages/arui-scripts/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
"version": "20.11.1",
44
"main": "./build/index.js",
55
"typings": "./build/index.d.ts",
6+
"exports": {
7+
".": "./build/index.js",
8+
"./vitest": "./build/configs/vitest/config.js"
9+
},
610
"license": "MPL-2.0",
711
"repository": {
812
"type": "git",
@@ -114,6 +118,8 @@
114118
"ts-jest": "29.1.0",
115119
"ts-loader": "9.4.4",
116120
"ts-node": "9.1.1",
121+
"vite-tsconfig-paths": "^5.1.0",
122+
"vitest": "^2.1.0",
117123
"webpack-bundle-analyzer": "4.10.2",
118124
"webpack-deduplication-plugin": "^0.0.8",
119125
"webpack-manifest-plugin": "3.2.0",
@@ -148,6 +154,7 @@
148154
"scripts": {
149155
"build": "sh bin/build.sh",
150156
"test": "jest",
157+
"test:vitest": "vitest",
151158
"lint:scripts": "arui-presets-lint scripts",
152159
"format": "arui-presets-lint format",
153160
"format:check": "arui-presets-lint format:check",

packages/arui-scripts/src/bin/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const commands: Record<string, () => void> = {
99
'docker-build': () => require('../commands/docker-build'),
1010
'docker-build:compiled': () => require('../commands/docker-build-compiled'),
1111
test: () => require('../commands/test'),
12+
'test:vitest': () => require('../commands/test-vitest'),
1213
'ensure-yarn': () => require('../commands/ensure-yarn'),
1314
'archive-build': () => require('../commands/archive-build'),
1415
'bundle-analyze': () => require('../commands/bundle-analyze'),
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { spawn } from 'child_process';
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
// Do this as the first thing so that any code reading it knows the right env.
6+
process.env.BABEL_ENV = 'test';
7+
process.env.NODE_ENV = 'test';
8+
process.env.PUBLIC_URL = '';
9+
10+
// расширения как в Vite (vite.config.* -> vitest.config.*)
11+
const VITEST_CONFIG_FILES = [
12+
'vitest.config.js',
13+
'vitest.config.mjs',
14+
'vitest.config.ts',
15+
'vitest.config.cjs',
16+
'vitest.config.mts',
17+
'vitest.config.cts',
18+
];
19+
20+
function hasProjectVitestConfig(cwd: string): boolean {
21+
return VITEST_CONFIG_FILES.some((file) => fs.existsSync(path.join(cwd, file)));
22+
}
23+
24+
const cwd = process.cwd();
25+
const aruiVitestConfigPath = path.resolve(__dirname, '../../configs/vitest/config.js');
26+
const args = process.argv.slice(3);
27+
28+
const vitestArgs = hasProjectVitestConfig(cwd)
29+
? ['run', ...args]
30+
: ['run', '--config', aruiVitestConfigPath, ...args];
31+
32+
const vitestDir = path.dirname(require.resolve('vitest/package.json'));
33+
const vitestBin = path.join(vitestDir, 'vitest.mjs');
34+
35+
const vitestProcess = spawn(process.execPath, [vitestBin, ...vitestArgs], {
36+
stdio: 'inherit',
37+
shell: false,
38+
});
39+
40+
vitestProcess.on('close', (code) => {
41+
process.exit(code ?? 0);
42+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { defineConfig } from 'vitest/config';
2+
3+
import { getVitestConfig } from './settings';
4+
5+
export default defineConfig(getVitestConfig());
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
4+
import tsconfigPaths from 'vite-tsconfig-paths';
5+
6+
function getSetupFiles(cwd: string): string[] {
7+
const packagePath = path.join(cwd, 'package.json');
8+
9+
let setupFiles: string[] = [];
10+
11+
if (fs.existsSync(packagePath)) {
12+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8')) as {
13+
jest?: { setupFiles?: string[] };
14+
};
15+
16+
setupFiles = pkg.jest?.setupFiles ?? [];
17+
}
18+
19+
return setupFiles.map((file: string) => path.resolve(cwd, file.replace('<rootDir>', '.')));
20+
}
21+
22+
const ASSET_EXTENSIONS = [
23+
'.svg',
24+
'.png',
25+
'.jpg',
26+
'.jpeg',
27+
'.gif',
28+
'.webp',
29+
'.ico',
30+
'.bmp',
31+
'.woff',
32+
'.woff2',
33+
'.ttf',
34+
'.eot',
35+
];
36+
37+
function isAsset(id: string): boolean {
38+
return ASSET_EXTENSIONS.some((extension) => id.endsWith(extension));
39+
}
40+
41+
const staticFilesMockPlugin = {
42+
name: 'arui-scripts-static-files-mock',
43+
enforce: 'pre' as const,
44+
load(id: string) {
45+
if (id.endsWith('.css')) {
46+
return 'export default {}';
47+
}
48+
49+
if (isAsset(id)) {
50+
const filename = path.basename(id);
51+
52+
return `export default ${JSON.stringify(filename)}`;
53+
}
54+
55+
return undefined;
56+
},
57+
};
58+
59+
export function getVitestConfig() {
60+
const cwd = process.cwd();
61+
const setupFiles = getSetupFiles(cwd);
62+
63+
return {
64+
plugins: [tsconfigPaths({ root: cwd }), staticFilesMockPlugin],
65+
test: {
66+
environment: 'jsdom' as const,
67+
setupFiles,
68+
include: [
69+
'src/**/__tests__/**/*.{ts,tsx,js,jsx}',
70+
'src/**/__test__/**/*.{ts,tsx,js,jsx}',
71+
'src/**/*.{test,spec,tests}.{ts,tsx,js,jsx}',
72+
],
73+
exclude: ['**/node_modules/**', '**/build/**', '**/.build/**'],
74+
coverage: {
75+
provider: 'v8' as const,
76+
include: ['src/**/*.{js,jsx,ts,tsx}'],
77+
exclude: ['**/*.d.ts', '**/__tests__/**'],
78+
},
79+
environmentOptions: {
80+
jsdom: {
81+
url: 'http://localhost',
82+
},
83+
},
84+
},
85+
};
86+
}

packages/example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"bundle-analyze": "arui-scripts bundle-analyze",
99
"start": "NODE_ENV=localhost arui-scripts start",
1010
"test": "arui-scripts test",
11+
"test:vitest": "arui-scripts test:vitest",
1112
"lint:styles": "arui-presets-lint styles",
1213
"lint:scripts": "arui-presets-lint scripts",
1314
"format": "arui-presets-lint format",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`app > should be match to snapshot 1`] = `ShallowWrapper {}`;
4+
35
exports[`app should be match to snapshot 1`] = `ShallowWrapper {}`;

0 commit comments

Comments
 (0)