Files
MoviePilot-Frontend/scripts/run-tests.mjs
T

57 lines
1.7 KiB
JavaScript

import { spawn } from 'node:child_process'
import { fileURLToPath } from 'node:url'
const defaultShards = ['1/2', '2/2']
const serialFlag = '--serial'
const vitestCliPath = fileURLToPath(import.meta.resolve('vitest/vitest.mjs'))
/**
* 生成一次 test:run 所需的 Vitest 参数组。全量测试默认并行;显式分片、串行模式和聚焦过滤保持单进程。
*
* @param {string[]} args test:run 接收的命令行参数
* @returns {string[][]} 每个 Vitest 进程接收的一组参数
*/
export function planTestRuns(args) {
const vitestArgs = args.filter(arg => arg !== serialFlag)
const hasExplicitShard = vitestArgs.some(arg => arg === '--shard' || arg.startsWith('--shard='))
const hasPositionalFilter = vitestArgs.some(arg => !arg.startsWith('-'))
if (args.includes(serialFlag) || hasExplicitShard || hasPositionalFilter) return [vitestArgs]
return defaultShards.map(shard => [...vitestArgs, `--shard=${shard}`])
}
function runVitest(args) {
return new Promise(resolveRun => {
const child = spawn(process.execPath, [vitestCliPath, 'run', ...args], {
env: process.env,
stdio: 'inherit',
})
child.on('error', error => {
console.error(`无法启动 Vitest: ${error.message}`)
resolveRun(1)
})
child.on('close', (code, signal) => {
if (signal) {
console.error(`Vitest 被信号 ${signal} 终止`)
resolveRun(1)
return
}
resolveRun(code ?? 1)
})
})
}
async function main() {
const runs = planTestRuns(process.argv.slice(2))
const exitCodes = await Promise.all(runs.map(runVitest))
process.exitCode = exitCodes.find(code => code !== 0) ?? 0
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
await main()
}