repterm 0.1.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.
Files changed (97) hide show
  1. package/dist/api/describe.d.ts +18 -0
  2. package/dist/api/describe.d.ts.map +1 -0
  3. package/dist/api/describe.js +33 -0
  4. package/dist/api/describe.js.map +1 -0
  5. package/dist/api/expect.d.ts +43 -0
  6. package/dist/api/expect.d.ts.map +1 -0
  7. package/dist/api/expect.js +167 -0
  8. package/dist/api/expect.js.map +1 -0
  9. package/dist/api/hooks.d.ts +178 -0
  10. package/dist/api/hooks.d.ts.map +1 -0
  11. package/dist/api/hooks.js +231 -0
  12. package/dist/api/hooks.js.map +1 -0
  13. package/dist/api/steps.d.ts +45 -0
  14. package/dist/api/steps.d.ts.map +1 -0
  15. package/dist/api/steps.js +106 -0
  16. package/dist/api/steps.js.map +1 -0
  17. package/dist/api/test.d.ts +101 -0
  18. package/dist/api/test.d.ts.map +1 -0
  19. package/dist/api/test.js +207 -0
  20. package/dist/api/test.js.map +1 -0
  21. package/dist/cli/index.d.ts +7 -0
  22. package/dist/cli/index.d.ts.map +1 -0
  23. package/dist/cli/index.js +203 -0
  24. package/dist/cli/index.js.map +1 -0
  25. package/dist/cli/reporter.d.ts +108 -0
  26. package/dist/cli/reporter.d.ts.map +1 -0
  27. package/dist/cli/reporter.js +368 -0
  28. package/dist/cli/reporter.js.map +1 -0
  29. package/dist/index.d.ts +15 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +24 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/plugin/index.d.ts +47 -0
  34. package/dist/plugin/index.d.ts.map +1 -0
  35. package/dist/plugin/index.js +86 -0
  36. package/dist/plugin/index.js.map +1 -0
  37. package/dist/plugin/withPlugins.d.ts +71 -0
  38. package/dist/plugin/withPlugins.d.ts.map +1 -0
  39. package/dist/plugin/withPlugins.js +101 -0
  40. package/dist/plugin/withPlugins.js.map +1 -0
  41. package/dist/recording/recorder.d.ts +45 -0
  42. package/dist/recording/recorder.d.ts.map +1 -0
  43. package/dist/recording/recorder.js +97 -0
  44. package/dist/recording/recorder.js.map +1 -0
  45. package/dist/runner/artifacts.d.ts +39 -0
  46. package/dist/runner/artifacts.d.ts.map +1 -0
  47. package/dist/runner/artifacts.js +59 -0
  48. package/dist/runner/artifacts.js.map +1 -0
  49. package/dist/runner/config.d.ts +46 -0
  50. package/dist/runner/config.d.ts.map +1 -0
  51. package/dist/runner/config.js +65 -0
  52. package/dist/runner/config.js.map +1 -0
  53. package/dist/runner/filter.d.ts +26 -0
  54. package/dist/runner/filter.d.ts.map +1 -0
  55. package/dist/runner/filter.js +88 -0
  56. package/dist/runner/filter.js.map +1 -0
  57. package/dist/runner/loader.d.ts +32 -0
  58. package/dist/runner/loader.d.ts.map +1 -0
  59. package/dist/runner/loader.js +252 -0
  60. package/dist/runner/loader.js.map +1 -0
  61. package/dist/runner/models.d.ts +261 -0
  62. package/dist/runner/models.d.ts.map +1 -0
  63. package/dist/runner/models.js +5 -0
  64. package/dist/runner/models.js.map +1 -0
  65. package/dist/runner/runner.d.ts +36 -0
  66. package/dist/runner/runner.d.ts.map +1 -0
  67. package/dist/runner/runner.js +216 -0
  68. package/dist/runner/runner.js.map +1 -0
  69. package/dist/runner/scheduler.d.ts +59 -0
  70. package/dist/runner/scheduler.d.ts.map +1 -0
  71. package/dist/runner/scheduler.js +157 -0
  72. package/dist/runner/scheduler.js.map +1 -0
  73. package/dist/runner/worker-runner.d.ts +6 -0
  74. package/dist/runner/worker-runner.d.ts.map +1 -0
  75. package/dist/runner/worker-runner.js +51 -0
  76. package/dist/runner/worker-runner.js.map +1 -0
  77. package/dist/runner/worker.d.ts +54 -0
  78. package/dist/runner/worker.d.ts.map +1 -0
  79. package/dist/runner/worker.js +112 -0
  80. package/dist/runner/worker.js.map +1 -0
  81. package/dist/terminal/session.d.ts +56 -0
  82. package/dist/terminal/session.d.ts.map +1 -0
  83. package/dist/terminal/session.js +126 -0
  84. package/dist/terminal/session.js.map +1 -0
  85. package/dist/terminal/terminal.d.ts +284 -0
  86. package/dist/terminal/terminal.d.ts.map +1 -0
  87. package/dist/terminal/terminal.js +1167 -0
  88. package/dist/terminal/terminal.js.map +1 -0
  89. package/dist/utils/dependencies.d.ts +19 -0
  90. package/dist/utils/dependencies.d.ts.map +1 -0
  91. package/dist/utils/dependencies.js +58 -0
  92. package/dist/utils/dependencies.js.map +1 -0
  93. package/dist/utils/timing.d.ts +55 -0
  94. package/dist/utils/timing.d.ts.map +1 -0
  95. package/dist/utils/timing.js +87 -0
  96. package/dist/utils/timing.js.map +1 -0
  97. package/package.json +43 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Hooks (beforeEach, afterEach) with Named Fixture Support
3
+ * Provides setup and teardown functionality with lazy execution
4
+ *
5
+ * Fixtures are only executed when tests explicitly request them via parameters.
6
+ */
7
+ import { registry } from './test.js';
8
+ /**
9
+ * Global hooks storage with named fixture support
10
+ */
11
+ class HooksRegistry {
12
+ namedBeforeEachHooks = [];
13
+ namedAfterEachHooks = [];
14
+ suiteBeforeAllHooks = new Map();
15
+ suiteAfterAllHooks = new Map();
16
+ /**
17
+ * Register a named beforeEach hook (lazy execution)
18
+ * @param name Fixture name - only executed if test requests this fixture
19
+ * @param fn Hook function
20
+ * @param suiteId Optional suite ID to scope the hook
21
+ */
22
+ registerBeforeEach(name, fn, suiteId) {
23
+ this.namedBeforeEachHooks.push({ name, fn, suiteId });
24
+ }
25
+ /**
26
+ * Register a named afterEach hook (lazy cleanup)
27
+ * @param name Fixture name - only executed if the corresponding beforeEach was run
28
+ * @param fn Hook function
29
+ * @param suiteId Optional suite ID to scope the hook
30
+ */
31
+ registerAfterEach(name, fn, suiteId) {
32
+ this.namedAfterEachHooks.push({ name, fn, suiteId });
33
+ }
34
+ /**
35
+ * Register a beforeAll hook for a suite
36
+ * @param name Optional fixture name
37
+ * @param fn Hook function
38
+ * @param suiteId Suite ID to scope the hook
39
+ */
40
+ registerBeforeAll(name, fn, suiteId) {
41
+ if (!this.suiteBeforeAllHooks.has(suiteId)) {
42
+ this.suiteBeforeAllHooks.set(suiteId, []);
43
+ }
44
+ this.suiteBeforeAllHooks.get(suiteId).push({ name, fn, suiteId });
45
+ }
46
+ /**
47
+ * Register an afterAll hook for a suite
48
+ * @param name Optional fixture name
49
+ * @param fn Hook function
50
+ * @param suiteId Suite ID to scope the hook
51
+ */
52
+ registerAfterAll(name, fn, suiteId) {
53
+ if (!this.suiteAfterAllHooks.has(suiteId)) {
54
+ this.suiteAfterAllHooks.set(suiteId, []);
55
+ }
56
+ this.suiteAfterAllHooks.get(suiteId).push({ name, fn, suiteId });
57
+ }
58
+ /**
59
+ * Get the chain of suite IDs from root to the given suite
60
+ */
61
+ getSuiteChain(suite) {
62
+ const chain = [];
63
+ let current = suite;
64
+ while (current) {
65
+ chain.unshift(current.id);
66
+ current = current.parent;
67
+ }
68
+ return chain;
69
+ }
70
+ /**
71
+ * Check if a hook should run for a given suite
72
+ */
73
+ shouldRunHookForSuite(hookSuiteId, suiteChain) {
74
+ if (hookSuiteId === undefined) {
75
+ return suiteChain.length === 0;
76
+ }
77
+ return suiteChain.includes(hookSuiteId);
78
+ }
79
+ /**
80
+ * Run beforeEach hooks for requested fixtures only (lazy execution)
81
+ * @param context Test context
82
+ * @param suite Optional suite to filter hooks
83
+ * @param requiredFixtures Set of fixture names requested by the test
84
+ * @returns Augmented context with fixture values and set of executed fixture names
85
+ */
86
+ async runBeforeEachFor(context, suite, requiredFixtures) {
87
+ let augmentedContext = { ...context };
88
+ const suiteChain = suite ? this.getSuiteChain(suite) : [];
89
+ const executedFixtures = new Set();
90
+ for (const entry of this.namedBeforeEachHooks) {
91
+ // Only run if fixture is requested AND belongs to correct suite
92
+ if (requiredFixtures.has(entry.name) &&
93
+ this.shouldRunHookForSuite(entry.suiteId, suiteChain)) {
94
+ const result = await entry.fn(augmentedContext);
95
+ if (result && typeof result === 'object') {
96
+ augmentedContext = { ...augmentedContext, ...result };
97
+ }
98
+ executedFixtures.add(entry.name);
99
+ }
100
+ }
101
+ return { context: augmentedContext, executedFixtures };
102
+ }
103
+ /**
104
+ * Run afterEach hooks for executed fixtures only
105
+ * @param context Test context
106
+ * @param suite Optional suite to filter hooks
107
+ * @param executedFixtures Set of fixture names that were actually executed
108
+ */
109
+ async runAfterEachFor(context, suite, executedFixtures) {
110
+ const suiteChain = suite ? this.getSuiteChain(suite) : [];
111
+ // Run in reverse order for proper cleanup
112
+ for (let i = this.namedAfterEachHooks.length - 1; i >= 0; i--) {
113
+ const entry = this.namedAfterEachHooks[i];
114
+ if (executedFixtures.has(entry.name) &&
115
+ this.shouldRunHookForSuite(entry.suiteId, suiteChain)) {
116
+ await entry.fn(context);
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * Run beforeAll hooks for a suite
122
+ * @param suite The suite to run hooks for
123
+ * @param inheritedContext Context inherited from parent suites
124
+ * @returns Augmented context with values from beforeAll hooks
125
+ */
126
+ async runBeforeAllFor(suite, inheritedContext = {}) {
127
+ const hooks = this.suiteBeforeAllHooks.get(suite.id) ?? [];
128
+ let context = { ...inheritedContext };
129
+ for (const entry of hooks) {
130
+ const result = await entry.fn(context);
131
+ if (result && typeof result === 'object') {
132
+ context = { ...context, ...result };
133
+ }
134
+ }
135
+ return context;
136
+ }
137
+ /**
138
+ * Run afterAll hooks for a suite
139
+ * @param suite The suite to run hooks for
140
+ * @param context Context to pass to hooks
141
+ */
142
+ async runAfterAllFor(suite, context = {}) {
143
+ const hooks = this.suiteAfterAllHooks.get(suite.id) ?? [];
144
+ // Run in reverse order for proper cleanup
145
+ for (let i = hooks.length - 1; i >= 0; i--) {
146
+ const entry = hooks[i];
147
+ await entry.fn(context);
148
+ }
149
+ }
150
+ /**
151
+ * Clear all hooks (for testing)
152
+ */
153
+ clear() {
154
+ this.namedBeforeEachHooks = [];
155
+ this.namedAfterEachHooks = [];
156
+ this.suiteBeforeAllHooks.clear();
157
+ this.suiteAfterAllHooks.clear();
158
+ }
159
+ }
160
+ // Global hooks registry
161
+ export const hooksRegistry = new HooksRegistry();
162
+ /**
163
+ * Register a named beforeEach hook with lazy execution
164
+ *
165
+ * 只有测试函数参数中请求了该 Fixture,才会执行此 Hook。
166
+ *
167
+ * @param name Fixture 名称(必须与返回对象的 key 一致)
168
+ * @param fn Hook 函数,返回对象会被注入到 context
169
+ *
170
+ * @example
171
+ * describe('my tests', () => {
172
+ * // 注册名为 'tmpDir' 的 fixture
173
+ * beforeEach('tmpDir', async () => {
174
+ * const tmpDir = await fs.mkdtemp('/tmp/test-');
175
+ * return { tmpDir };
176
+ * });
177
+ *
178
+ * afterEach('tmpDir', async ({ tmpDir }) => {
179
+ * if (tmpDir) await fs.rm(tmpDir, { recursive: true });
180
+ * });
181
+ *
182
+ * // 这个测试会触发 tmpDir fixture
183
+ * test('uses tmpDir', async ({ terminal, tmpDir }) => {
184
+ * await terminal.run(`ls ${tmpDir}`);
185
+ * });
186
+ *
187
+ * // 这个测试不会触发 tmpDir fixture
188
+ * test('no fixture needed', async ({ terminal }) => {
189
+ * await terminal.run('echo hello');
190
+ * });
191
+ * });
192
+ */
193
+ export function beforeEach(name, fn) {
194
+ const suiteId = registry.getCurrentSuiteId();
195
+ hooksRegistry.registerBeforeEach(name, fn, suiteId);
196
+ }
197
+ /**
198
+ * Register a named afterEach hook
199
+ *
200
+ * 只有对应的 beforeEach 被执行了,此 Hook 才会执行。
201
+ *
202
+ * @param name Fixture 名称(与 beforeEach 注册的名称一致)
203
+ * @param fn Hook 函数
204
+ */
205
+ export function afterEach(name, fn) {
206
+ const suiteId = registry.getCurrentSuiteId();
207
+ hooksRegistry.registerAfterEach(name, fn, suiteId);
208
+ }
209
+ export function beforeAll(nameOrFn, maybeFn) {
210
+ const suiteId = registry.getCurrentSuiteId();
211
+ if (!suiteId) {
212
+ throw new Error('beforeAll must be called inside a describe() block');
213
+ }
214
+ const name = typeof nameOrFn === 'string' ? nameOrFn : undefined;
215
+ const fn = typeof nameOrFn === 'function' ? nameOrFn : maybeFn;
216
+ hooksRegistry.registerBeforeAll(name, fn, suiteId);
217
+ }
218
+ export function afterAll(nameOrFn, maybeFn) {
219
+ const suiteId = registry.getCurrentSuiteId();
220
+ if (!suiteId) {
221
+ throw new Error('afterAll must be called inside a describe() block');
222
+ }
223
+ const name = typeof nameOrFn === 'string' ? nameOrFn : undefined;
224
+ const fn = typeof nameOrFn === 'function' ? nameOrFn : maybeFn;
225
+ hooksRegistry.registerAfterAll(name, fn, suiteId);
226
+ }
227
+ /**
228
+ * Export hooks registry for runner
229
+ */
230
+ export { hooksRegistry as hooks };
231
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/api/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * test.step with step reporting
3
+ * Provides named steps within tests for better organization
4
+ */
5
+ /**
6
+ * Step 录制选项
7
+ */
8
+ export interface StepRecordingOptions {
9
+ /** 步骤内命令的打字速度 (ms/字符) */
10
+ typingSpeed?: number;
11
+ /** 步骤结束后暂停时间 (ms) */
12
+ pauseAfter?: number;
13
+ /** 步骤开始前暂停时间 (ms) */
14
+ pauseBefore?: number;
15
+ /** 在录制中显示步骤标题作为注释 */
16
+ showStepTitle?: boolean;
17
+ }
18
+ /**
19
+ * 获取当前 step 的录制选项
20
+ */
21
+ export declare function getCurrentStepOptions(): StepRecordingOptions | null;
22
+ /**
23
+ * 获取当前 step 的名称
24
+ */
25
+ export declare function getCurrentStepName(): string | null;
26
+ /**
27
+ * 检查是否应该显示步骤标题(只显示一次)
28
+ */
29
+ export declare function shouldShowStepTitle(): boolean;
30
+ /**
31
+ * 标记步骤标题已显示
32
+ */
33
+ export declare function markStepTitleShown(): void;
34
+ /**
35
+ * Execute a named step within a test
36
+ * 支持两种调用方式:
37
+ * - step(name, fn)
38
+ * - step(name, options, fn)
39
+ */
40
+ export declare function step<T>(name: string, optionsOrFn: StepRecordingOptions | (() => Promise<T>), maybeFn?: () => Promise<T>): Promise<T>;
41
+ /**
42
+ * Clear steps (called after each test)
43
+ */
44
+ export declare function clearSteps(): void;
45
+ //# sourceMappingURL=steps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../../src/api/steps.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qBAAqB;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,qBAAqB;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qBAAqB;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAsBD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAElD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAG7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,CAAC,EAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,oBAAoB,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,EACtD,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACzB,OAAO,CAAC,CAAC,CAAC,CAuCZ;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAKjC"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * test.step with step reporting
3
+ * Provides named steps within tests for better organization
4
+ */
5
+ import { randomBytes } from 'crypto';
6
+ /**
7
+ * Current step context (for tracking nested steps)
8
+ */
9
+ let currentSteps = [];
10
+ /**
11
+ * 当前 step 配置上下文
12
+ */
13
+ let currentStepOptions = null;
14
+ /**
15
+ * 当前 step 名称
16
+ */
17
+ let currentStepName = null;
18
+ /**
19
+ * 当前 step 标题是否已显示
20
+ */
21
+ let stepTitleShown = false;
22
+ /**
23
+ * 获取当前 step 的录制选项
24
+ */
25
+ export function getCurrentStepOptions() {
26
+ return currentStepOptions;
27
+ }
28
+ /**
29
+ * 获取当前 step 的名称
30
+ */
31
+ export function getCurrentStepName() {
32
+ return currentStepName;
33
+ }
34
+ /**
35
+ * 检查是否应该显示步骤标题(只显示一次)
36
+ */
37
+ export function shouldShowStepTitle() {
38
+ if (stepTitleShown)
39
+ return false;
40
+ return currentStepOptions?.showStepTitle ?? false;
41
+ }
42
+ /**
43
+ * 标记步骤标题已显示
44
+ */
45
+ export function markStepTitleShown() {
46
+ stepTitleShown = true;
47
+ }
48
+ /**
49
+ * Execute a named step within a test
50
+ * 支持两种调用方式:
51
+ * - step(name, fn)
52
+ * - step(name, options, fn)
53
+ */
54
+ export async function step(name, optionsOrFn, maybeFn) {
55
+ const options = typeof optionsOrFn === 'function' ? {} : optionsOrFn;
56
+ const fn = typeof optionsOrFn === 'function' ? optionsOrFn : maybeFn;
57
+ const stepObj = {
58
+ id: generateId(),
59
+ type: 'step',
60
+ name,
61
+ payload: null,
62
+ };
63
+ // Add to current steps
64
+ currentSteps.push(stepObj);
65
+ // 保存之前的配置
66
+ const previousOptions = currentStepOptions;
67
+ const previousName = currentStepName;
68
+ // 设置当前 step 配置
69
+ currentStepOptions = options;
70
+ currentStepName = name;
71
+ stepTitleShown = false; // 重置标题显示状态
72
+ try {
73
+ // Execute the step function
74
+ const result = await fn();
75
+ return result;
76
+ }
77
+ catch (error) {
78
+ // Attach error info to step
79
+ stepObj.payload = {
80
+ error: error.message,
81
+ stack: error.stack,
82
+ };
83
+ throw error;
84
+ }
85
+ finally {
86
+ // 恢复之前的配置
87
+ currentStepOptions = previousOptions;
88
+ currentStepName = previousName;
89
+ }
90
+ }
91
+ /**
92
+ * Clear steps (called after each test)
93
+ */
94
+ export function clearSteps() {
95
+ currentSteps = [];
96
+ currentStepOptions = null;
97
+ currentStepName = null;
98
+ stepTitleShown = false;
99
+ }
100
+ /**
101
+ * Generate a unique step ID
102
+ */
103
+ function generateId() {
104
+ return randomBytes(8).toString('hex');
105
+ }
106
+ //# sourceMappingURL=steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steps.js","sourceRoot":"","sources":["../../src/api/steps.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAmBrC;;GAEG;AACH,IAAI,YAAY,GAAW,EAAE,CAAC;AAE9B;;GAEG;AACH,IAAI,kBAAkB,GAAgC,IAAI,CAAC;AAE3D;;GAEG;AACH,IAAI,eAAe,GAAkB,IAAI,CAAC;AAE1C;;GAEG;AACH,IAAI,cAAc,GAAY,KAAK,CAAC;AAEpC;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,cAAc;QAAE,OAAO,KAAK,CAAC;IACjC,OAAO,kBAAkB,EAAE,aAAa,IAAI,KAAK,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,cAAc,GAAG,IAAI,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,IAAY,EACZ,WAAsD,EACtD,OAA0B;IAE1B,MAAM,OAAO,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACrE,MAAM,EAAE,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAQ,CAAC;IAEtE,MAAM,OAAO,GAAS;QACpB,EAAE,EAAE,UAAU,EAAE;QAChB,IAAI,EAAE,MAAM;QACZ,IAAI;QACJ,OAAO,EAAE,IAAI;KACd,CAAC;IAEF,uBAAuB;IACvB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE3B,UAAU;IACV,MAAM,eAAe,GAAG,kBAAkB,CAAC;IAC3C,MAAM,YAAY,GAAG,eAAe,CAAC;IAErC,eAAe;IACf,kBAAkB,GAAG,OAAO,CAAC;IAC7B,eAAe,GAAG,IAAI,CAAC;IACvB,cAAc,GAAG,KAAK,CAAC,CAAE,WAAW;IAEpC,IAAI,CAAC;QACH,4BAA4B;QAC5B,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4BAA4B;QAC5B,OAAO,CAAC,OAAO,GAAG;YAChB,KAAK,EAAG,KAAe,CAAC,OAAO;YAC/B,KAAK,EAAG,KAAe,CAAC,KAAK;SAC9B,CAAC;QACF,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,UAAU;QACV,kBAAkB,GAAG,eAAe,CAAC;QACrC,eAAe,GAAG,YAAY,CAAC;IACjC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,YAAY,GAAG,EAAE,CAAC;IAClB,kBAAkB,GAAG,IAAI,CAAC;IAC1B,eAAe,GAAG,IAAI,CAAC;IACvB,cAAc,GAAG,KAAK,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,SAAS,UAAU;IACjB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Playwright-style test() registration and suite registry
3
+ */
4
+ import type { TestCase, TestFunction, TestSuite, TestOptions } from '../runner/models.js';
5
+ /**
6
+ * Global registry of test suites and cases
7
+ */
8
+ declare class TestRegistry {
9
+ private suites;
10
+ private fileSuites;
11
+ private suiteStack;
12
+ private defaultSuite;
13
+ constructor();
14
+ /**
15
+ * Get the current suite (top of stack)
16
+ */
17
+ private getCurrentSuite;
18
+ /**
19
+ * Get the current suite ID (for hooks registration)
20
+ */
21
+ getCurrentSuiteId(): string | undefined;
22
+ /** Set by loader when loading a file so dynamically imported test code uses this suite (same registry instance). */
23
+ __pendingFileSuite?: TestSuite;
24
+ /**
25
+ * Register a test case
26
+ */
27
+ registerTest(name: string, fn: TestFunction, options?: TestOptions): void;
28
+ /**
29
+ * Get all registered test suites
30
+ */
31
+ getSuites(): TestSuite[];
32
+ /**
33
+ * Get only root-level suites for execution
34
+ * This returns file-level suites if present, otherwise suites without parents
35
+ */
36
+ getRootSuites(): TestSuite[];
37
+ /**
38
+ * Get a specific suite by ID
39
+ */
40
+ getSuite(id: string): TestSuite | undefined;
41
+ /**
42
+ * Push a new suite onto the stack (for describe() blocks)
43
+ */
44
+ pushSuite(suite: TestSuite): void;
45
+ /**
46
+ * Pop the current suite from the stack (end of describe() block)
47
+ */
48
+ popSuite(): void;
49
+ /**
50
+ * Set the current suite (for describe() blocks) - legacy compatibility
51
+ */
52
+ setCurrentSuite(suite: TestSuite): void;
53
+ /**
54
+ * Set the current file and create/reuse a file-level suite.
55
+ * Uses full path as key so different files (e.g. same basename in different dirs) get separate suites.
56
+ * @returns the file suite (for loader to set pending global when loading dynamic files)
57
+ */
58
+ setCurrentFile(filePath: string): TestSuite;
59
+ /**
60
+ * Reset to default suite
61
+ */
62
+ resetCurrentSuite(): void;
63
+ /**
64
+ * Remove and return tests that were registered to the default suite.
65
+ * Used by the loader to reassign tests that landed on the default suite (e.g. due to
66
+ * async module evaluation) to the correct file-level suite.
67
+ */
68
+ takeTestsFromDefaultSuite(): TestCase[];
69
+ /**
70
+ * Clear all registered tests (for testing)
71
+ */
72
+ clear(): void;
73
+ /**
74
+ * Generate a unique test ID
75
+ */
76
+ private generateId;
77
+ }
78
+ export declare const registry: TestRegistry;
79
+ /**
80
+ * Playwright-style test() function
81
+ * Registers a test case with the current suite
82
+ *
83
+ * @example
84
+ * // 普通测试
85
+ * test('name', async ({ terminal }) => { ... });
86
+ *
87
+ * // 录制测试
88
+ * test('name', { record: true }, async ({ terminal }) => { ... });
89
+ */
90
+ export declare function test(name: string, fn: TestFunction): void;
91
+ export declare function test(name: string, options: TestOptions, fn: TestFunction): void;
92
+ /**
93
+ * Get all registered tests
94
+ */
95
+ export declare function getTests(): TestSuite[];
96
+ /**
97
+ * Clear all registered tests
98
+ */
99
+ export declare function clearTests(): void;
100
+ export {};
101
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/api/test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG1F;;GAEG;AACH,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,YAAY,CAAY;;IAehC;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,iBAAiB,IAAI,MAAM,GAAG,SAAS;IAMvC,oHAAoH;IACpH,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAE/B;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI;IAczE;;OAEG;IACH,SAAS,IAAI,SAAS,EAAE;IASxB;;;OAGG;IACH,aAAa,IAAI,SAAS,EAAE;IAe5B;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI3C;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAmBjC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAMhB;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAIvC;;;;OAIG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAuB3C;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAIzB;;;;OAIG;IACH,yBAAyB,IAAI,QAAQ,EAAE;IAMvC;;OAEG;IACH,KAAK,IAAI,IAAI;IAcb;;OAEG;IACH,OAAO,CAAC,UAAU;CAGnB;AAUD,eAAO,MAAM,QAAQ,EAAE,YAAoD,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,IAAI,CAAC;AAC3D,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,GAAG,IAAI,CAAC;AAYjF;;GAEG;AACH,wBAAgB,QAAQ,IAAI,SAAS,EAAE,CAEtC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}