@browserflow-ai/cli 0.0.8 → 0.0.9

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.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * bf codify command - generate Playwright tests from explorations
3
+ * @see bf-0lr
4
+ */
5
+ import { Command } from 'commander';
6
+ export declare function codifyCommand(): Command;
7
+ //# sourceMappingURL=codify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codify.d.ts","sourceRoot":"","sources":["../../src/commands/codify.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4NpC,wBAAgB,aAAa,IAAI,OAAO,CAwGvC"}
@@ -0,0 +1,294 @@
1
+ /**
2
+ * bf codify command - generate Playwright tests from explorations
3
+ * @see bf-0lr
4
+ */
5
+ import { Command } from 'commander';
6
+ import { readFile, writeFile, mkdir, access } from 'node:fs/promises';
7
+ import { join, dirname } from 'node:path';
8
+ import { generateTest } from '@browserflow-ai/generator';
9
+ import { colors } from '../ui/colors.js';
10
+ import { loadExploration, listExplorations } from './review.js';
11
+ /**
12
+ * Resolve an element ref to a locator object using snapshot refs data.
13
+ * The exploration stores elementRef (e.g., "e17") and the actual locator data
14
+ * is in snapshotBefore.refs or snapshotAfter.refs.
15
+ *
16
+ * For testid-based targets, elementRef may contain the actual CSS selector
17
+ * (e.g., "[data-testid=\"todo-input\"]") which should be used directly.
18
+ */
19
+ function resolveElementRefToLocator(elementRef, snapshotBefore, snapshotAfter) {
20
+ if (!elementRef)
21
+ return undefined;
22
+ // Check if elementRef is already a CSS selector (starts with [ or contains data-testid)
23
+ if (elementRef.startsWith('[') || elementRef.includes('data-testid')) {
24
+ // Extract testid if present and use getByTestId
25
+ const testIdMatch = elementRef.match(/data-testid="([^"]+)"/);
26
+ if (testIdMatch) {
27
+ return {
28
+ method: 'getByTestId',
29
+ args: { testId: testIdMatch[1] },
30
+ };
31
+ }
32
+ // Otherwise use as CSS selector
33
+ return { selector: elementRef };
34
+ }
35
+ // Try to get refs from snapshot (prefer snapshotBefore as it's what was used for the action)
36
+ const refs = (snapshotBefore?.refs ?? snapshotAfter?.refs);
37
+ if (!refs)
38
+ return undefined;
39
+ const refData = refs[elementRef];
40
+ if (!refData)
41
+ return undefined;
42
+ // The refs contain a 'selector' field which is actually Playwright code like:
43
+ // "getByRole('button', { name: \"ComfyGit\", exact: true })"
44
+ // We need to parse this into a LocatorObject format
45
+ const selectorStr = refData.selector;
46
+ if (!selectorStr)
47
+ return undefined;
48
+ // Try to parse method-style selectors (getByRole, getByText, etc.)
49
+ const methodMatch = selectorStr.match(/^(getBy\w+)\((.+)\)$/);
50
+ if (methodMatch) {
51
+ const method = methodMatch[1];
52
+ const argsStr = methodMatch[2];
53
+ // For getByRole, parse: 'button', { name: "...", exact: true }
54
+ // For getByText/etc, parse: '...', { exact: true }
55
+ if (method === 'getByRole') {
56
+ const roleMatch = argsStr.match(/^'(\w+)'(?:,\s*\{(.+)\})?$/);
57
+ if (roleMatch) {
58
+ const role = roleMatch[1];
59
+ const args = { role };
60
+ // Parse options if present
61
+ if (roleMatch[2]) {
62
+ const nameMatch = roleMatch[2].match(/name:\s*"([^"]+)"/);
63
+ if (nameMatch)
64
+ args.name = nameMatch[1];
65
+ const exactMatch = roleMatch[2].match(/exact:\s*(true|false)/);
66
+ if (exactMatch)
67
+ args.exact = exactMatch[1] === 'true';
68
+ }
69
+ return { method, args };
70
+ }
71
+ }
72
+ else if (method === 'getByTestId') {
73
+ const testIdMatch = argsStr.match(/^'([^']+)'$/);
74
+ if (testIdMatch) {
75
+ return { method, args: { testId: testIdMatch[1] } };
76
+ }
77
+ }
78
+ else {
79
+ // getByText, getByLabel, etc.
80
+ const textMatch = argsStr.match(/^'([^']+)'(?:,\s*\{(.+)\})?$/);
81
+ if (textMatch) {
82
+ const args = { text: textMatch[1] };
83
+ if (textMatch[2]) {
84
+ const exactMatch = textMatch[2].match(/exact:\s*(true|false)/);
85
+ if (exactMatch)
86
+ args.exact = exactMatch[1] === 'true';
87
+ }
88
+ return { method, args };
89
+ }
90
+ }
91
+ }
92
+ // Fallback: treat as CSS selector
93
+ return { selector: selectorStr };
94
+ }
95
+ /**
96
+ * Transform camelCase exploration output to snake_case lockfile format.
97
+ * The exploration engine outputs camelCase, but the generator expects snake_case.
98
+ */
99
+ function transformToLockfile(exploration) {
100
+ // Transform step execution, resolving element refs to locators
101
+ const transformExecution = (exec, snapshotBefore, snapshotAfter) => {
102
+ const elementRef = exec.elementRef;
103
+ const resolvedLocator = resolveElementRefToLocator(elementRef, snapshotBefore, snapshotAfter);
104
+ return {
105
+ status: exec.status,
106
+ method: exec.method,
107
+ element_ref: elementRef,
108
+ selector_used: exec.selectorUsed,
109
+ locator: exec.locator ?? resolvedLocator,
110
+ duration_ms: exec.durationMs,
111
+ error: exec.error,
112
+ value_used: exec.valueUsed,
113
+ url_used: exec.urlUsed,
114
+ };
115
+ };
116
+ // Transform steps
117
+ const transformStep = (step) => {
118
+ const snapshotBefore = step.snapshotBefore;
119
+ const snapshotAfter = step.snapshotAfter;
120
+ return {
121
+ step_index: step.stepIndex,
122
+ spec_action: step.specAction,
123
+ execution: transformExecution(step.execution, snapshotBefore, snapshotAfter),
124
+ screenshots: step.screenshots,
125
+ snapshot_before: snapshotBefore,
126
+ snapshot_after: snapshotAfter,
127
+ };
128
+ };
129
+ // Transform outcome checks (already snake_case in the interface)
130
+ const transformOutcomeCheck = (check) => ({
131
+ check: check.check,
132
+ expected: check.expected,
133
+ actual: check.actual,
134
+ passed: check.passed,
135
+ });
136
+ // Transform errors
137
+ const transformErrors = (errors) => {
138
+ return errors.map((err) => {
139
+ if (typeof err === 'string') {
140
+ return { message: err };
141
+ }
142
+ const errObj = err;
143
+ return {
144
+ step_index: errObj.stepIndex,
145
+ message: errObj.message,
146
+ stack: errObj.stack,
147
+ };
148
+ });
149
+ };
150
+ return {
151
+ spec: exploration.spec,
152
+ spec_path: exploration.specPath,
153
+ spec_description: exploration.specDescription,
154
+ exploration_id: exploration.explorationId,
155
+ timestamp: exploration.timestamp,
156
+ duration_ms: exploration.durationMs,
157
+ browser: exploration.browser,
158
+ viewport: exploration.viewport,
159
+ base_url: exploration.baseUrl,
160
+ steps: exploration.steps.map((s) => transformStep(s)),
161
+ outcome_checks: exploration.outcomeChecks.map((c) => transformOutcomeCheck(c)),
162
+ overall_status: exploration.overallStatus,
163
+ errors: transformErrors(exploration.errors),
164
+ };
165
+ }
166
+ /**
167
+ * Load review data if it exists
168
+ */
169
+ async function loadReview(explorationId, cwd = process.cwd()) {
170
+ const reviewPath = join(cwd, '.browserflow', 'explorations', explorationId, 'review.json');
171
+ try {
172
+ const content = await readFile(reviewPath, 'utf-8');
173
+ return JSON.parse(content);
174
+ }
175
+ catch (error) {
176
+ const err = error;
177
+ if (err.code === 'ENOENT') {
178
+ return undefined; // No review exists
179
+ }
180
+ throw error;
181
+ }
182
+ }
183
+ /**
184
+ * Find the most recent exploration for a spec name
185
+ */
186
+ async function findExplorationForSpec(specName, cwd = process.cwd()) {
187
+ const explorations = await listExplorations(cwd);
188
+ // Sort by timestamp (newest first) - exp-{timestamp} format
189
+ const sorted = explorations.sort().reverse();
190
+ for (const id of sorted) {
191
+ try {
192
+ const exploration = await loadExploration(id, cwd);
193
+ if (exploration.spec === specName) {
194
+ return id;
195
+ }
196
+ }
197
+ catch {
198
+ // Skip invalid explorations
199
+ }
200
+ }
201
+ return null;
202
+ }
203
+ export function codifyCommand() {
204
+ return new Command('codify')
205
+ .description('Generate Playwright test from an exploration')
206
+ .option('--exploration <id>', 'Exploration ID to codify')
207
+ .option('--spec <name>', 'Find latest exploration for this spec')
208
+ .option('--output <path>', 'Output path for generated test')
209
+ .option('--no-visual', 'Skip visual assertions')
210
+ .option('--no-comments', 'Skip step comments')
211
+ .option('--require-review', 'Only codify if exploration has been reviewed')
212
+ .option('--dry-run', 'Print generated test without writing to disk')
213
+ .action(async (options) => {
214
+ const cwd = process.cwd();
215
+ try {
216
+ // 1. Determine exploration ID
217
+ let explorationId;
218
+ if (options.exploration) {
219
+ explorationId = options.exploration;
220
+ }
221
+ else if (options.spec) {
222
+ const found = await findExplorationForSpec(options.spec, cwd);
223
+ if (!found) {
224
+ throw new Error(`No exploration found for spec: ${options.spec}`);
225
+ }
226
+ explorationId = found;
227
+ console.log(colors.dim(`Found exploration: ${explorationId}`));
228
+ }
229
+ else {
230
+ // List available explorations
231
+ const explorations = await listExplorations(cwd);
232
+ if (explorations.length === 0) {
233
+ throw new Error('No explorations found. Run `bf explore` first.');
234
+ }
235
+ // Use the most recent one
236
+ explorationId = explorations.sort().reverse()[0];
237
+ console.log(colors.dim(`Using most recent exploration: ${explorationId}`));
238
+ }
239
+ // 2. Load exploration data
240
+ const rawExploration = await loadExploration(explorationId, cwd);
241
+ // 3. Check exploration status
242
+ if (rawExploration.overallStatus !== 'completed') {
243
+ console.warn(colors.warning(`Exploration status: ${rawExploration.overallStatus}`));
244
+ const errors = rawExploration.errors;
245
+ if (errors?.length > 0) {
246
+ console.warn(colors.warning(`Errors: ${errors.length}`));
247
+ }
248
+ }
249
+ // 4. Load review if exists
250
+ const review = await loadReview(explorationId, cwd);
251
+ if (options.requireReview && !review) {
252
+ throw new Error('Exploration has not been reviewed. Run `bf review` first or remove --require-review.');
253
+ }
254
+ if (options.requireReview && review?.verdict !== 'approved') {
255
+ throw new Error(`Exploration not approved. Current verdict: ${review?.verdict}`);
256
+ }
257
+ // 5. Transform to lockfile format
258
+ const lockfile = transformToLockfile(rawExploration);
259
+ // 6. Generate test
260
+ const generated = generateTest(lockfile, {
261
+ includeVisualChecks: options.visual !== false,
262
+ includeComments: options.comments !== false,
263
+ }, review);
264
+ // 7. Determine output path
265
+ const outputPath = options.output ?? generated.path;
266
+ // 8. Handle output
267
+ if (options.dryRun) {
268
+ console.log(colors.info(`Would write to: ${outputPath}`));
269
+ console.log('');
270
+ console.log(generated.content);
271
+ }
272
+ else {
273
+ // Ensure directory exists
274
+ const outputDir = dirname(outputPath);
275
+ await mkdir(outputDir, { recursive: true });
276
+ // Write test file
277
+ await writeFile(outputPath, generated.content, 'utf-8');
278
+ console.log(colors.success(`Generated: ${outputPath}`));
279
+ // Print summary
280
+ console.log(colors.dim(` Spec: ${generated.specName}`));
281
+ console.log(colors.dim(` Exploration: ${generated.explorationId}`));
282
+ if (review) {
283
+ console.log(colors.dim(` Reviewed: ${review.verdict} by ${review.reviewer ?? 'unknown'}`));
284
+ }
285
+ }
286
+ }
287
+ catch (error) {
288
+ const err = error;
289
+ console.error(colors.fail(err.message));
290
+ process.exitCode = 1;
291
+ }
292
+ });
293
+ }
294
+ //# sourceMappingURL=codify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codify.js","sourceRoot":"","sources":["../../src/commands/codify.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,wBAAgB,aAAa,IAAI,OAAO,CAkBvC;AAED,wBAAgB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAGzC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,wBAAgB,aAAa,IAAI,OAAO,CAmBvC;AAED,wBAAgB,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAGzC"}
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { baselineCommand } from './commands/baseline.js';
8
8
  import { repairCommand } from './commands/repair.js';
9
9
  import { exploreCommand } from './commands/explore.js';
10
10
  import { reviewCommand } from './commands/review.js';
11
+ import { codifyCommand } from './commands/codify.js';
11
12
  const require = createRequire(import.meta.url);
12
13
  const { version: VERSION } = require('../package.json');
13
14
  export function createProgram() {
@@ -24,6 +25,7 @@ export function createProgram() {
24
25
  program.addCommand(repairCommand());
25
26
  program.addCommand(exploreCommand());
26
27
  program.addCommand(reviewCommand());
28
+ program.addCommand(codifyCommand());
27
29
  return program;
28
30
  }
29
31
  export function run(argv) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAExD,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,IAAI,CAAC;SACV,WAAW,CAAC,qDAAqD,CAAC;SAClE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAEpC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAe;IACjC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,iCAAiC;AACjC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,GAAG,EAAE,CAAC;AACR,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAExD,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,IAAI,CAAC;SACV,WAAW,CAAC,qDAAqD,CAAC;SAClE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;IACjC,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC;IAEpC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAe;IACjC,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,iCAAiC;AACjC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrB,GAAG,EAAE,CAAC;AACR,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserflow-ai/cli",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "bf command-line tool for BrowserFlow - Human-in-the-Loop E2E Test Generation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,10 +58,10 @@
58
58
  "node": ">=18.0.0"
59
59
  },
60
60
  "dependencies": {
61
- "@browserflow-ai/core": "0.0.8",
62
- "@browserflow-ai/exploration": "0.0.8",
63
- "@browserflow-ai/generator": "0.0.8",
64
- "@browserflow-ai/review-ui": "0.0.8",
61
+ "@browserflow-ai/core": "0.0.9",
62
+ "@browserflow-ai/exploration": "0.0.9",
63
+ "@browserflow-ai/generator": "0.0.9",
64
+ "@browserflow-ai/review-ui": "0.0.9",
65
65
  "chalk": "^5.3.0",
66
66
  "commander": "^12.0.0",
67
67
  "ora": "^8.0.0",