/// import react from '@vitejs/plugin-react'; import fs from 'fs'; import path, { resolve } from 'path'; import { URL } from 'url'; import { mergeConfig, defineConfig as vitestConfig } from 'vitest/config'; const CORE_CLIENT_PACKAGES = ['sdk', 'client']; const __dirname = new URL('.', import.meta.url).pathname; const relativePathToAbsolute = (relativePath) => { return path.resolve(process.cwd(), relativePath); }; function tsConfigPathsToAlias() { const json = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), './tsconfig.paths.json'), { encoding: 'utf8' })); const paths = json.compilerOptions.paths; const alias = Object.keys(paths).reduce((acc, key) => { if (key !== '@@/*') { const value = paths[key][0]; acc.push({ find: key, replacement: value, }); } return acc; }, []); alias.unshift( { find: '@nocobase/utils/plugin-symlink', replacement: 'node_modules/@nocobase/utils/plugin-symlink.js', }, { find: '@opentelemetry/resources', replacement: 'node_modules/@opentelemetry/resources/build/src/index.js', }, ); return [ { find: /^~antd\/(.*)/, replacement: 'antd/$1' }, ...alias.map((item) => { return { ...item, replacement: relativePathToAbsolute(item.replacement), }; }), ]; } const defineCommonConfig = () => { return vitestConfig({ root: process.cwd(), resolve: { mainFields: ['module'], }, test: { globals: true, alias: tsConfigPathsToAlias(), testTimeout: 300000, hookTimeout: 300000, silent: !!process.env.GITHUB_ACTIONS, include: ['packages/**/src/**/__tests__/**/*.test.{ts,tsx}'], exclude: [ '**/demos/**', '**/node_modules/**', '**/dist/**', '**/lib/**', '**/es/**', '**/.dumi/**', '**/e2e/**', '**/__e2e__/**', '**/{vitest,commitlint}.config.*', ], watchExclude: [ '**/node_modules/**', '**/dist/**', '**/lib/**', '**/es/**', '**/.dumi/**', '**/e2e/**', '**/__e2e__/**', '**/{vitest,commitlint}.config.*', ], coverage: { provider: 'istanbul', include: ['packages/**/src/**/*.{ts,tsx}'], exclude: [ '**/requirejs.ts', '**/demos/**', '**/swagger/**', '**/.dumi/**', '**/.umi/**', '**/.plugins/**', '**/lib/**', '**/__tests__/**', '**/e2e/**', '**/__e2e__/**', '**/client.js', '**/server.js', '**/*.d.ts', ], }, }, }); }; function getExclude(isServer) { return [ `packages/core/${isServer ? '' : '!'}(${CORE_CLIENT_PACKAGES.join('|')})/**/*`, `packages/**/src/${isServer ? 'client' : 'server'}/**/*`, ]; } const defineServerConfig = () => { return vitestConfig({ test: { setupFiles: resolve(__dirname, './setup/server.ts'), exclude: getExclude(true), }, coverage: { exclude: getExclude(true), }, }); }; const defineClientConfig = () => { return vitestConfig({ plugins: [react()], define: { 'process.env.__TEST__': true, 'process.env.__E2E__': false, global: 'window', }, test: { environment: 'jsdom', css: false, setupFiles: resolve(__dirname, './setup/client.ts'), server: { deps: { inline: ['@juggle/resize-observer', 'clsx'], }, }, exclude: getExclude(false), coverage: { exclude: getExclude(false), }, }, }); }; export const getFilterInclude = (isServer, isCoverage) => { let argv = process.argv .slice(2); argv = argv .filter((item, index) => { if (!item.startsWith('-')) { const pre = argv[index - 1]; if (pre && pre.startsWith('--') && !pre.includes('=')) { return false; } return true; } return false; }); let filterFileOrDir = argv[0]; if (!filterFileOrDir) return {}; const absPath = path.join(process.cwd(), filterFileOrDir); const isDir = fs.existsSync(absPath) && fs.statSync(absPath).isDirectory(); // 如果是文件,则只测试当前文件 if (!isDir) { return { isFile: true, include: [filterFileOrDir], }; } const suffix = isCoverage ? `**/*.{ts,tsx}` : `**/__tests__/**/*.{test,spec}.{ts,tsx}`; // 判断是否为包目录,如果不是包目录,则只测试当前目录 const isPackage = fs.existsSync(path.join(absPath, 'package.json')); if (!isPackage) { return { include: [`${filterFileOrDir}/${suffix}`], }; } // 判断是否为 core 包目录,不分 client 和 server const isCore = absPath.includes('packages/core'); if (isCore) { return { include: [`${filterFileOrDir}/src/${suffix}`], }; } // 插件目录,区分 client 和 server return { include: [`${filterFileOrDir}/src/${isServer ? 'server' : 'client'}/${suffix}`], }; }; export const getReportsDirectory = (isServer) => { let filterFileOrDir = process.argv.slice(2).find((arg) => !arg.startsWith('-')); if (!filterFileOrDir) return; const basePath = `./storage/coverage/`; const isPackage = fs.existsSync(path.join(process.cwd(), filterFileOrDir, 'package.json')); if (isPackage) { let reportsDirectory = `${basePath}${filterFileOrDir.replace('packages/', '')}`; const isCore = filterFileOrDir.includes('packages/core'); if (!isCore) { reportsDirectory = `${reportsDirectory}/${isServer ? 'server' : 'client'}`; } return reportsDirectory; } else { return `${basePath}${filterFileOrDir.replace('packages/', '').replace('src/', '')}`; } }; export const defineConfig = () => { const isServer = process.env.TEST_ENV === 'server-side'; const config = vitestConfig( mergeConfig(defineCommonConfig(), isServer ? defineServerConfig() : defineClientConfig()), ); const { isFile, include: filterInclude } = getFilterInclude(isServer); if (filterInclude) { config.test.include = filterInclude; if (isFile) { // 减少收集的文件 config.test.exclude = []; config.test.coverage = { enabled: false, }; return config; } } const isCoverage = process.argv.includes('--coverage'); if (!isCoverage) { return config; } const { include: coverageInclude } = getFilterInclude(isServer, true); if (coverageInclude) { config.test.coverage.include = coverageInclude; } const reportsDirectory = getReportsDirectory(isServer); if (reportsDirectory) { config.test.coverage.reportsDirectory = reportsDirectory; } return config; };