@browserflow-ai/cli 0.0.6

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 (90) hide show
  1. package/bin/bf.js +3 -0
  2. package/dist/commands/baseline.d.ts +77 -0
  3. package/dist/commands/baseline.d.ts.map +1 -0
  4. package/dist/commands/baseline.js +429 -0
  5. package/dist/commands/baseline.js.map +1 -0
  6. package/dist/commands/doctor.d.ts +39 -0
  7. package/dist/commands/doctor.d.ts.map +1 -0
  8. package/dist/commands/doctor.js +230 -0
  9. package/dist/commands/doctor.js.map +1 -0
  10. package/dist/commands/explore.d.ts +12 -0
  11. package/dist/commands/explore.d.ts.map +1 -0
  12. package/dist/commands/explore.js +114 -0
  13. package/dist/commands/explore.js.map +1 -0
  14. package/dist/commands/init.d.ts +15 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +160 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/lint.d.ts +37 -0
  19. package/dist/commands/lint.d.ts.map +1 -0
  20. package/dist/commands/lint.js +248 -0
  21. package/dist/commands/lint.js.map +1 -0
  22. package/dist/commands/repair.d.ts +72 -0
  23. package/dist/commands/repair.d.ts.map +1 -0
  24. package/dist/commands/repair.js +271 -0
  25. package/dist/commands/repair.js.map +1 -0
  26. package/dist/commands/review.d.ts +26 -0
  27. package/dist/commands/review.d.ts.map +1 -0
  28. package/dist/commands/review.js +371 -0
  29. package/dist/commands/review.js.map +1 -0
  30. package/dist/commands/run.d.ts +5 -0
  31. package/dist/commands/run.d.ts.map +1 -0
  32. package/dist/commands/run.js +66 -0
  33. package/dist/commands/run.js.map +1 -0
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +35 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/run/executor.d.ts +10 -0
  39. package/dist/run/executor.d.ts.map +1 -0
  40. package/dist/run/executor.js +95 -0
  41. package/dist/run/executor.js.map +1 -0
  42. package/dist/run/failure-bundle.d.ts +65 -0
  43. package/dist/run/failure-bundle.d.ts.map +1 -0
  44. package/dist/run/failure-bundle.js +253 -0
  45. package/dist/run/failure-bundle.js.map +1 -0
  46. package/dist/run/index.d.ts +6 -0
  47. package/dist/run/index.d.ts.map +1 -0
  48. package/dist/run/index.js +6 -0
  49. package/dist/run/index.js.map +1 -0
  50. package/dist/run/output.d.ts +5 -0
  51. package/dist/run/output.d.ts.map +1 -0
  52. package/dist/run/output.js +62 -0
  53. package/dist/run/output.js.map +1 -0
  54. package/dist/run/results.d.ts +5 -0
  55. package/dist/run/results.d.ts.map +1 -0
  56. package/dist/run/results.js +124 -0
  57. package/dist/run/results.js.map +1 -0
  58. package/dist/run/types.d.ts +44 -0
  59. package/dist/run/types.d.ts.map +1 -0
  60. package/dist/run/types.js +2 -0
  61. package/dist/run/types.js.map +1 -0
  62. package/dist/ui/box.d.ts +13 -0
  63. package/dist/ui/box.d.ts.map +1 -0
  64. package/dist/ui/box.js +32 -0
  65. package/dist/ui/box.js.map +1 -0
  66. package/dist/ui/colors.d.ts +28 -0
  67. package/dist/ui/colors.d.ts.map +1 -0
  68. package/dist/ui/colors.js +34 -0
  69. package/dist/ui/colors.js.map +1 -0
  70. package/dist/ui/env.d.ts +31 -0
  71. package/dist/ui/env.d.ts.map +1 -0
  72. package/dist/ui/env.js +77 -0
  73. package/dist/ui/env.js.map +1 -0
  74. package/dist/ui/index.d.ts +7 -0
  75. package/dist/ui/index.d.ts.map +1 -0
  76. package/dist/ui/index.js +7 -0
  77. package/dist/ui/index.js.map +1 -0
  78. package/dist/ui/output.d.ts +18 -0
  79. package/dist/ui/output.d.ts.map +1 -0
  80. package/dist/ui/output.js +33 -0
  81. package/dist/ui/output.js.map +1 -0
  82. package/dist/ui/prompts.d.ts +12 -0
  83. package/dist/ui/prompts.d.ts.map +1 -0
  84. package/dist/ui/prompts.js +37 -0
  85. package/dist/ui/prompts.js.map +1 -0
  86. package/dist/ui/spinner.d.ts +9 -0
  87. package/dist/ui/spinner.d.ts.map +1 -0
  88. package/dist/ui/spinner.js +27 -0
  89. package/dist/ui/spinner.js.map +1 -0
  90. package/package.json +78 -0
@@ -0,0 +1,65 @@
1
+ export type ErrorType = 'locator_not_found' | 'timeout' | 'assertion_failed' | 'screenshot_diff' | 'unknown';
2
+ export interface RepairSuggestion {
3
+ type: 'update_locator' | 'increase_timeout' | 'update_baseline' | 'fix_assertion' | 'investigate';
4
+ description: string;
5
+ confidence: 'high' | 'medium' | 'low';
6
+ }
7
+ export interface TestFailure {
8
+ specName: string;
9
+ stepId: string;
10
+ action: string;
11
+ message: string;
12
+ context: {
13
+ url: string;
14
+ viewport: {
15
+ width: number;
16
+ height: number;
17
+ };
18
+ browser: string;
19
+ };
20
+ }
21
+ export interface FailureBundle {
22
+ run_id: string;
23
+ spec_name: string;
24
+ failed_at: string;
25
+ failure: {
26
+ step_id: string;
27
+ action: string;
28
+ error_message: string;
29
+ error_type: ErrorType;
30
+ };
31
+ context: {
32
+ url: string;
33
+ viewport: {
34
+ width: number;
35
+ height: number;
36
+ };
37
+ browser: string;
38
+ };
39
+ artifacts: {
40
+ trace?: string;
41
+ video?: string;
42
+ screenshot?: string;
43
+ diff?: {
44
+ baseline: string;
45
+ actual: string;
46
+ diff: string;
47
+ };
48
+ console_log?: string;
49
+ network_log?: string;
50
+ };
51
+ suggestions?: RepairSuggestion[];
52
+ }
53
+ /**
54
+ * Classify an error message into a specific error type.
55
+ */
56
+ export declare function classifyError(errorMessage: string): ErrorType;
57
+ /**
58
+ * Generate repair suggestions based on the failure type.
59
+ */
60
+ export declare function generateRepairSuggestions(failure: TestFailure): RepairSuggestion[];
61
+ /**
62
+ * Generate a failure bundle with all artifacts and metadata.
63
+ */
64
+ export declare function generateFailureBundle(runDir: string, failure: TestFailure, playwrightArtifacts: string): Promise<string>;
65
+ //# sourceMappingURL=failure-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure-bundle.d.ts","sourceRoot":"","sources":["../../src/run/failure-bundle.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,mBAAmB,GAAG,SAAS,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAE7G,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,eAAe,GAAG,aAAa,CAAC;IAClG,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAElB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,SAAS,CAAC;KACvB,CAAC;IAEF,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF,SAAS,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE;YACL,QAAQ,EAAE,MAAM,CAAC;YACjB,MAAM,EAAE,MAAM,CAAC;YACf,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;QACF,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IAEF,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAiC7D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,gBAAgB,EAAE,CA6DlF;AA6GD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,EACpB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,MAAM,CAAC,CAuEjB"}
@@ -0,0 +1,253 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ /**
4
+ * Classify an error message into a specific error type.
5
+ */
6
+ export function classifyError(errorMessage) {
7
+ const msg = errorMessage.toLowerCase();
8
+ // Locator not found
9
+ if (/locator resolved to (\d+|N) elements/i.test(errorMessage)) {
10
+ return 'locator_not_found';
11
+ }
12
+ // Timeout errors
13
+ if (msg.includes('timeout') || msg.includes('timeouterror')) {
14
+ return 'timeout';
15
+ }
16
+ // Assertion failures
17
+ if (msg.includes('expect') ||
18
+ msg.includes('expected:') ||
19
+ msg.includes('received:') ||
20
+ msg.includes('assertionerror')) {
21
+ return 'assertion_failed';
22
+ }
23
+ // Screenshot/visual diff
24
+ if (msg.includes('screenshot comparison') ||
25
+ msg.includes('visual comparison') ||
26
+ msg.includes('tomatchsnapshot')) {
27
+ return 'screenshot_diff';
28
+ }
29
+ return 'unknown';
30
+ }
31
+ /**
32
+ * Generate repair suggestions based on the failure type.
33
+ */
34
+ export function generateRepairSuggestions(failure) {
35
+ const errorType = classifyError(failure.message);
36
+ const suggestions = [];
37
+ switch (errorType) {
38
+ case 'locator_not_found':
39
+ suggestions.push({
40
+ type: 'update_locator',
41
+ description: `The locator for "${failure.action}" action could not find the element. Consider updating the locator with a more specific selector or waiting for the element to appear.`,
42
+ confidence: 'high',
43
+ });
44
+ suggestions.push({
45
+ type: 'investigate',
46
+ description: 'Check if the page structure has changed or if the element loads dynamically.',
47
+ confidence: 'medium',
48
+ });
49
+ break;
50
+ case 'timeout':
51
+ suggestions.push({
52
+ type: 'increase_timeout',
53
+ description: 'The operation timed out. Consider increasing the timeout or checking if the element/action is slow to respond.',
54
+ confidence: 'high',
55
+ });
56
+ suggestions.push({
57
+ type: 'investigate',
58
+ description: 'Check for network issues or slow page loads that might be causing the timeout.',
59
+ confidence: 'medium',
60
+ });
61
+ break;
62
+ case 'assertion_failed':
63
+ suggestions.push({
64
+ type: 'fix_assertion',
65
+ description: 'The assertion failed. Review the expected vs actual values and update the test or fix the application behavior.',
66
+ confidence: 'medium',
67
+ });
68
+ break;
69
+ case 'screenshot_diff':
70
+ suggestions.push({
71
+ type: 'update_baseline',
72
+ description: 'Visual differences detected. Review the diff images and update the baseline if the changes are intentional.',
73
+ confidence: 'high',
74
+ });
75
+ suggestions.push({
76
+ type: 'investigate',
77
+ description: 'Check if the visual differences indicate a regression or an expected UI change.',
78
+ confidence: 'medium',
79
+ });
80
+ break;
81
+ default:
82
+ suggestions.push({
83
+ type: 'investigate',
84
+ description: 'Unknown error type. Review the error message and stack trace for more details.',
85
+ confidence: 'low',
86
+ });
87
+ }
88
+ return suggestions;
89
+ }
90
+ /**
91
+ * Find trace file in the artifacts directory.
92
+ */
93
+ async function findTrace(artifactsDir) {
94
+ try {
95
+ const testResultsDir = path.join(artifactsDir, 'test-results');
96
+ const entries = await fs.readdir(testResultsDir, { withFileTypes: true, recursive: true });
97
+ for (const entry of entries) {
98
+ if (entry.isFile() && entry.name === 'trace.zip') {
99
+ return path.join(entry.parentPath || testResultsDir, entry.name);
100
+ }
101
+ }
102
+ }
103
+ catch {
104
+ // Directory doesn't exist or other error
105
+ }
106
+ return null;
107
+ }
108
+ /**
109
+ * Find failure screenshot in the artifacts directory.
110
+ */
111
+ async function findFailureScreenshot(artifactsDir) {
112
+ try {
113
+ const testResultsDir = path.join(artifactsDir, 'test-results');
114
+ const entries = await fs.readdir(testResultsDir, { withFileTypes: true, recursive: true });
115
+ for (const entry of entries) {
116
+ if (entry.isFile() && entry.name.match(/test-failed.*\.png$/)) {
117
+ return path.join(entry.parentPath || testResultsDir, entry.name);
118
+ }
119
+ }
120
+ }
121
+ catch {
122
+ // Directory doesn't exist or other error
123
+ }
124
+ return null;
125
+ }
126
+ /**
127
+ * Find and copy diff images for screenshot failures.
128
+ */
129
+ async function copyDiffImages(artifactsDir, bundleDir) {
130
+ try {
131
+ const testResultsDir = path.join(artifactsDir, 'test-results');
132
+ const entries = await fs.readdir(testResultsDir, { withFileTypes: true, recursive: true });
133
+ const diffDir = path.join(bundleDir, 'diff');
134
+ await fs.mkdir(diffDir, { recursive: true });
135
+ const result = {};
136
+ for (const entry of entries) {
137
+ if (!entry.isFile())
138
+ continue;
139
+ const fullPath = path.join(entry.parentPath || testResultsDir, entry.name);
140
+ if (entry.name.includes('-expected.png') || entry.name.includes('-baseline.png')) {
141
+ const destPath = path.join(diffDir, 'baseline.png');
142
+ await fs.copyFile(fullPath, destPath);
143
+ result.baseline = destPath;
144
+ }
145
+ else if (entry.name.includes('-actual.png')) {
146
+ const destPath = path.join(diffDir, 'actual.png');
147
+ await fs.copyFile(fullPath, destPath);
148
+ result.actual = destPath;
149
+ }
150
+ else if (entry.name.includes('-diff.png')) {
151
+ const destPath = path.join(diffDir, 'diff.png');
152
+ await fs.copyFile(fullPath, destPath);
153
+ result.diff = destPath;
154
+ }
155
+ }
156
+ if (result.baseline || result.actual || result.diff) {
157
+ return result;
158
+ }
159
+ }
160
+ catch {
161
+ // Error reading or copying files
162
+ }
163
+ return null;
164
+ }
165
+ /**
166
+ * Extract console and network logs from trace.
167
+ * Note: This is a placeholder - actual trace extraction would require parsing the trace.zip file.
168
+ */
169
+ async function extractLogsFromTrace(_tracePath) {
170
+ // Placeholder implementation - in a real implementation, we would:
171
+ // 1. Unzip the trace file
172
+ // 2. Parse the trace JSON
173
+ // 3. Extract console and network events
174
+ return {
175
+ console: [],
176
+ network: [],
177
+ };
178
+ }
179
+ /**
180
+ * Write JSON to a file, ensuring the directory exists.
181
+ */
182
+ async function writeJson(filePath, data) {
183
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
184
+ await fs.writeFile(filePath, JSON.stringify(data, null, 2));
185
+ }
186
+ /**
187
+ * Generate a failure bundle with all artifacts and metadata.
188
+ */
189
+ export async function generateFailureBundle(runDir, failure, playwrightArtifacts) {
190
+ const bundleDir = path.join(runDir, 'artifacts');
191
+ await fs.mkdir(bundleDir, { recursive: true });
192
+ const artifacts = {};
193
+ // 1. Copy trace file
194
+ const tracePath = await findTrace(playwrightArtifacts);
195
+ if (tracePath) {
196
+ const destPath = path.join(bundleDir, 'trace.zip');
197
+ await fs.copyFile(tracePath, destPath);
198
+ artifacts.trace = destPath;
199
+ // 4. Extract console/network logs from trace
200
+ const logs = await extractLogsFromTrace(destPath);
201
+ const logsDir = path.join(bundleDir, 'logs');
202
+ await writeJson(path.join(logsDir, 'console.json'), logs.console);
203
+ await writeJson(path.join(logsDir, 'network.json'), logs.network);
204
+ artifacts.console_log = path.join(logsDir, 'console.json');
205
+ artifacts.network_log = path.join(logsDir, 'network.json');
206
+ }
207
+ else {
208
+ // Still create empty log files even without trace
209
+ const logsDir = path.join(bundleDir, 'logs');
210
+ await writeJson(path.join(logsDir, 'console.json'), []);
211
+ await writeJson(path.join(logsDir, 'network.json'), []);
212
+ artifacts.console_log = path.join(logsDir, 'console.json');
213
+ artifacts.network_log = path.join(logsDir, 'network.json');
214
+ }
215
+ // 2. Copy failure screenshot
216
+ const screenshotPath = await findFailureScreenshot(playwrightArtifacts);
217
+ if (screenshotPath) {
218
+ const screenshotsDir = path.join(bundleDir, 'screenshots');
219
+ await fs.mkdir(screenshotsDir, { recursive: true });
220
+ const destPath = path.join(screenshotsDir, 'failure.png');
221
+ await fs.copyFile(screenshotPath, destPath);
222
+ artifacts.screenshot = destPath;
223
+ }
224
+ // 3. Copy diff images if screenshot failure
225
+ const errorType = classifyError(failure.message);
226
+ if (errorType === 'screenshot_diff') {
227
+ const diffImages = await copyDiffImages(playwrightArtifacts, bundleDir);
228
+ if (diffImages) {
229
+ artifacts.diff = diffImages;
230
+ }
231
+ }
232
+ // 5. Generate repair suggestions
233
+ const suggestions = generateRepairSuggestions(failure);
234
+ // 6. Write failure.json
235
+ const bundle = {
236
+ run_id: path.basename(runDir),
237
+ spec_name: failure.specName,
238
+ failed_at: new Date().toISOString(),
239
+ failure: {
240
+ step_id: failure.stepId,
241
+ action: failure.action,
242
+ error_message: failure.message,
243
+ error_type: errorType,
244
+ },
245
+ context: failure.context,
246
+ artifacts,
247
+ suggestions,
248
+ };
249
+ const bundlePath = path.join(runDir, 'failure.json');
250
+ await writeJson(bundlePath, bundle);
251
+ return bundlePath;
252
+ }
253
+ //# sourceMappingURL=failure-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure-bundle.js","sourceRoot":"","sources":["../../src/run/failure-bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from './types.js';
2
+ export * from './executor.js';
3
+ export * from './results.js';
4
+ export * from './output.js';
5
+ export * from './failure-bundle.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/run/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './types.js';
2
+ export * from './executor.js';
3
+ export * from './results.js';
4
+ export * from './output.js';
5
+ export * from './failure-bundle.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/run/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { RunResult } from './types.js';
2
+ export declare function printRunHeader(specs: string[]): void;
3
+ export declare function printRunSummary(result: RunResult): void;
4
+ export declare function printError(message: string): void;
5
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/run/output.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAA0B,MAAM,YAAY,CAAC;AAEpE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAQpD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4BvD;AA8BD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGhD"}
@@ -0,0 +1,62 @@
1
+ import { colors } from '../ui/colors.js';
2
+ export function printRunHeader(specs) {
3
+ console.log();
4
+ if (specs.length > 0) {
5
+ console.log(colors.bold(`Running: ${specs.join(', ')}`));
6
+ }
7
+ else {
8
+ console.log(colors.bold('Running: all specs'));
9
+ }
10
+ console.log();
11
+ }
12
+ export function printRunSummary(result) {
13
+ console.log();
14
+ // Print spec-by-spec results
15
+ for (const spec of result.specs) {
16
+ printSpecResult(spec);
17
+ }
18
+ // Print summary line
19
+ console.log();
20
+ const parts = [];
21
+ if (result.passed > 0) {
22
+ parts.push(colors.pass(`${result.passed} passed`));
23
+ }
24
+ if (result.failed > 0) {
25
+ parts.push(colors.fail(`${result.failed} failed`));
26
+ }
27
+ if (result.skipped > 0) {
28
+ parts.push(colors.skip(`${result.skipped} skipped`));
29
+ }
30
+ const duration = formatDuration(result.duration);
31
+ console.log(` ${parts.join(', ')} (${duration})`);
32
+ // Print run location
33
+ console.log();
34
+ console.log(`Run complete. Results at: ${colors.path(result.runDir)}`);
35
+ }
36
+ function printSpecResult(spec) {
37
+ console.log(` ${colors.bold(spec.name)}`);
38
+ for (const step of spec.steps) {
39
+ printStepResult(step);
40
+ }
41
+ console.log();
42
+ }
43
+ function printStepResult(step) {
44
+ const duration = formatDuration(step.duration);
45
+ const icon = step.status === 'passed'
46
+ ? colors.pass('✓')
47
+ : step.status === 'failed'
48
+ ? colors.fail('✗')
49
+ : colors.skip('○');
50
+ console.log(` ${icon} ${step.name} ${colors.dim(`(${duration})`)}`);
51
+ }
52
+ function formatDuration(ms) {
53
+ if (ms < 1000) {
54
+ return `${Math.round(ms)}ms`;
55
+ }
56
+ return `${(ms / 1000).toFixed(1)}s`;
57
+ }
58
+ export function printError(message) {
59
+ console.error();
60
+ console.error(colors.error(`Error: ${message}`));
61
+ }
62
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/run/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { RunResult, FailureInfo } from './types.js';
2
+ import type { ExecutorResult } from './executor.js';
3
+ export declare function collectResults(runDir: string, executorResult: ExecutorResult): Promise<RunResult>;
4
+ export declare function generateFailureBundles(runDir: string, failures: FailureInfo[]): Promise<string[]>;
5
+ //# sourceMappingURL=results.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../../src/run/results.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAA0B,WAAW,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,SAAS,CAAC,CAkGpB;AAgDD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,EAAE,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,CA+BnB"}
@@ -0,0 +1,124 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { generateFailureBundle } from './failure-bundle.js';
4
+ export async function collectResults(runDir, executorResult) {
5
+ const specs = [];
6
+ const failures = [];
7
+ // Parse results from JSON output
8
+ if (!executorResult.jsonOutput) {
9
+ // Fallback if no JSON output available
10
+ return {
11
+ runDir,
12
+ specs: [],
13
+ passed: 0,
14
+ failed: 0,
15
+ skipped: 0,
16
+ duration: 0,
17
+ failures: [],
18
+ };
19
+ }
20
+ const json = executorResult.jsonOutput;
21
+ // Process each suite (file)
22
+ for (const suite of json.suites ?? []) {
23
+ // Extract spec name from file path
24
+ // e.g., 'e2e/tests/login.spec.ts' -> 'login'
25
+ // e.g., 'e2e/tests/nested/deep/test.spec.ts' -> 'nested/deep/test'
26
+ const specName = extractSpecName(suite.file);
27
+ const steps = [];
28
+ let suiteDuration = 0;
29
+ let suiteStatus = 'passed';
30
+ // Process each spec (test) within the suite as a step
31
+ for (const spec of suite.specs ?? []) {
32
+ const test = spec.tests?.[0];
33
+ const result = test?.results?.[0];
34
+ const status = result?.status === 'skipped'
35
+ ? 'skipped'
36
+ : spec.ok
37
+ ? 'passed'
38
+ : 'failed';
39
+ const duration = result?.duration ?? 0;
40
+ const errorMessage = result?.error?.message;
41
+ steps.push({
42
+ name: spec.title,
43
+ duration,
44
+ status,
45
+ error: errorMessage,
46
+ });
47
+ suiteDuration += duration;
48
+ // Suite fails if any test fails
49
+ if (status === 'failed') {
50
+ suiteStatus = 'failed';
51
+ }
52
+ else if (status === 'skipped' && suiteStatus === 'passed') {
53
+ suiteStatus = 'skipped';
54
+ }
55
+ // Track failures
56
+ if (status === 'failed' && errorMessage) {
57
+ failures.push({
58
+ spec: specName,
59
+ step: spec.title,
60
+ error: errorMessage,
61
+ });
62
+ }
63
+ }
64
+ // Create one SpecResult per suite (file) with all tests as steps
65
+ if (steps.length > 0) {
66
+ specs.push({
67
+ name: specName,
68
+ steps,
69
+ duration: suiteDuration,
70
+ status: suiteStatus,
71
+ });
72
+ }
73
+ }
74
+ // Use stats from JSON report
75
+ const stats = json.stats;
76
+ const passed = stats?.expected ?? 0;
77
+ const failed = stats?.unexpected ?? 0;
78
+ const skipped = stats?.skipped ?? 0;
79
+ const duration = stats?.duration ?? 0;
80
+ return {
81
+ runDir,
82
+ specs,
83
+ passed,
84
+ failed,
85
+ skipped,
86
+ duration,
87
+ failures,
88
+ };
89
+ }
90
+ function extractSpecName(filePath) {
91
+ // Extract spec name from file path
92
+ // e.g., 'e2e/tests/login.spec.ts' -> 'login'
93
+ // e.g., 'e2e/tests/nested/deep/test.spec.ts' -> 'nested/deep/test'
94
+ const match = filePath.match(/tests\/(.+?)\.spec\.ts/);
95
+ return match ? match[1] : 'unknown';
96
+ }
97
+ export async function generateFailureBundles(runDir, failures) {
98
+ const bundlesDir = path.join(runDir, 'failure-bundles');
99
+ await fs.mkdir(bundlesDir, { recursive: true });
100
+ const bundlePaths = [];
101
+ const artifactsDir = path.join(runDir, 'artifacts');
102
+ for (const failure of failures) {
103
+ const bundleName = `${failure.spec}-${failure.step}`.replace(/[^a-zA-Z0-9-_]/g, '-');
104
+ const bundleDir = path.join(bundlesDir, bundleName);
105
+ await fs.mkdir(bundleDir, { recursive: true });
106
+ // Convert FailureInfo to TestFailure
107
+ const testFailure = {
108
+ specName: failure.spec,
109
+ stepId: failure.step,
110
+ action: failure.step, // Use step name as action if not available
111
+ message: failure.error,
112
+ context: failure.context ?? {
113
+ url: 'unknown',
114
+ viewport: { width: 1280, height: 720 },
115
+ browser: 'chromium',
116
+ },
117
+ };
118
+ // Generate comprehensive failure bundle
119
+ const bundlePath = await generateFailureBundle(bundleDir, testFailure, artifactsDir);
120
+ bundlePaths.push(bundlePath);
121
+ }
122
+ return bundlePaths;
123
+ }
124
+ //# sourceMappingURL=results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"results.js","sourceRoot":"","sources":["../../src/run/results.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface RunOptions {
2
+ spec?: string;
3
+ tag?: string;
4
+ parallel?: number;
5
+ headed?: boolean;
6
+ trace?: 'on' | 'off' | 'on-first-retry';
7
+ }
8
+ export interface StepResult {
9
+ name: string;
10
+ duration: number;
11
+ status: 'passed' | 'failed' | 'skipped';
12
+ error?: string;
13
+ }
14
+ export interface SpecResult {
15
+ name: string;
16
+ steps: StepResult[];
17
+ duration: number;
18
+ status: 'passed' | 'failed' | 'skipped';
19
+ }
20
+ export interface RunResult {
21
+ runDir: string;
22
+ specs: SpecResult[];
23
+ passed: number;
24
+ failed: number;
25
+ skipped: number;
26
+ duration: number;
27
+ failures: FailureInfo[];
28
+ }
29
+ export interface FailureInfo {
30
+ spec: string;
31
+ step: string;
32
+ error: string;
33
+ screenshot?: string;
34
+ trace?: string;
35
+ context?: {
36
+ url: string;
37
+ viewport: {
38
+ width: number;
39
+ height: number;
40
+ };
41
+ browser: string;
42
+ };
43
+ }
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/run/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,gBAAgB,CAAC;CACzC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/run/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ export interface BoxOptions {
2
+ /** Width of the box content area (default: 58) */
3
+ width?: number;
4
+ }
5
+ /**
6
+ * Format content into a box with title and return as string
7
+ */
8
+ export declare function formatBox(title: string, content: string[], options?: BoxOptions): string;
9
+ /**
10
+ * Print a formatted box to the console
11
+ */
12
+ export declare function printBox(title: string, content: string[], options?: BoxOptions): void;
13
+ //# sourceMappingURL=box.d.ts.map