@browserflow-ai/cli 0.0.7 → 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 @@
|
|
|
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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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { initCommand } from './commands/init.js';
|
|
3
4
|
import { doctorCommand } from './commands/doctor.js';
|
|
4
5
|
import { lintCommand } from './commands/lint.js';
|
|
@@ -7,7 +8,9 @@ import { baselineCommand } from './commands/baseline.js';
|
|
|
7
8
|
import { repairCommand } from './commands/repair.js';
|
|
8
9
|
import { exploreCommand } from './commands/explore.js';
|
|
9
10
|
import { reviewCommand } from './commands/review.js';
|
|
10
|
-
|
|
11
|
+
import { codifyCommand } from './commands/codify.js';
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const { version: VERSION } = require('../package.json');
|
|
11
14
|
export function createProgram() {
|
|
12
15
|
const program = new Command();
|
|
13
16
|
program
|
|
@@ -22,6 +25,7 @@ export function createProgram() {
|
|
|
22
25
|
program.addCommand(repairCommand());
|
|
23
26
|
program.addCommand(exploreCommand());
|
|
24
27
|
program.addCommand(reviewCommand());
|
|
28
|
+
program.addCommand(codifyCommand());
|
|
25
29
|
return program;
|
|
26
30
|
}
|
|
27
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,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,OAAO,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.
|
|
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.
|
|
62
|
-
"@browserflow-ai/exploration": "0.0.
|
|
63
|
-
"@browserflow-ai/generator": "0.0.
|
|
64
|
-
"@browserflow-ai/review-ui": "0.0.
|
|
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",
|