flowspec 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.
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/config.d.ts +54 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +102 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +181 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +41 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +173 -0
- package/dist/init.js.map +1 -0
- package/dist/parser.d.ts +16 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +56 -0
- package/dist/parser.js.map +1 -0
- package/dist/reporter.d.ts +22 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +80 -0
- package/dist/reporter.js.map +1 -0
- package/dist/runner.d.ts +24 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +418 -0
- package/dist/runner.js.map +1 -0
- package/dist/types.d.ts +512 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +78 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
package/dist/runner.js
ADDED
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Default timeout for assertion retries (in milliseconds)
|
|
4
|
+
*/
|
|
5
|
+
export const DEFAULT_TIMEOUT = 5000;
|
|
6
|
+
/**
|
|
7
|
+
* Interval between retry attempts (in milliseconds)
|
|
8
|
+
*/
|
|
9
|
+
export const POLL_INTERVAL = 250;
|
|
10
|
+
/**
|
|
11
|
+
* Sleep for specified milliseconds
|
|
12
|
+
*/
|
|
13
|
+
function sleep(ms) {
|
|
14
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
|
+
}
|
|
16
|
+
const DEFAULT_BASE_URL = "http://localhost:3456";
|
|
17
|
+
/**
|
|
18
|
+
* Escape a string for safe use in shell commands.
|
|
19
|
+
* Uses single quotes and escapes any single quotes within the string.
|
|
20
|
+
* This prevents command injection via backticks, $(), etc.
|
|
21
|
+
*/
|
|
22
|
+
function shellEscape(str) {
|
|
23
|
+
// Single-quote the entire string and escape any embedded single quotes
|
|
24
|
+
// 'foo' -> 'foo'
|
|
25
|
+
// "it's" -> 'it'"'"'s'
|
|
26
|
+
return `'${str.replace(/'/g, "'\"'\"'")}'`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generate a unique session name for isolation between test runs
|
|
30
|
+
*/
|
|
31
|
+
function generateSessionName() {
|
|
32
|
+
return `flowspec-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Execute an agent-browser command and return the output
|
|
36
|
+
*/
|
|
37
|
+
function execBrowser(command, session) {
|
|
38
|
+
try {
|
|
39
|
+
const fullCommand = `agent-browser --session ${session} ${command}`;
|
|
40
|
+
const result = execSync(fullCommand, {
|
|
41
|
+
encoding: "utf-8",
|
|
42
|
+
timeout: 30000,
|
|
43
|
+
shell: process.env.SHELL || "/bin/sh",
|
|
44
|
+
});
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const execError = error;
|
|
49
|
+
throw new Error(execError.stderr ||
|
|
50
|
+
execError.stdout ||
|
|
51
|
+
execError.message ||
|
|
52
|
+
"Browser command failed");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the current page URL
|
|
57
|
+
*/
|
|
58
|
+
function getCurrentUrl(session) {
|
|
59
|
+
return execBrowser('eval "window.location.href"', session).trim();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get the current page text content
|
|
63
|
+
*/
|
|
64
|
+
function getPageContent(session) {
|
|
65
|
+
return execBrowser("snapshot", session);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get interactive elements with refs
|
|
69
|
+
*/
|
|
70
|
+
function getInteractiveSnapshot(session) {
|
|
71
|
+
return execBrowser("snapshot -i", session);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse snapshot output to find element ref by text/label
|
|
75
|
+
* Returns the ref (e.g., "@e3") for the matching element
|
|
76
|
+
*/
|
|
77
|
+
function findElementRef(snapshot, targetText) {
|
|
78
|
+
const lines = snapshot.split("\n");
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
// Match lines with refs like: [ref=e3] followed by element info
|
|
81
|
+
// Format examples:
|
|
82
|
+
// - textbox "Email" [ref=e1]
|
|
83
|
+
// - button "Sign In" [ref=e2]
|
|
84
|
+
// - link "Settings" [ref=e5]
|
|
85
|
+
const refMatch = line.match(/\[ref=(\w+)\]/);
|
|
86
|
+
if (!refMatch)
|
|
87
|
+
continue;
|
|
88
|
+
const ref = `@${refMatch[1]}`;
|
|
89
|
+
// Check if this line contains the target text
|
|
90
|
+
// Could be in quotes as label, or as visible text
|
|
91
|
+
if (line.includes(`"${targetText}"`)) {
|
|
92
|
+
return ref;
|
|
93
|
+
}
|
|
94
|
+
// Also check for partial matches (e.g., "Technical Support" in options)
|
|
95
|
+
const quotedTextMatch = line.match(/"([^"]+)"/g);
|
|
96
|
+
if (quotedTextMatch) {
|
|
97
|
+
for (const quoted of quotedTextMatch) {
|
|
98
|
+
const text = quoted.slice(1, -1); // Remove quotes
|
|
99
|
+
if (text === targetText) {
|
|
100
|
+
return ref;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Find element ref by label (for form fields)
|
|
109
|
+
* Searches for input/textarea/select with the given label
|
|
110
|
+
*/
|
|
111
|
+
function findFieldRefByLabel(snapshot, labelText) {
|
|
112
|
+
const lines = snapshot.split("\n");
|
|
113
|
+
for (const line of lines) {
|
|
114
|
+
const refMatch = line.match(/\[ref=(\w+)\]/);
|
|
115
|
+
if (!refMatch)
|
|
116
|
+
continue;
|
|
117
|
+
// Check for textbox, combobox, or other input types with the label
|
|
118
|
+
const isFormField = line.includes("textbox") ||
|
|
119
|
+
line.includes("combobox") ||
|
|
120
|
+
line.includes("textarea") ||
|
|
121
|
+
line.includes("spinbutton");
|
|
122
|
+
if (isFormField && line.includes(`"${labelText}"`)) {
|
|
123
|
+
return `@${refMatch[1]}`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Execute a visit step
|
|
130
|
+
*/
|
|
131
|
+
function executeVisit(url, baseUrl, session) {
|
|
132
|
+
const fullUrl = url.startsWith("http")
|
|
133
|
+
? url
|
|
134
|
+
: new URL(url, baseUrl).toString();
|
|
135
|
+
execBrowser(`open ${shellEscape(fullUrl)}`, session);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Execute a click step
|
|
139
|
+
*/
|
|
140
|
+
function executeClick(targetText, session) {
|
|
141
|
+
const snapshot = getInteractiveSnapshot(session);
|
|
142
|
+
const ref = findElementRef(snapshot, targetText);
|
|
143
|
+
if (!ref) {
|
|
144
|
+
const currentUrl = getCurrentUrl(session);
|
|
145
|
+
throw new Error(`Could not find element with text "${targetText}" on ${currentUrl}`);
|
|
146
|
+
}
|
|
147
|
+
execBrowser(`click ${ref}`, session);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Execute a fill step
|
|
151
|
+
*/
|
|
152
|
+
function executeFill(fields, session) {
|
|
153
|
+
const snapshot = getInteractiveSnapshot(session);
|
|
154
|
+
for (const [label, value] of Object.entries(fields)) {
|
|
155
|
+
const ref = findFieldRefByLabel(snapshot, label);
|
|
156
|
+
if (!ref) {
|
|
157
|
+
const currentUrl = getCurrentUrl(session);
|
|
158
|
+
throw new Error(`Could not find field with label "${label}" on ${currentUrl}`);
|
|
159
|
+
}
|
|
160
|
+
// Use fill to clear and set value
|
|
161
|
+
execBrowser(`fill ${ref} ${shellEscape(value)}`, session);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execute a select step
|
|
166
|
+
*/
|
|
167
|
+
function executeSelect(selections, session) {
|
|
168
|
+
const snapshot = getInteractiveSnapshot(session);
|
|
169
|
+
for (const [label, option] of Object.entries(selections)) {
|
|
170
|
+
const ref = findFieldRefByLabel(snapshot, label);
|
|
171
|
+
if (!ref) {
|
|
172
|
+
const currentUrl = getCurrentUrl(session);
|
|
173
|
+
throw new Error(`Could not find select field with label "${label}" on ${currentUrl}`);
|
|
174
|
+
}
|
|
175
|
+
execBrowser(`select ${ref} ${shellEscape(option)}`, session);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check if text is visible on the page
|
|
180
|
+
* Returns undefined if found, or an error message if not found
|
|
181
|
+
*/
|
|
182
|
+
function checkTextVisible(text, session) {
|
|
183
|
+
const content = getPageContent(session);
|
|
184
|
+
if (content.includes(text)) {
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
const currentUrl = getCurrentUrl(session);
|
|
188
|
+
return `Text "${text}" not found on ${currentUrl}`;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Execute a wait_for step with retry/polling
|
|
192
|
+
* Waits until the specified text appears on the page
|
|
193
|
+
*/
|
|
194
|
+
async function executeWaitFor(text, session, timeout) {
|
|
195
|
+
// First check: if text is visible, return immediately
|
|
196
|
+
let lastError = checkTextVisible(text, session);
|
|
197
|
+
if (!lastError) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// If timeout is 0, fail immediately
|
|
201
|
+
if (timeout <= 0) {
|
|
202
|
+
throw new Error(lastError);
|
|
203
|
+
}
|
|
204
|
+
// Calculate deadline for retry loop
|
|
205
|
+
const deadline = Date.now() + timeout;
|
|
206
|
+
// Poll loop: sleep, then re-check until found or deadline
|
|
207
|
+
while (Date.now() < deadline) {
|
|
208
|
+
await sleep(POLL_INTERVAL);
|
|
209
|
+
lastError = checkTextVisible(text, session);
|
|
210
|
+
if (!lastError) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Timeout reached: throw the last error
|
|
215
|
+
throw new Error(`Timeout waiting for text "${text}" to appear (waited ${timeout}ms)`);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Execute a single step
|
|
219
|
+
* Returns a Promise to handle async steps like wait_for
|
|
220
|
+
*/
|
|
221
|
+
async function executeStep(step, baseUrl, session, timeout) {
|
|
222
|
+
if ("visit" in step) {
|
|
223
|
+
executeVisit(step.visit, baseUrl, session);
|
|
224
|
+
}
|
|
225
|
+
else if ("click" in step) {
|
|
226
|
+
executeClick(step.click, session);
|
|
227
|
+
}
|
|
228
|
+
else if ("fill" in step) {
|
|
229
|
+
executeFill(step.fill, session);
|
|
230
|
+
}
|
|
231
|
+
else if ("select" in step) {
|
|
232
|
+
executeSelect(step.select, session);
|
|
233
|
+
}
|
|
234
|
+
else if ("wait_for" in step) {
|
|
235
|
+
await executeWaitFor(step.wait_for, session, timeout);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Check a URL assertion
|
|
240
|
+
*/
|
|
241
|
+
function assertUrl(expected, session) {
|
|
242
|
+
const actual = getCurrentUrl(session);
|
|
243
|
+
const passed = actual.endsWith(expected) || actual.includes(expected);
|
|
244
|
+
return { passed, actual };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Check a visible assertion
|
|
248
|
+
*/
|
|
249
|
+
function assertVisible(text, session) {
|
|
250
|
+
const content = getPageContent(session);
|
|
251
|
+
const passed = content.includes(text);
|
|
252
|
+
return { passed, content };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Check a matches (regex) assertion
|
|
256
|
+
*/
|
|
257
|
+
function assertMatches(pattern, session) {
|
|
258
|
+
const content = getPageContent(session);
|
|
259
|
+
const regex = new RegExp(pattern);
|
|
260
|
+
const passed = regex.test(content);
|
|
261
|
+
return { passed, content };
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Check a not_visible assertion
|
|
265
|
+
*/
|
|
266
|
+
function assertNotVisible(text, session) {
|
|
267
|
+
const content = getPageContent(session);
|
|
268
|
+
const passed = !content.includes(text);
|
|
269
|
+
return { passed, content };
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Check a single assertion once (synchronous single-check)
|
|
273
|
+
* Returns error if assertion fails, undefined if it passes
|
|
274
|
+
*/
|
|
275
|
+
function checkAssertion(assertion, session) {
|
|
276
|
+
if ("url" in assertion) {
|
|
277
|
+
const result = assertUrl(assertion.url, session);
|
|
278
|
+
if (!result.passed) {
|
|
279
|
+
return {
|
|
280
|
+
message: `URL assertion failed: expected "${assertion.url}" but got "${result.actual}"`,
|
|
281
|
+
assertion,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else if ("visible" in assertion) {
|
|
286
|
+
const result = assertVisible(assertion.visible, session);
|
|
287
|
+
if (!result.passed) {
|
|
288
|
+
return {
|
|
289
|
+
message: `Visible assertion failed: text "${assertion.visible}" not found on page`,
|
|
290
|
+
assertion,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
else if ("matches" in assertion) {
|
|
295
|
+
try {
|
|
296
|
+
const result = assertMatches(assertion.matches, session);
|
|
297
|
+
if (!result.passed) {
|
|
298
|
+
return {
|
|
299
|
+
message: `Matches assertion failed: pattern "${assertion.matches}" did not match page content`,
|
|
300
|
+
assertion,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
306
|
+
return {
|
|
307
|
+
message: `Matches assertion failed: invalid pattern "${assertion.matches}" - ${message}`,
|
|
308
|
+
assertion,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else if ("not_visible" in assertion) {
|
|
313
|
+
const result = assertNotVisible(assertion.not_visible, session);
|
|
314
|
+
if (!result.passed) {
|
|
315
|
+
return {
|
|
316
|
+
message: `Not visible assertion failed: text "${assertion.not_visible}" was found on page`,
|
|
317
|
+
assertion,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Execute a single assertion with retry/polling
|
|
325
|
+
* Wraps checkAssertion in a poll loop until pass or timeout
|
|
326
|
+
* Returns error if assertion fails after all retries, undefined if it passes
|
|
327
|
+
*/
|
|
328
|
+
async function executeAssertion(assertion, session, timeout) {
|
|
329
|
+
// First check: if it passes, return immediately (zero overhead)
|
|
330
|
+
let lastError = checkAssertion(assertion, session);
|
|
331
|
+
if (!lastError) {
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
// If timeout is 0, no retry - return the error immediately
|
|
335
|
+
if (timeout <= 0) {
|
|
336
|
+
return lastError;
|
|
337
|
+
}
|
|
338
|
+
// Calculate deadline for retry loop
|
|
339
|
+
const deadline = Date.now() + timeout;
|
|
340
|
+
// Poll loop: sleep, then re-check until pass or deadline
|
|
341
|
+
while (Date.now() < deadline) {
|
|
342
|
+
await sleep(POLL_INTERVAL);
|
|
343
|
+
// Re-check assertion (re-fetches page state from browser)
|
|
344
|
+
lastError = checkAssertion(assertion, session);
|
|
345
|
+
if (!lastError) {
|
|
346
|
+
return undefined;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Timeout reached: return the last error
|
|
350
|
+
return lastError;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Close a browser session
|
|
354
|
+
*/
|
|
355
|
+
function closeBrowserSession(session) {
|
|
356
|
+
try {
|
|
357
|
+
execBrowser("close", session);
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// Ignore errors when closing - session may already be closed
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Execute a flow specification and return the result
|
|
365
|
+
* @param flow - The FlowSpec to execute
|
|
366
|
+
* @param options - Optional runner configuration
|
|
367
|
+
* @returns Promise resolving to the FlowResult
|
|
368
|
+
*/
|
|
369
|
+
export async function runFlow(flow, options) {
|
|
370
|
+
const startTime = Date.now();
|
|
371
|
+
const baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL;
|
|
372
|
+
const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
|
|
373
|
+
const session = generateSessionName();
|
|
374
|
+
try {
|
|
375
|
+
// Execute all steps
|
|
376
|
+
for (let stepIndex = 0; stepIndex < flow.steps.length; stepIndex++) {
|
|
377
|
+
const step = flow.steps[stepIndex];
|
|
378
|
+
try {
|
|
379
|
+
await executeStep(step, baseUrl, session, timeout);
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
383
|
+
return {
|
|
384
|
+
success: false,
|
|
385
|
+
flowName: flow.name,
|
|
386
|
+
duration: Date.now() - startTime,
|
|
387
|
+
error: {
|
|
388
|
+
message: errorMessage,
|
|
389
|
+
step: stepIndex,
|
|
390
|
+
action: step,
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// Execute all assertions with retry/polling
|
|
396
|
+
for (const assertion of flow.expect) {
|
|
397
|
+
const assertionError = await executeAssertion(assertion, session, timeout);
|
|
398
|
+
if (assertionError) {
|
|
399
|
+
return {
|
|
400
|
+
success: false,
|
|
401
|
+
flowName: flow.name,
|
|
402
|
+
duration: Date.now() - startTime,
|
|
403
|
+
error: assertionError,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
success: true,
|
|
409
|
+
flowName: flow.name,
|
|
410
|
+
duration: Date.now() - startTime,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
finally {
|
|
414
|
+
// Always close the browser session when done
|
|
415
|
+
closeBrowserSession(session);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|