1- import fs from 'node:fs' ;
2- import { createRequire } from 'node:module' ;
3- import path from 'node:path' ;
4- import utils from './utils.js' ;
1+ import fs from 'node:fs'
2+ import { createRequire } from 'node:module'
3+ import path from 'node:path'
4+ import utils from './utils.js'
55
66const printHeader = ( utils && utils . printHeader ) || ( utils && utils . default && utils . default . printHeader )
77
8+ // 简化说明:
9+ // - 本文件为 FreeEye 插件的客户端运行器(用于加载插件的 tests 并顺序执行)。
10+ // - 为了降低运行时复杂度,我们将插件根定为本文件所在目录(`PLUGIN_ROOT = __dirname`),
11+ // 不再向上遍历查找配置文件或插件目录。这样实现假定项目中该文件位置稳定。
12+ // - 配置加载采用同步的 `require` 风格(通过 `createRequire` 创建的 `pluginRequire`),
13+ // 以便在 CommonJS 环境或混合模块环境中更可靠地加载 `config.js`(`module.exports` 或 `export default`)。
14+ // 如果你的 `config.js` 是严格 ESM-only(例如使用 `export` 且包含顶级 `await`),
15+ // 需要改回基于动态 `import()` 的实现。
816const TEST_PACKAGE_DIR = 'checkpoints'
9- const PLUGIN_RELATIVE_PATH = path . join ( 'packages' , 'core' , 'src' , 'modules' , 'plugin' , 'free-eye' )
1017
11- function locatePluginRoot ( ) {
12- const localConfig = path . join ( __dirname , 'config.json' )
13- if ( fs . existsSync ( localConfig ) ) {
14- return __dirname
15- }
16-
17- let current = __dirname
18- for ( let i = 0 ; i < 8 ; i += 1 ) {
19- const candidate = path . join ( current , PLUGIN_RELATIVE_PATH )
20- if ( fs . existsSync ( path . join ( candidate , 'config.json' ) ) ) {
21- return candidate
22- }
23- const parent = path . dirname ( current )
24- if ( parent === current ) {
25- break
26- }
27- current = parent
28- }
29- return __dirname
30- }
31-
32- const PLUGIN_ROOT = locatePluginRoot ( )
18+ // 插件根目录(简化为当前目录)
19+ const PLUGIN_ROOT = __dirname
20+ // 用于在插件目录上下文中同步加载模块(config、tests 等)
3321const pluginRequire = createRequire ( path . join ( PLUGIN_ROOT , 'index.js' ) )
3422
3523function resolveTestsDir ( customDir ) {
@@ -55,7 +43,11 @@ async function loadAllTests (globalConfig, testsDir) {
5543 for ( const file of files ) {
5644 const modulePath = path . join ( resolvedDir , file )
5745
46+ // 使用 pluginRequire 同步加载测试模块。这样做的好处:
47+ // - 保持加载行为一致(在 CommonJS / 混合项目中更可靠)
48+ // - 避免动态 import 带来的 URL 转换与异步模块解析复杂性
5849 const module = pluginRequire ( modulePath )
50+ // 测试模块可以导出 `getClientTests`(命名导出或 default 导出中的方法)
5951 const getClientTests = module . getClientTests || ( module . default && module . default . getClientTests )
6052 if ( typeof getClientTests === 'function' ) {
6153 for ( const testCls of getClientTests ( ) ) {
@@ -70,6 +62,8 @@ async function loadAllTests (globalConfig, testsDir) {
7062
7163function getNextTest ( todoTests , doneTests ) {
7264 for ( const testCls of todoTests ) {
65+ // 检查此测试类的前置依赖(prereqs)是否全部完成。
66+ // 如果全部满足,则返回该测试类作为下一要执行的任务。
7367 let allPrereqsDone = true
7468 for ( const testTag of testCls . getPrereqs ( ) ) {
7569 if ( ! doneTests . includes ( testTag ) ) {
@@ -86,31 +80,30 @@ function getNextTest (todoTests, doneTests) {
8680
8781async function runTests ( options = { } ) {
8882 const { configPath, testsDir } = options
89- const preferredConfigPath = configPath && configPath . length > 0
90- ? ( path . isAbsolute ( configPath ) ? configPath : path . join ( PLUGIN_ROOT , configPath ) )
91- : null
92- const fallbackConfigPath = path . join ( PLUGIN_ROOT , 'config.json' )
93-
94- const configCandidates = Array . from ( new Set ( [ preferredConfigPath , fallbackConfigPath ] . filter ( Boolean ) ) )
95-
96- let globalConfig
97- let lastError
98- for ( const candidatePath of configCandidates ) {
99- try {
100- if ( ! fs . existsSync ( candidatePath ) ) {
101- lastError = new Error ( `Config file not found: ${ candidatePath } ` )
102- continue
103- }
104- const configData = fs . readFileSync ( candidatePath , 'utf8' )
105- globalConfig = JSON . parse ( configData )
106- break
107- } catch ( error ) {
108- lastError = new Error ( `Error reading config file (${ candidatePath } ): ${ error . message } ` )
83+ // 配置文件解析规则(简化):
84+ // - 如果传入了 `configPath`,则优先使用它(相对路径相对于插件根)。
85+ // - 否则使用插件根下的 `config.js`。
86+ // - 使用 `pluginRequire` 同步加载配置模块;接受 `module.exports` 或 `export default` 两种形式。
87+ let preferredConfigPath = path . join ( PLUGIN_ROOT , 'config.js' )
88+ if ( configPath && configPath . length > 0 ) {
89+ if ( path . isAbsolute ( configPath ) ) {
90+ preferredConfigPath = configPath
91+ } else {
92+ preferredConfigPath = path . join ( PLUGIN_ROOT , configPath )
10993 }
11094 }
11195
112- if ( ! globalConfig ) {
113- throw lastError || new Error ( 'Unable to load FreeEye config.' )
96+ if ( ! fs . existsSync ( preferredConfigPath ) ) {
97+ throw new Error ( `Config file not found: ${ preferredConfigPath } ` )
98+ }
99+
100+ let globalConfig
101+ try {
102+ // 这里期望 config.js 导出一个对象,包含如 mainConfig.server.plugin.free_eye 的合并结果或默认设置
103+ const mod = pluginRequire ( preferredConfigPath )
104+ globalConfig = mod && ( mod . default || mod )
105+ } catch ( err ) {
106+ throw new Error ( `Error loading config (${ preferredConfigPath } ): ${ err . message } ` )
114107 }
115108
116109 const globalResults = { }
@@ -165,4 +158,4 @@ if (require.main === module) {
165158 } )
166159}
167160
168- export default { runTests } ;
161+ export default { runTests }
0 commit comments