@naturalcycles/dev-lib 16.0.2 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,119 @@
1
+ import fs from 'node:fs'
2
+ import type { InlineConfig } from 'vitest/node'
3
+
4
+ let silent: boolean
5
+ let testType: TestType = (process.env['TEST_TYPE'] as TestType) || 'unit'
6
+
7
+ const runsInIDE = process.argv.some(
8
+ a => a === '--runTestsByPath' || a.includes('IDEA') || a.includes('Visual Studio'),
9
+ )
10
+
11
+ if (runsInIDE) {
12
+ silent = false
13
+
14
+ if (process.argv.some(a => a.endsWith('.integration.test.ts'))) {
15
+ testType = 'integration'
16
+ } else if (process.argv.some(a => a.endsWith('.manual.test.ts'))) {
17
+ testType = 'manual'
18
+ }
19
+ } else {
20
+ silent = isRunningAllTests()
21
+ }
22
+
23
+ const isCI = !!process.env['CI']
24
+ process.env.TZ = process.env.TZ || 'UTC'
25
+ if (testType === 'unit') {
26
+ process.env['APP_ENV'] = process.env['APP_ENV'] || 'test'
27
+ }
28
+
29
+ // Set 'setupFiles' only if setup files exist
30
+ const setupFiles: InlineConfig['setupFiles'] = []
31
+ if (fs.existsSync(`./src/test/setupVitest.ts`)) {
32
+ setupFiles.push('./src/test/setupVitest.ts')
33
+ }
34
+ if (fs.existsSync(`./src/test/setupVitest.${testType}.ts`)) {
35
+ setupFiles.push(`./src/test/setupVitest.${testType}.ts`)
36
+ }
37
+
38
+ let include: InlineConfig['include']
39
+ const exclude: InlineConfig['exclude'] = ['**/__exclude/**']
40
+
41
+ if (testType === 'integration') {
42
+ include = ['{src,scripts}/**/*.integration.test.ts']
43
+ } else if (testType === 'manual') {
44
+ include = ['{src,scripts}/**/*.manual.test.ts']
45
+ } else {
46
+ // normal unit test
47
+ include = ['{src,scripts}/**/*.test.ts']
48
+ exclude.push('**/*.{integration,manual}.test.*')
49
+ }
50
+
51
+ if (silent) {
52
+ process.env['TEST_SILENT'] = 'true'
53
+ }
54
+
55
+ console.log('shared vitest config', { testType, silent, isCI, runsInIDE, include, exclude })
56
+
57
+ /**
58
+ * Shared config for Vitest.
59
+ */
60
+ export const sharedConfig: InlineConfig = {
61
+ watch: false,
62
+ // dir: 'src',
63
+ restoreMocks: true,
64
+ silent,
65
+ setupFiles,
66
+ logHeapUsage: true,
67
+ testTimeout: 60_000,
68
+ sequence: {
69
+ // todo: make it sort alphabetically
70
+ },
71
+ include,
72
+ exclude,
73
+ coverage: {
74
+ enabled: isCI && testType === 'unit',
75
+ reporter: ['html', 'lcov', 'json', !isCI && 'text'].filter(Boolean) as string[],
76
+ include: ['src/**/*.{ts,tsx}'],
77
+ exclude: [
78
+ '**/__exclude/**',
79
+ 'scripts/**',
80
+ 'public/**',
81
+ 'src/index.*',
82
+ 'src/test/**',
83
+ 'src/typings/**',
84
+ 'src/{env,environment,environments}/**',
85
+ 'src/bin/**',
86
+ 'src/vendor/**',
87
+ '**/*.test.*',
88
+ '**/*.script.*',
89
+ '**/*.module.*',
90
+ '**/*.mock.*',
91
+ '**/*.page.*',
92
+ '**/*.component.*',
93
+ '**/*.modal.*',
94
+ ],
95
+ },
96
+ }
97
+
98
+ /**
99
+ * Detects if vitest is run with all tests, or with selected individual tests.
100
+ */
101
+ function isRunningAllTests(): boolean {
102
+ let vitestArg = false
103
+ let hasPositionalArgs = false
104
+ process.argv.forEach(a => {
105
+ if (a.includes('.bin/vitest')) {
106
+ vitestArg = true
107
+ return
108
+ }
109
+ if (!vitestArg) return
110
+ if (!a.startsWith('-')) {
111
+ hasPositionalArgs = true
112
+ }
113
+ })
114
+ // console.log({vitestArg, hasPositionalArgs}, process.argv)
115
+
116
+ return !hasPositionalArgs
117
+ }
118
+
119
+ type TestType = 'unit' | 'integration' | 'manual'
@@ -35,16 +35,21 @@ const commands = [
35
35
  desc: 'Clean ./dist and ./dist-esm, then run "tsc" in CJS and ESM modes, with --emit and --noCheck',
36
36
  },
37
37
  new prompts_1.Separator(), // test
38
- { name: 'test', fn: test_util_1.runJest, desc: 'Run jest for *.test.ts files.' },
38
+ { name: 'test', fn: test_util_1.runTest, desc: 'Run vitest/jest for *.test.ts files.' },
39
39
  {
40
40
  name: 'test-integration',
41
- fn: () => (0, test_util_1.runJest)({ integration: true }),
42
- desc: 'Run jest for *.integration.test.ts files.',
41
+ fn: () => (0, test_util_1.runTest)({ integration: true }),
42
+ desc: 'Run vitest/jest for *.integration.test.ts files.',
43
+ },
44
+ {
45
+ name: 'test-manual',
46
+ fn: () => (0, test_util_1.runTest)({ manual: true }),
47
+ desc: 'Run vitest/jest for *.manual.test.ts files.',
43
48
  },
44
49
  {
45
50
  name: 'test-leaks',
46
- fn: () => (0, test_util_1.runJest)({ leaks: true }),
47
- desc: 'Run jest --detectLeaks for *.test.ts files.',
51
+ fn: () => (0, test_util_1.runTest)({ leaks: true }),
52
+ desc: 'Run vitest/jest --detectLeaks for *.test.ts files.',
48
53
  },
49
54
  new prompts_1.Separator(), // lint
50
55
  {
@@ -136,7 +141,7 @@ async function lbt() {
136
141
  }
137
142
  async function bt() {
138
143
  await tscAll();
139
- (0, test_util_1.runJest)();
144
+ (0, test_util_1.runTest)();
140
145
  }
141
146
  async function tscAll() {
142
147
  await (0, build_util_1.runTSCInFolders)(['.', 'scripts', 'e2e'], ['--noEmit']);
package/dist/lint.util.js CHANGED
@@ -182,20 +182,10 @@ function stylelintAll() {
182
182
  });
183
183
  }
184
184
  async function lintStagedCommand() {
185
- // const cwd = process.cwd()
186
185
  const localConfig = `./lint-staged.config.js`;
187
186
  const sharedConfig = `${paths_1.cfgDir}/lint-staged.config.js`;
188
187
  const config = node_fs_1.default.existsSync(localConfig) ? localConfig : sharedConfig;
189
- // if (!config) {
190
- // console.log(`lint-staged is skipped, because no ${localConfig} is found`)
191
- // return
192
- // }
193
- // await execWithArgs(`lint-staged`, [`--config`, config])
194
- // const lintStaged = require('lint-staged')
195
- // lint-staged is ESM since 12.0
196
- // const lintStaged = await import('lint-staged')
197
- // biome-ignore lint/security/noGlobalEval: ok
198
- const { default: lintStaged } = await eval(`import('lint-staged')`);
188
+ const { default: lintStaged } = await import('lint-staged');
199
189
  const success = await lintStaged({
200
190
  configPath: config,
201
191
  });
@@ -1,10 +1,7 @@
1
- interface RunJestOpt {
1
+ interface RunTestOptions {
2
2
  integration?: boolean;
3
3
  manual?: boolean;
4
4
  leaks?: boolean;
5
5
  }
6
- /**
7
- * 1. Adds `--silent` if running all tests at once.
8
- */
9
- export declare function runJest(opt?: RunJestOpt): void;
6
+ export declare function runTest(opt?: RunTestOptions): void;
10
7
  export {};
package/dist/test.util.js CHANGED
@@ -1,19 +1,51 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runJest = runJest;
3
+ exports.runTest = runTest;
4
4
  const tslib_1 = require("tslib");
5
5
  const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
6
6
  const js_lib_1 = require("@naturalcycles/js-lib");
7
7
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
8
8
  const paths_1 = require("./paths");
9
+ function runTest(opt = {}) {
10
+ if (nodeModuleExists('vitest')) {
11
+ runVitest(opt);
12
+ return;
13
+ }
14
+ if (nodeModuleExists('jest')) {
15
+ runJest(opt);
16
+ return;
17
+ }
18
+ console.log((0, nodejs_lib_1.dimGrey)(`vitest/jest not found, skipping tests`));
19
+ }
20
+ function runVitest(opt) {
21
+ const { integration, manual } = opt;
22
+ const processArgs = process.argv.slice(3);
23
+ const args = [...processArgs];
24
+ const { TZ = 'UTC' } = process.env;
25
+ const env = {
26
+ TZ,
27
+ };
28
+ if (integration) {
29
+ Object.assign(env, {
30
+ TEST_TYPE: 'integration',
31
+ });
32
+ }
33
+ else if (manual) {
34
+ Object.assign(env, {
35
+ TEST_TYPE: 'manual',
36
+ });
37
+ }
38
+ nodejs_lib_1.exec2.spawn('vitest', {
39
+ args: (0, js_lib_1._uniq)(args),
40
+ logFinish: false,
41
+ shell: false,
42
+ env,
43
+ });
44
+ }
9
45
  /**
10
46
  * 1. Adds `--silent` if running all tests at once.
11
47
  */
12
- function runJest(opt = {}) {
13
- if (!nodeModuleExists('jest')) {
14
- console.log((0, nodejs_lib_1.dimGrey)(`node_modules/${(0, nodejs_lib_1.white)('jest')} not found, skipping tests`));
15
- return;
16
- }
48
+ function runJest(opt) {
17
49
  const { CI, CPU_LIMIT, TZ = 'UTC', APP_ENV, JEST_NO_ALPHABETIC, JEST_SHARDS } = process.env;
18
50
  const cpuLimit = Number(CPU_LIMIT) || undefined;
19
51
  const { integration, manual, leaks } = opt;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.testOffline = testOffline;
4
4
  exports.jestOnline = jestOnline;
5
- const index_1 = require("./index");
6
5
  const LOCAL_HOSTS = ['localhost', '127.0.0.1'];
7
6
  const detectLeaks = process.argv.some(a => a.includes('detectLeaks'));
8
7
  let mitm;
@@ -11,10 +10,10 @@ let mitm;
11
10
  */
12
11
  function testOffline() {
13
12
  if (detectLeaks) {
14
- (0, index_1.jestLog)('NOT applying testOffline() when --detectLeaks is on');
13
+ console.log('NOT applying testOffline() when --detectLeaks is on');
15
14
  return;
16
15
  }
17
- (0, index_1.jestLog)('test offline mode');
16
+ console.log('test offline mode');
18
17
  const createMitm = require('mitm');
19
18
  mitm ||= createMitm();
20
19
  mitm.on('connect', (socket, opts) => {
@@ -1,3 +1,3 @@
1
1
  export declare function silentConsole(): void;
2
- export declare const jestLogger: import("@naturalcycles/js-lib").CommonLogger;
3
- export declare const jestLog: import("@naturalcycles/js-lib").CommonLogFunction;
2
+ export declare const testLogger: import("@naturalcycles/js-lib").CommonLogger;
3
+ export declare const testLog: import("@naturalcycles/js-lib").CommonLogFunction;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.jestLog = exports.jestLogger = void 0;
3
+ exports.testLog = exports.testLogger = void 0;
4
4
  exports.silentConsole = silentConsole;
5
5
  const js_lib_1 = require("@naturalcycles/js-lib");
6
6
  const nodejs_lib_1 = require("@naturalcycles/nodejs-lib");
@@ -13,8 +13,8 @@ function silentConsole() {
13
13
  console.time = () => { };
14
14
  console.table = () => { };
15
15
  }
16
- exports.jestLogger = (0, js_lib_1.commonLoggerCreate)((_level, args) => {
17
- if (process.env['JEST_SILENT'])
16
+ exports.testLogger = (0, js_lib_1.commonLoggerCreate)((_level, args) => {
17
+ if (process.env['JEST_SILENT'] || process.env['TEST_SILENT'])
18
18
  return; // no-op
19
19
  process.stdout.write(args
20
20
  .map(a => (0, nodejs_lib_1._inspect)(a, {
@@ -22,4 +22,4 @@ exports.jestLogger = (0, js_lib_1.commonLoggerCreate)((_level, args) => {
22
22
  }))
23
23
  .join(' ') + '\n');
24
24
  });
25
- exports.jestLog = exports.jestLogger.log.bind(exports.jestLogger);
25
+ exports.testLog = exports.testLogger.log.bind(exports.testLogger);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/dev-lib",
3
- "version": "16.0.2",
3
+ "version": "16.2.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "tsn-debug": "tsn testScript.ts",
@@ -12,6 +12,7 @@
12
12
  "test": "tsn ./src/bin/dev-lib.ts test",
13
13
  "test-leaks": "tsn ./src/bin/dev-lib.ts test-leaks",
14
14
  "test-integration": "tsn ./src/bin/dev-lib.ts test-integration",
15
+ "test-manual": "tsn ./src/bin/dev-lib.ts test-manual",
15
16
  "lint": "tsn ./src/bin/dev-lib.ts lint",
16
17
  "up": "tsn ./src/bin/up.ts",
17
18
  "upnc": "tsn ./src/bin/upnc.ts"
@@ -47,13 +48,10 @@
47
48
  "yargs": "^17"
48
49
  },
49
50
  "devDependencies": {
50
- "@types/jest": "^29",
51
- "eslint-plugin-jest": "^28",
52
- "jest": "^29",
53
- "jest-junit": "^16",
51
+ "@vitest/coverage-v8": "^3",
54
52
  "stylelint": "^16",
55
53
  "stylelint-config-standard-scss": "^14",
56
- "ts-jest": "^29"
54
+ "vitest": "^3"
57
55
  },
58
56
  "files": [
59
57
  "dist",