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,216 @@
1
+ /**
2
+ * Single-runner execution pipeline
3
+ * Executes test suites and cases, manages lifecycle with onion execution model
4
+ */
5
+ import { createTerminal } from '../terminal/terminal.js';
6
+ import { hooksRegistry } from '../api/hooks.js';
7
+ import { clearSteps } from '../api/steps.js';
8
+ /**
9
+ * Extract parameter names from a test function
10
+ * Parses destructured parameters like ({ terminal, tmpDir }) => ...
11
+ */
12
+ function getTestFunctionParameters(fn) {
13
+ const fnStr = fn.toString();
14
+ // Match destructured object parameter: ({ param1, param2, ... })
15
+ const match = fnStr.match(/\(\s*\{\s*([^}]*)\s*\}/);
16
+ if (!match)
17
+ return [];
18
+ return match[1]
19
+ .split(',')
20
+ .map((p) => {
21
+ // Handle cases like "param: Type" or "param = default" or just "param"
22
+ const trimmed = p.trim();
23
+ const paramName = trimmed.split(/[:\s=]/)[0].trim();
24
+ return paramName;
25
+ })
26
+ .filter(Boolean);
27
+ }
28
+ /**
29
+ * Execute tests in a suite (without lifecycle hooks)
30
+ * This is the internal function for running tests only
31
+ */
32
+ async function runTestsInSuite(suite, options, inheritedContext = {}) {
33
+ const results = [];
34
+ for (const testCase of suite.tests) {
35
+ const result = await runTest(testCase, suite, options, inheritedContext);
36
+ results.push(result);
37
+ }
38
+ return results;
39
+ }
40
+ /**
41
+ * Execute a single test suite with lifecycle hooks (onion model)
42
+ *
43
+ * Execution order:
44
+ * 1. Run beforeAll hooks for this suite
45
+ * 2. Merge beforeAll context with inherited context
46
+ * 3. Run tests in this suite
47
+ * 4. Recursively run child suites
48
+ * 5. Run afterAll hooks for this suite
49
+ */
50
+ export async function runSuite(suite, options, inheritedContext = {}) {
51
+ const results = [];
52
+ let suiteContext = { ...inheritedContext };
53
+ try {
54
+ // 1. Run beforeAll hooks for this suite
55
+ suiteContext = await hooksRegistry.runBeforeAllFor(suite, inheritedContext);
56
+ // 2. Run tests in this suite with the merged context
57
+ const testResults = await runTestsInSuite(suite, options, suiteContext);
58
+ results.push(...testResults);
59
+ // 3. Recursively run child suites with the merged context
60
+ if (suite.suites && suite.suites.length > 0) {
61
+ for (const childSuite of suite.suites) {
62
+ const childResults = await runSuite(childSuite, options, suiteContext);
63
+ results.push(...childResults);
64
+ }
65
+ }
66
+ }
67
+ finally {
68
+ // 4. Run afterAll hooks for this suite (always, even if tests failed)
69
+ try {
70
+ await hooksRegistry.runAfterAllFor(suite, suiteContext);
71
+ }
72
+ catch (hookError) {
73
+ console.error(`Error in afterAll hook for suite "${suite.name}":`, hookError);
74
+ }
75
+ }
76
+ return results;
77
+ }
78
+ /**
79
+ * 获取从 suite 继承的 record 配置
80
+ */
81
+ function getInheritedRecordConfig(suite) {
82
+ if (suite.options?.record !== undefined) {
83
+ return suite.options.record;
84
+ }
85
+ if (suite.parent) {
86
+ return getInheritedRecordConfig(suite.parent);
87
+ }
88
+ return undefined;
89
+ }
90
+ /**
91
+ * Execute a single test case
92
+ */
93
+ export async function runTest(testCase, suite, options, inheritedContext = {}) {
94
+ // Build suite path
95
+ const suitePath = [suite.name];
96
+ let parent = suite.parent;
97
+ while (parent && parent.id !== 'default' && !parent.id.startsWith('file-') && !parent.id.startsWith('dir-')) {
98
+ suitePath.unshift(parent.name);
99
+ parent = parent.parent;
100
+ }
101
+ const startTime = Date.now();
102
+ const { config, artifactManager, onResult, onTestStart } = options;
103
+ // 确定执行模式:
104
+ // 1. testRecordConfig: 测试级别或 suite 级别的 record 配置
105
+ // 2. cliRecordMode: CLI --record 标志
106
+ // 3. shouldRecord: 只有 CLI 和 test 都启用时才完整录制(asciinema + tmux + 打字效果)
107
+ // 4. shouldUsePtyOnly: test 启用但 CLI 未启用时使用 PTY-only(无录制、无打字效果)
108
+ const testRecordConfig = testCase.options?.record ?? getInheritedRecordConfig(suite);
109
+ const cliRecordMode = config.record?.enabled ?? false;
110
+ const shouldRecord = cliRecordMode && testRecordConfig; // 完整录制模式
111
+ const shouldUsePtyOnly = testRecordConfig && !cliRecordMode; // PTY-only 模式
112
+ // Get recording path for this test (only in recording mode)
113
+ const recordingPath = shouldRecord
114
+ ? artifactManager.getCastPath(testCase.id)
115
+ : undefined;
116
+ // 在 hooks 运行前通知测试即将开始,确保 suite 名称先于 hook 输出打印
117
+ onTestStart?.({ suitePath, testName: testCase.name });
118
+ // Create terminal for test
119
+ // Use user's actual terminal size (like simple-example.js)
120
+ const terminal = createTerminal({
121
+ cols: process.stdout.columns || 120,
122
+ rows: process.stdout.rows || 40,
123
+ recording: shouldRecord,
124
+ ptyOnly: shouldUsePtyOnly,
125
+ recordingPath,
126
+ promptLineCount: config.terminal?.promptLineCount,
127
+ });
128
+ // Build initial test context with inherited context from beforeAll hooks
129
+ let context = {
130
+ terminal,
131
+ ...inheritedContext,
132
+ ...testCase.fixtures,
133
+ };
134
+ // Track which fixtures were actually executed (for cleanup)
135
+ let executedFixtures = new Set();
136
+ try {
137
+ // Extract required fixtures from test function parameters
138
+ const requiredFixtures = new Set(getTestFunctionParameters(testCase.fn));
139
+ // Run beforeEach hooks only for requested fixtures (lazy execution)
140
+ const hookResult = await hooksRegistry.runBeforeEachFor(context, suite, requiredFixtures);
141
+ context = hookResult.context;
142
+ executedFixtures = hookResult.executedFixtures;
143
+ // Set timeout
144
+ const timeout = testCase.timeout ?? config.timeouts.testMs;
145
+ await Promise.race([
146
+ testCase.fn(context),
147
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Test timeout after ${timeout}ms`)), timeout)),
148
+ ]);
149
+ // Test passed
150
+ const durationMs = Date.now() - startTime;
151
+ const result = {
152
+ id: `result-${testCase.id}`,
153
+ suiteId: suite.id,
154
+ caseId: testCase.id,
155
+ suiteName: suite.name,
156
+ suitePath,
157
+ caseName: testCase.name,
158
+ status: 'pass',
159
+ durationMs,
160
+ artifacts: [],
161
+ recordingPath,
162
+ };
163
+ onResult?.(result);
164
+ return result;
165
+ }
166
+ catch (error) {
167
+ // Test failed
168
+ const durationMs = Date.now() - startTime;
169
+ const result = {
170
+ id: `result-${testCase.id}`,
171
+ suiteId: suite.id,
172
+ caseId: testCase.id,
173
+ suiteName: suite.name,
174
+ suitePath,
175
+ caseName: testCase.name,
176
+ status: 'fail',
177
+ durationMs,
178
+ error: {
179
+ message: error.message,
180
+ stack: error.stack,
181
+ expected: error.expected,
182
+ actual: error.actual,
183
+ commandLogs: terminal.getCommandLogs(),
184
+ },
185
+ artifacts: [],
186
+ recordingPath,
187
+ };
188
+ onResult?.(result);
189
+ return result;
190
+ }
191
+ finally {
192
+ // Cleanup
193
+ clearSteps();
194
+ // Run afterEach hooks only for fixtures that were actually executed
195
+ try {
196
+ await hooksRegistry.runAfterEachFor(context, suite, executedFixtures);
197
+ }
198
+ catch (hookError) {
199
+ console.error('Error in afterEach hook:', hookError);
200
+ }
201
+ // Cleanup terminal
202
+ await terminal.close();
203
+ }
204
+ }
205
+ /**
206
+ * Execute all test suites with lifecycle hooks
207
+ */
208
+ export async function runAllSuites(suites, options) {
209
+ const allResults = [];
210
+ for (const suite of suites) {
211
+ const results = await runSuite(suite, options);
212
+ allResults.push(...results);
213
+ }
214
+ return allResults;
215
+ }
216
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/runner/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Scheduler + aggregation for parallel test execution
3
+ * Distributes tests across workers and aggregates results
4
+ */
5
+ import type { TestSuite, RunResult } from './models.js';
6
+ import type { RunConfig } from './config.js';
7
+ export interface SchedulerOptions {
8
+ config: RunConfig;
9
+ artifactBaseDir: string;
10
+ onResult?: (result: RunResult) => void;
11
+ }
12
+ /**
13
+ * Parallel test scheduler
14
+ */
15
+ export declare class Scheduler {
16
+ private options;
17
+ private workers;
18
+ private results;
19
+ private pendingSuites;
20
+ private activeSuites;
21
+ constructor(options: SchedulerOptions);
22
+ /**
23
+ * Run test suites in parallel across workers
24
+ */
25
+ run(suites: TestSuite[]): Promise<RunResult[]>;
26
+ /**
27
+ * Initialize worker pool
28
+ */
29
+ private initWorkers;
30
+ /**
31
+ * Wait for all workers to signal ready
32
+ */
33
+ private waitForWorkers;
34
+ /**
35
+ * Distribute suites to available workers
36
+ */
37
+ private distributeSuites;
38
+ /**
39
+ * Handle worker completion
40
+ */
41
+ private handleWorkerDone;
42
+ /**
43
+ * Handle worker error
44
+ */
45
+ private handleWorkerError;
46
+ /**
47
+ * Wait for all work to complete
48
+ */
49
+ private waitForCompletion;
50
+ /**
51
+ * Cleanup worker pool
52
+ */
53
+ private cleanupWorkers;
54
+ }
55
+ /**
56
+ * Create a scheduler
57
+ */
58
+ export declare function createScheduler(options: SchedulerOptions): Scheduler;
59
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/runner/scheduler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,SAAS,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;CACxC;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,aAAa,CAAmB;IACxC,OAAO,CAAC,YAAY,CAAK;gBAEb,OAAO,EAAE,gBAAgB;IAIrC;;OAEG;IACG,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA4BpD;;OAEG;YACW,WAAW;IA6BzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;OAEG;YACW,gBAAgB;IAgB9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;IACH,OAAO,CAAC,cAAc;CAMvB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAEpE"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Scheduler + aggregation for parallel test execution
3
+ * Distributes tests across workers and aggregates results
4
+ */
5
+ import { createWorker } from './worker.js';
6
+ /**
7
+ * Parallel test scheduler
8
+ */
9
+ export class Scheduler {
10
+ options;
11
+ workers = [];
12
+ results = [];
13
+ pendingSuites = [];
14
+ activeSuites = 0;
15
+ constructor(options) {
16
+ this.options = options;
17
+ }
18
+ /**
19
+ * Run test suites in parallel across workers
20
+ */
21
+ async run(suites) {
22
+ const workerCount = this.options.config.parallel.workers;
23
+ if (workerCount === 1) {
24
+ // Single worker mode - run sequentially (already handled by caller)
25
+ throw new Error('Scheduler should not be used for single worker');
26
+ }
27
+ // Initialize workers
28
+ await this.initWorkers(workerCount);
29
+ // Queue all suites
30
+ this.pendingSuites = [...suites];
31
+ this.results = [];
32
+ this.activeSuites = 0;
33
+ // Start distributing work
34
+ await this.distributeSuites();
35
+ // Wait for all work to complete
36
+ await this.waitForCompletion();
37
+ // Cleanup workers
38
+ this.cleanupWorkers();
39
+ return this.results;
40
+ }
41
+ /**
42
+ * Initialize worker pool
43
+ */
44
+ async initWorkers(count) {
45
+ for (let i = 0; i < count; i++) {
46
+ const worker = createWorker({
47
+ workerId: i,
48
+ config: this.options.config,
49
+ artifactBaseDir: this.options.artifactBaseDir,
50
+ });
51
+ // Set up event handlers
52
+ worker.on('done', (results) => {
53
+ this.handleWorkerDone(worker, results);
54
+ });
55
+ worker.on('result', (result) => {
56
+ this.options.onResult?.(result);
57
+ });
58
+ worker.on('error', (error) => {
59
+ this.handleWorkerError(worker, error);
60
+ });
61
+ this.workers.push(worker);
62
+ worker.start();
63
+ }
64
+ // Wait for all workers to be ready
65
+ await this.waitForWorkers();
66
+ }
67
+ /**
68
+ * Wait for all workers to signal ready
69
+ */
70
+ waitForWorkers() {
71
+ return new Promise((resolve) => {
72
+ let readyCount = 0;
73
+ const targetCount = this.workers.length;
74
+ for (const worker of this.workers) {
75
+ worker.once('ready', () => {
76
+ readyCount++;
77
+ if (readyCount === targetCount) {
78
+ resolve();
79
+ }
80
+ });
81
+ }
82
+ });
83
+ }
84
+ /**
85
+ * Distribute suites to available workers
86
+ */
87
+ async distributeSuites() {
88
+ for (const worker of this.workers) {
89
+ if (this.pendingSuites.length === 0) {
90
+ break;
91
+ }
92
+ if (!worker.isBusy()) {
93
+ const suite = this.pendingSuites.shift();
94
+ if (suite) {
95
+ this.activeSuites++;
96
+ worker.runSuite(suite);
97
+ }
98
+ }
99
+ }
100
+ }
101
+ /**
102
+ * Handle worker completion
103
+ */
104
+ handleWorkerDone(worker, results) {
105
+ this.results.push(...results);
106
+ this.activeSuites--;
107
+ // Assign next suite if available
108
+ if (this.pendingSuites.length > 0) {
109
+ const suite = this.pendingSuites.shift();
110
+ if (suite) {
111
+ this.activeSuites++;
112
+ worker.runSuite(suite);
113
+ }
114
+ }
115
+ }
116
+ /**
117
+ * Handle worker error
118
+ */
119
+ handleWorkerError(worker, error) {
120
+ console.error(`Worker ${worker.getWorkerId()} error:`, error);
121
+ this.activeSuites--;
122
+ // Try to assign next suite to another worker
123
+ this.distributeSuites();
124
+ }
125
+ /**
126
+ * Wait for all work to complete
127
+ */
128
+ waitForCompletion() {
129
+ return new Promise((resolve) => {
130
+ const checkComplete = () => {
131
+ if (this.activeSuites === 0 && this.pendingSuites.length === 0) {
132
+ resolve();
133
+ }
134
+ else {
135
+ setTimeout(checkComplete, 100);
136
+ }
137
+ };
138
+ checkComplete();
139
+ });
140
+ }
141
+ /**
142
+ * Cleanup worker pool
143
+ */
144
+ cleanupWorkers() {
145
+ for (const worker of this.workers) {
146
+ worker.stop();
147
+ }
148
+ this.workers = [];
149
+ }
150
+ }
151
+ /**
152
+ * Create a scheduler
153
+ */
154
+ export function createScheduler(options) {
155
+ return new Scheduler(options);
156
+ }
157
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/runner/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Worker runner script
3
+ * Executed in worker process to run tests
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=worker-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-runner.d.ts","sourceRoot":"","sources":["../../src/runner/worker-runner.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Worker runner script
3
+ * Executed in worker process to run tests
4
+ */
5
+ import { runSuite } from './runner.js';
6
+ import { ArtifactManager } from './artifacts.js';
7
+ /**
8
+ * Handle messages from parent process
9
+ */
10
+ process.on('message', async (message) => {
11
+ if (message.type === 'run' && message.data) {
12
+ try {
13
+ const { suite, config, artifactBaseDir } = message.data;
14
+ // Create artifact manager for this worker
15
+ const artifactManager = new ArtifactManager({
16
+ baseDir: artifactBaseDir,
17
+ runId: `worker-${process.pid}-${Date.now()}`,
18
+ });
19
+ artifactManager.init();
20
+ // Run the suite
21
+ const results = await runSuite(suite, {
22
+ config,
23
+ artifactManager,
24
+ onResult: (result) => {
25
+ process.send?.({
26
+ type: 'result',
27
+ data: result,
28
+ });
29
+ },
30
+ });
31
+ // Send results back to parent
32
+ process.send?.({
33
+ type: 'done',
34
+ data: results,
35
+ });
36
+ }
37
+ catch (error) {
38
+ // Send error back to parent
39
+ process.send?.({
40
+ type: 'error',
41
+ data: {
42
+ message: error.message,
43
+ stack: error.stack,
44
+ },
45
+ });
46
+ }
47
+ }
48
+ });
49
+ // Signal ready
50
+ process.send?.({ type: 'ready' });
51
+ //# sourceMappingURL=worker-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-runner.js","sourceRoot":"","sources":["../../src/runner/worker-runner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWjD;;GAEG;AACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,OAAsB,EAAE,EAAE;IACrD,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAExD,0CAA0C;YAC1C,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC;gBAC1C,OAAO,EAAE,eAAe;gBACxB,KAAK,EAAE,UAAU,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;aAC7C,CAAC,CAAC;YACH,eAAe,CAAC,IAAI,EAAE,CAAC;YAEvB,gBAAgB;YAChB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE;gBACpC,MAAM;gBACN,eAAe;gBACf,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;oBACnB,OAAO,CAAC,IAAI,EAAE,CAAC;wBACb,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,MAAM;qBACb,CAAC,CAAC;gBACL,CAAC;aACF,CAAC,CAAC;YAEH,8BAA8B;YAC9B,OAAO,CAAC,IAAI,EAAE,CAAC;gBACb,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,OAAO;aACd,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,4BAA4B;YAC5B,OAAO,CAAC,IAAI,EAAE,CAAC;gBACb,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE;oBACJ,OAAO,EAAG,KAAe,CAAC,OAAO;oBACjC,KAAK,EAAG,KAAe,CAAC,KAAK;iBAC9B;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,eAAe;AACf,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Worker process runner for parallel test execution
3
+ * Runs tests in isolated worker processes
4
+ */
5
+ import type { TestSuite } from './models.js';
6
+ import type { RunConfig } from './config.js';
7
+ import { EventEmitter } from 'events';
8
+ export interface WorkerConfig {
9
+ workerId: number;
10
+ config: RunConfig;
11
+ artifactBaseDir: string;
12
+ }
13
+ export interface WorkerMessage {
14
+ type: 'ready' | 'result' | 'error' | 'done';
15
+ data?: unknown;
16
+ }
17
+ /**
18
+ * Worker process manager
19
+ */
20
+ export declare class Worker extends EventEmitter {
21
+ private process;
22
+ private config;
23
+ private busy;
24
+ constructor(config: WorkerConfig);
25
+ /**
26
+ * Start the worker process
27
+ */
28
+ start(): void;
29
+ /**
30
+ * Run a test suite in the worker
31
+ */
32
+ runSuite(suite: TestSuite): void;
33
+ /**
34
+ * Stop the worker
35
+ */
36
+ stop(): void;
37
+ /**
38
+ * Check if worker is busy
39
+ */
40
+ isBusy(): boolean;
41
+ /**
42
+ * Get worker ID
43
+ */
44
+ getWorkerId(): number;
45
+ /**
46
+ * Handle message from worker
47
+ */
48
+ private handleMessage;
49
+ }
50
+ /**
51
+ * Create a worker
52
+ */
53
+ export declare function createWorker(config: WorkerConfig): Worker;
54
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/runner/worker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5C,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,MAAO,SAAQ,YAAY;IACtC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,IAAI,CAAS;gBAET,MAAM,EAAE,YAAY;IAKhC;;OAEG;IACH,KAAK,IAAI,IAAI;IA0Bb;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAsBhC;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,OAAO,CAAC,aAAa;CAqBtB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAEzD"}