afterburn-cli 1.0.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 +281 -0
- package/dist/ai/gemini-client.d.ts +21 -0
- package/dist/ai/gemini-client.js +105 -0
- package/dist/ai/gemini-client.js.map +1 -0
- package/dist/ai/index.d.ts +1 -0
- package/dist/ai/index.js +3 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/analysis/diagnosis-schema.d.ts +106 -0
- package/dist/analysis/diagnosis-schema.js +54 -0
- package/dist/analysis/diagnosis-schema.js.map +1 -0
- package/dist/analysis/error-analyzer.d.ts +9 -0
- package/dist/analysis/error-analyzer.js +573 -0
- package/dist/analysis/error-analyzer.js.map +1 -0
- package/dist/analysis/index.d.ts +4 -0
- package/dist/analysis/index.js +6 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/source-mapper.d.ts +19 -0
- package/dist/analysis/source-mapper.js +329 -0
- package/dist/analysis/source-mapper.js.map +1 -0
- package/dist/analysis/ui-auditor.d.ts +9 -0
- package/dist/analysis/ui-auditor.js +104 -0
- package/dist/analysis/ui-auditor.js.map +1 -0
- package/dist/artifacts/artifact-storage.d.ts +44 -0
- package/dist/artifacts/artifact-storage.js +99 -0
- package/dist/artifacts/artifact-storage.js.map +1 -0
- package/dist/artifacts/index.d.ts +1 -0
- package/dist/artifacts/index.js +3 -0
- package/dist/artifacts/index.js.map +1 -0
- package/dist/browser/browser-manager.d.ts +45 -0
- package/dist/browser/browser-manager.js +88 -0
- package/dist/browser/browser-manager.js.map +1 -0
- package/dist/browser/challenge-detector.d.ts +10 -0
- package/dist/browser/challenge-detector.js +58 -0
- package/dist/browser/challenge-detector.js.map +1 -0
- package/dist/browser/cookie-dismisser.d.ts +18 -0
- package/dist/browser/cookie-dismisser.js +76 -0
- package/dist/browser/cookie-dismisser.js.map +1 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.js +6 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/stealth-browser.d.ts +13 -0
- package/dist/browser/stealth-browser.js +59 -0
- package/dist/browser/stealth-browser.js.map +1 -0
- package/dist/cli/commander-cli.d.ts +2 -0
- package/dist/cli/commander-cli.js +150 -0
- package/dist/cli/commander-cli.js.map +1 -0
- package/dist/cli/doctor.d.ts +34 -0
- package/dist/cli/doctor.js +124 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/first-run.d.ts +6 -0
- package/dist/cli/first-run.js +58 -0
- package/dist/cli/first-run.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/progress.d.ts +11 -0
- package/dist/cli/progress.js +30 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/core/engine.d.ts +33 -0
- package/dist/core/engine.js +269 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/validation.d.ts +52 -0
- package/dist/core/validation.js +228 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/discovery/crawler.d.ts +58 -0
- package/dist/discovery/crawler.js +240 -0
- package/dist/discovery/crawler.js.map +1 -0
- package/dist/discovery/discovery-pipeline.d.ts +22 -0
- package/dist/discovery/discovery-pipeline.js +256 -0
- package/dist/discovery/discovery-pipeline.js.map +1 -0
- package/dist/discovery/element-mapper.d.ts +21 -0
- package/dist/discovery/element-mapper.js +422 -0
- package/dist/discovery/element-mapper.js.map +1 -0
- package/dist/discovery/index.d.ts +8 -0
- package/dist/discovery/index.js +8 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/link-validator.d.ts +15 -0
- package/dist/discovery/link-validator.js +137 -0
- package/dist/discovery/link-validator.js.map +1 -0
- package/dist/discovery/sitemap-builder.d.ts +19 -0
- package/dist/discovery/sitemap-builder.js +166 -0
- package/dist/discovery/sitemap-builder.js.map +1 -0
- package/dist/discovery/spa-detector.d.ts +12 -0
- package/dist/discovery/spa-detector.js +271 -0
- package/dist/discovery/spa-detector.js.map +1 -0
- package/dist/execution/error-detector.d.ts +10 -0
- package/dist/execution/error-detector.js +87 -0
- package/dist/execution/error-detector.js.map +1 -0
- package/dist/execution/evidence-capture.d.ts +8 -0
- package/dist/execution/evidence-capture.js +37 -0
- package/dist/execution/evidence-capture.js.map +1 -0
- package/dist/execution/index.d.ts +5 -0
- package/dist/execution/index.js +7 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/step-handlers.d.ts +48 -0
- package/dist/execution/step-handlers.js +349 -0
- package/dist/execution/step-handlers.js.map +1 -0
- package/dist/execution/test-data.d.ts +50 -0
- package/dist/execution/test-data.js +160 -0
- package/dist/execution/test-data.js.map +1 -0
- package/dist/execution/workflow-executor.d.ts +56 -0
- package/dist/execution/workflow-executor.js +331 -0
- package/dist/execution/workflow-executor.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/entry.d.ts +2 -0
- package/dist/mcp/entry.js +5 -0
- package/dist/mcp/entry.js.map +1 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +4 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +19 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +2 -0
- package/dist/mcp/tools.js +162 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/planning/heuristic-planner.d.ts +7 -0
- package/dist/planning/heuristic-planner.js +238 -0
- package/dist/planning/heuristic-planner.js.map +1 -0
- package/dist/planning/index.d.ts +3 -0
- package/dist/planning/index.js +5 -0
- package/dist/planning/index.js.map +1 -0
- package/dist/planning/plan-schema.d.ts +74 -0
- package/dist/planning/plan-schema.js +39 -0
- package/dist/planning/plan-schema.js.map +1 -0
- package/dist/planning/workflow-planner.d.ts +39 -0
- package/dist/planning/workflow-planner.js +211 -0
- package/dist/planning/workflow-planner.js.map +1 -0
- package/dist/reports/health-scorer.d.ts +14 -0
- package/dist/reports/health-scorer.js +88 -0
- package/dist/reports/health-scorer.js.map +1 -0
- package/dist/reports/html-generator.d.ts +10 -0
- package/dist/reports/html-generator.js +155 -0
- package/dist/reports/html-generator.js.map +1 -0
- package/dist/reports/index.d.ts +4 -0
- package/dist/reports/index.js +6 -0
- package/dist/reports/index.js.map +1 -0
- package/dist/reports/markdown-generator.d.ts +10 -0
- package/dist/reports/markdown-generator.js +334 -0
- package/dist/reports/markdown-generator.js.map +1 -0
- package/dist/reports/priority-ranker.d.ts +22 -0
- package/dist/reports/priority-ranker.js +608 -0
- package/dist/reports/priority-ranker.js.map +1 -0
- package/dist/screenshots/dual-format.d.ts +14 -0
- package/dist/screenshots/dual-format.js +59 -0
- package/dist/screenshots/dual-format.js.map +1 -0
- package/dist/screenshots/index.d.ts +2 -0
- package/dist/screenshots/index.js +4 -0
- package/dist/screenshots/index.js.map +1 -0
- package/dist/screenshots/screenshot-manager.d.ts +33 -0
- package/dist/screenshots/screenshot-manager.js +86 -0
- package/dist/screenshots/screenshot-manager.js.map +1 -0
- package/dist/testing/accessibility-auditor.d.ts +23 -0
- package/dist/testing/accessibility-auditor.js +44 -0
- package/dist/testing/accessibility-auditor.js.map +1 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/meta-auditor.d.ts +16 -0
- package/dist/testing/meta-auditor.js +268 -0
- package/dist/testing/meta-auditor.js.map +1 -0
- package/dist/testing/performance-monitor.d.ts +15 -0
- package/dist/testing/performance-monitor.js +64 -0
- package/dist/testing/performance-monitor.js.map +1 -0
- package/dist/types/artifacts.d.ts +58 -0
- package/dist/types/artifacts.js +3 -0
- package/dist/types/artifacts.js.map +1 -0
- package/dist/types/discovery.d.ts +124 -0
- package/dist/types/discovery.js +3 -0
- package/dist/types/discovery.js.map +1 -0
- package/dist/types/execution.d.ts +154 -0
- package/dist/types/execution.js +3 -0
- package/dist/types/execution.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/sanitizer.d.ts +25 -0
- package/dist/utils/sanitizer.js +98 -0
- package/dist/utils/sanitizer.js.map +1 -0
- package/package.json +86 -0
- package/templates/report.hbs +202 -0
- package/templates/styles/report.css +607 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Page } from 'playwright-core';
|
|
2
|
+
import type { StepResult, DeadButtonResult, BrokenFormResult } from '../types/execution.js';
|
|
3
|
+
import type { WorkflowStep, FormInfo } from '../types/discovery.js';
|
|
4
|
+
export declare const DEAD_BUTTON_WAIT = 500;
|
|
5
|
+
/**
|
|
6
|
+
* Convert legacy LLM selector strings into Playwright selector engines.
|
|
7
|
+
* Supports getByRole/getByLabel/getByText compatibility for older plans.
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalizeStepSelector(selector: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Main dispatcher - executes a workflow step and returns structured result
|
|
12
|
+
*/
|
|
13
|
+
export declare function executeStep(page: Page, step: WorkflowStep, stepIndex: number, baseUrl?: string): Promise<StepResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Fill all fields in a form with test data
|
|
16
|
+
*/
|
|
17
|
+
export declare function fillFormFields(page: Page, form: FormInfo): Promise<{
|
|
18
|
+
filled: number;
|
|
19
|
+
skipped: Array<{
|
|
20
|
+
selector: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
}>;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Snapshot of page state used for dead-button comparison (no re-click needed)
|
|
26
|
+
*/
|
|
27
|
+
export interface ClickStateSnapshot {
|
|
28
|
+
url: string;
|
|
29
|
+
domSize: number;
|
|
30
|
+
hadNetworkActivity: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Capture current page state for dead-button comparison
|
|
34
|
+
*/
|
|
35
|
+
export declare function captureClickState(page: Page): Promise<ClickStateSnapshot>;
|
|
36
|
+
/**
|
|
37
|
+
* Compare pre/post click state to detect dead buttons (no re-click)
|
|
38
|
+
*/
|
|
39
|
+
export declare function checkDeadButton(selector: string, before: ClickStateSnapshot, after: ClickStateSnapshot): DeadButtonResult;
|
|
40
|
+
/**
|
|
41
|
+
* Detect broken forms by checking if submit has any effect
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectBrokenForm(page: Page, formSelector: string): Promise<BrokenFormResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Dismiss modals/popups that might block interaction
|
|
46
|
+
* Tries multiple strategies: close button, Escape key, native dialog dismissal
|
|
47
|
+
*/
|
|
48
|
+
export declare function dismissModalIfPresent(page: Page): Promise<void>;
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
// Workflow step action handlers: fill, click, navigate, select, wait, expect with error recovery
|
|
2
|
+
import { getTestValueForField } from './test-data.js';
|
|
3
|
+
import { validateUrl, validateNavigationUrl, validateSelector, sanitizeValue } from '../core/validation.js';
|
|
4
|
+
// Step execution timeouts
|
|
5
|
+
const STEP_TIMEOUT = 10_000;
|
|
6
|
+
const NAV_TIMEOUT = 30_000;
|
|
7
|
+
export const DEAD_BUTTON_WAIT = 500;
|
|
8
|
+
/**
|
|
9
|
+
* Convert legacy LLM selector strings into Playwright selector engines.
|
|
10
|
+
* Supports getByRole/getByLabel/getByText compatibility for older plans.
|
|
11
|
+
*/
|
|
12
|
+
export function normalizeStepSelector(selector) {
|
|
13
|
+
const trimmed = selector.trim();
|
|
14
|
+
const roleMatch = trimmed.match(/^(?:page\.)?getByRole\(\s*['"]([^'"]+)['"]\s*(?:,\s*\{\s*name\s*:\s*['"]([^'"]+)['"]\s*\})?\s*\)$/);
|
|
15
|
+
if (roleMatch) {
|
|
16
|
+
const role = roleMatch[1];
|
|
17
|
+
const name = roleMatch[2]?.replace(/"/g, '\\"');
|
|
18
|
+
return name ? `role=${role}[name="${name}"]` : `role=${role}`;
|
|
19
|
+
}
|
|
20
|
+
const labelMatch = trimmed.match(/^(?:page\.)?getByLabel\(\s*['"]([^'"]+)['"]\s*\)$/);
|
|
21
|
+
if (labelMatch) {
|
|
22
|
+
const label = labelMatch[1].replace(/"/g, '\\"');
|
|
23
|
+
return `label=${label}`;
|
|
24
|
+
}
|
|
25
|
+
const textMatch = trimmed.match(/^(?:page\.)?getByText\(\s*['"]([^'"]+)['"]\s*\)$/);
|
|
26
|
+
if (textMatch) {
|
|
27
|
+
const text = textMatch[1].replace(/"/g, '\\"');
|
|
28
|
+
return `text=${text}`;
|
|
29
|
+
}
|
|
30
|
+
return selector;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Main dispatcher - executes a workflow step and returns structured result
|
|
34
|
+
*/
|
|
35
|
+
export async function executeStep(page, step, stepIndex, baseUrl) {
|
|
36
|
+
const startTime = Date.now();
|
|
37
|
+
const normalizedSelector = normalizeStepSelector(step.selector);
|
|
38
|
+
try {
|
|
39
|
+
// Dismiss any modals that might interfere
|
|
40
|
+
await dismissModalIfPresent(page);
|
|
41
|
+
// Security: validate selector length to prevent injection via oversized strings
|
|
42
|
+
validateSelector(normalizedSelector);
|
|
43
|
+
// Security: sanitize value to strip script injections from AI-generated content
|
|
44
|
+
const safeValue = step.value ? sanitizeValue(step.value) : undefined;
|
|
45
|
+
switch (step.action) {
|
|
46
|
+
case 'navigate':
|
|
47
|
+
// Security: validate navigation targets; enforce same-origin when baseUrl is known
|
|
48
|
+
const targetInput = safeValue || normalizedSelector;
|
|
49
|
+
const targetUrl = baseUrl ? new URL(targetInput, baseUrl).href : targetInput;
|
|
50
|
+
if (baseUrl) {
|
|
51
|
+
validateNavigationUrl(targetUrl, baseUrl);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
validateUrl(targetUrl);
|
|
55
|
+
}
|
|
56
|
+
const baseOrigin = baseUrl ? new URL(baseUrl).origin : null;
|
|
57
|
+
await page.goto(targetUrl, {
|
|
58
|
+
waitUntil: 'domcontentloaded',
|
|
59
|
+
timeout: NAV_TIMEOUT,
|
|
60
|
+
});
|
|
61
|
+
// Verify we stayed on the same origin
|
|
62
|
+
const afterOrigin = new URL(page.url()).origin;
|
|
63
|
+
if (baseOrigin && afterOrigin !== baseOrigin) {
|
|
64
|
+
throw new Error(`Navigation blocked: left origin ${baseOrigin} to ${afterOrigin}`);
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
case 'click':
|
|
68
|
+
await page.click(normalizedSelector, { timeout: STEP_TIMEOUT });
|
|
69
|
+
break;
|
|
70
|
+
case 'fill':
|
|
71
|
+
await page.fill(normalizedSelector, safeValue || '', { timeout: STEP_TIMEOUT });
|
|
72
|
+
break;
|
|
73
|
+
case 'select':
|
|
74
|
+
await page.selectOption(normalizedSelector, safeValue || '', { timeout: STEP_TIMEOUT });
|
|
75
|
+
break;
|
|
76
|
+
case 'wait':
|
|
77
|
+
await page.waitForSelector(normalizedSelector, { timeout: STEP_TIMEOUT });
|
|
78
|
+
break;
|
|
79
|
+
case 'expect':
|
|
80
|
+
// Verify element is visible
|
|
81
|
+
const isVisible = await page.isVisible(normalizedSelector);
|
|
82
|
+
if (!isVisible) {
|
|
83
|
+
throw new Error(`Expected element not found: ${normalizedSelector}`);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unknown action: ${step.action}`);
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
stepIndex,
|
|
91
|
+
action: step.action,
|
|
92
|
+
selector: step.selector,
|
|
93
|
+
status: 'passed',
|
|
94
|
+
duration: Date.now() - startTime,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
stepIndex,
|
|
100
|
+
action: step.action,
|
|
101
|
+
selector: step.selector,
|
|
102
|
+
status: 'failed',
|
|
103
|
+
duration: Date.now() - startTime,
|
|
104
|
+
error: error instanceof Error ? error.message : String(error),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Fill an individual form field with test data
|
|
110
|
+
* Returns { skipped: boolean, reason?: string }
|
|
111
|
+
*/
|
|
112
|
+
async function fillField(page, field, timeout) {
|
|
113
|
+
const testValue = getTestValueForField(field.name, field.type);
|
|
114
|
+
// Skip unrecognized fields
|
|
115
|
+
if (testValue === null) {
|
|
116
|
+
return { skipped: true, reason: `No test data for type: ${field.type}` };
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
// Build selector - try by name first, fall back to id
|
|
120
|
+
let selector = field.name.startsWith('#') ? field.name : `[name="${field.name}"]`;
|
|
121
|
+
// Check if field exists and is visible
|
|
122
|
+
let exists = await page.locator(selector).count();
|
|
123
|
+
if (exists === 0) {
|
|
124
|
+
// Fallback: try by id
|
|
125
|
+
selector = `#${field.name}`;
|
|
126
|
+
exists = await page.locator(selector).count();
|
|
127
|
+
}
|
|
128
|
+
if (exists === 0) {
|
|
129
|
+
return { skipped: true, reason: 'Field not found' };
|
|
130
|
+
}
|
|
131
|
+
// Handle different field types
|
|
132
|
+
if (field.type === 'checkbox' || field.type === 'radio') {
|
|
133
|
+
await page.check(selector, { timeout });
|
|
134
|
+
}
|
|
135
|
+
else if (field.type === 'select' || field.type === 'select-one') {
|
|
136
|
+
// Try the test value first; if no matching option exists, pick the first non-empty option
|
|
137
|
+
try {
|
|
138
|
+
await page.selectOption(selector, testValue, { timeout });
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
const firstOption = await page.evaluate((sel) => {
|
|
142
|
+
const select = document.querySelector(sel);
|
|
143
|
+
if (!select)
|
|
144
|
+
return null;
|
|
145
|
+
const option = Array.from(select.options).find(o => o.value && o.value !== '');
|
|
146
|
+
return option?.value ?? null;
|
|
147
|
+
}, selector);
|
|
148
|
+
if (firstOption) {
|
|
149
|
+
await page.selectOption(selector, firstOption, { timeout });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else if (field.type === 'textarea') {
|
|
154
|
+
await page.fill(selector, testValue, { timeout });
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// text, email, password, tel, date, etc.
|
|
158
|
+
await page.fill(selector, testValue, { timeout });
|
|
159
|
+
}
|
|
160
|
+
return { skipped: false };
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return {
|
|
164
|
+
skipped: true,
|
|
165
|
+
reason: error instanceof Error ? error.message : 'Unknown error',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Fill all fields in a form with test data
|
|
171
|
+
*/
|
|
172
|
+
export async function fillFormFields(page, form) {
|
|
173
|
+
let filled = 0;
|
|
174
|
+
const skipped = [];
|
|
175
|
+
for (const field of form.fields) {
|
|
176
|
+
const result = await fillField(page, field, STEP_TIMEOUT);
|
|
177
|
+
if (result.skipped) {
|
|
178
|
+
skipped.push({
|
|
179
|
+
selector: `[name="${field.name}"]`,
|
|
180
|
+
reason: result.reason || 'Unknown',
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
filled++;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return { filled, skipped };
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Capture current page state for dead-button comparison
|
|
191
|
+
*/
|
|
192
|
+
export async function captureClickState(page) {
|
|
193
|
+
return {
|
|
194
|
+
url: page.url(),
|
|
195
|
+
domSize: await page.evaluate(() => document.body.innerHTML.length),
|
|
196
|
+
hadNetworkActivity: false, // Caller sets this via network listener
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Compare pre/post click state to detect dead buttons (no re-click)
|
|
201
|
+
*/
|
|
202
|
+
export function checkDeadButton(selector, before, after) {
|
|
203
|
+
const urlChanged = before.url !== after.url;
|
|
204
|
+
const domChanged = Math.abs(after.domSize - before.domSize) > 100;
|
|
205
|
+
const hasNetwork = after.hadNetworkActivity;
|
|
206
|
+
if (!urlChanged && !domChanged && !hasNetwork) {
|
|
207
|
+
return { isDead: true, selector, reason: 'No URL change, DOM change, or network activity detected' };
|
|
208
|
+
}
|
|
209
|
+
return { isDead: false, selector };
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Detect broken forms by checking if submit has any effect
|
|
213
|
+
*/
|
|
214
|
+
export async function detectBrokenForm(page, formSelector) {
|
|
215
|
+
try {
|
|
216
|
+
// Find the form
|
|
217
|
+
const formExists = await page.locator(formSelector).count();
|
|
218
|
+
if (formExists === 0) {
|
|
219
|
+
return {
|
|
220
|
+
isBroken: false,
|
|
221
|
+
formSelector,
|
|
222
|
+
reason: 'Form not found',
|
|
223
|
+
filledFields: 0,
|
|
224
|
+
skippedFields: 0,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
// Extract form info
|
|
228
|
+
const formData = await page.evaluate((selector) => {
|
|
229
|
+
const form = document.querySelector(selector);
|
|
230
|
+
if (!form)
|
|
231
|
+
return null;
|
|
232
|
+
const fields = [];
|
|
233
|
+
const inputs = form.querySelectorAll('input, select, textarea');
|
|
234
|
+
inputs.forEach((input) => {
|
|
235
|
+
const fieldName = input.name || input.id;
|
|
236
|
+
if (fieldName && input.type !== 'submit' && input.type !== 'button') {
|
|
237
|
+
fields.push({
|
|
238
|
+
type: input.type || 'text',
|
|
239
|
+
name: fieldName,
|
|
240
|
+
label: input.placeholder || input.name || input.id || '',
|
|
241
|
+
required: input.required || false,
|
|
242
|
+
placeholder: input.placeholder || '',
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
action: form.action,
|
|
248
|
+
method: form.method || 'GET',
|
|
249
|
+
selector,
|
|
250
|
+
fields,
|
|
251
|
+
};
|
|
252
|
+
}, formSelector);
|
|
253
|
+
if (!formData) {
|
|
254
|
+
return {
|
|
255
|
+
isBroken: false,
|
|
256
|
+
formSelector,
|
|
257
|
+
reason: 'Could not extract form data',
|
|
258
|
+
filledFields: 0,
|
|
259
|
+
skippedFields: 0,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// Fill form fields
|
|
263
|
+
const fillResult = await fillFormFields(page, formData);
|
|
264
|
+
// Capture pre-submit state
|
|
265
|
+
const urlBefore = page.url();
|
|
266
|
+
let networkActivity = false;
|
|
267
|
+
const networkListener = () => { networkActivity = true; };
|
|
268
|
+
page.on('request', networkListener);
|
|
269
|
+
// Submit form
|
|
270
|
+
const submitButton = await page.locator(`${formSelector} button[type="submit"], ${formSelector} input[type="submit"], ${formSelector} button[type="button"], ${formSelector} button:not([type])`).first();
|
|
271
|
+
if (await submitButton.count() > 0) {
|
|
272
|
+
await submitButton.click({ timeout: STEP_TIMEOUT });
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
// Try form.submit() as fallback
|
|
276
|
+
await page.evaluate((selector) => {
|
|
277
|
+
const form = document.querySelector(selector);
|
|
278
|
+
if (form)
|
|
279
|
+
form.submit();
|
|
280
|
+
}, formSelector);
|
|
281
|
+
}
|
|
282
|
+
// Wait for any effects
|
|
283
|
+
await page.waitForTimeout(DEAD_BUTTON_WAIT);
|
|
284
|
+
// Capture post-submit state
|
|
285
|
+
const urlAfter = page.url();
|
|
286
|
+
// Clean up listener
|
|
287
|
+
page.off('request', networkListener);
|
|
288
|
+
// Check if anything happened
|
|
289
|
+
const hasNavigation = urlBefore !== urlAfter;
|
|
290
|
+
const hasNetworkActivity = networkActivity;
|
|
291
|
+
if (!hasNavigation && !hasNetworkActivity) {
|
|
292
|
+
return {
|
|
293
|
+
isBroken: true,
|
|
294
|
+
formSelector,
|
|
295
|
+
reason: 'Form submission caused no navigation or network request',
|
|
296
|
+
filledFields: fillResult.filled,
|
|
297
|
+
skippedFields: fillResult.skipped.length,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
isBroken: false,
|
|
302
|
+
formSelector,
|
|
303
|
+
filledFields: fillResult.filled,
|
|
304
|
+
skippedFields: fillResult.skipped.length,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
return {
|
|
309
|
+
isBroken: false,
|
|
310
|
+
formSelector,
|
|
311
|
+
reason: `Detection failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
312
|
+
filledFields: 0,
|
|
313
|
+
skippedFields: 0,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Dismiss modals/popups that might block interaction
|
|
319
|
+
* Tries multiple strategies: close button, Escape key, native dialog dismissal
|
|
320
|
+
*/
|
|
321
|
+
export async function dismissModalIfPresent(page) {
|
|
322
|
+
try {
|
|
323
|
+
// Note: Native dialog handling (alert/confirm/prompt) is done by a single persistent
|
|
324
|
+
// handler registered in workflow-executor.ts — NOT here. Registering per-step handlers
|
|
325
|
+
// caused stacked handlers to crash when multiple tried to dismiss the same dialog.
|
|
326
|
+
// Try to find and click common modal close buttons
|
|
327
|
+
const closeSelectors = [
|
|
328
|
+
'[aria-label*="close" i]',
|
|
329
|
+
'[aria-label*="dismiss" i]',
|
|
330
|
+
'button.close',
|
|
331
|
+
'button.modal-close',
|
|
332
|
+
'.modal-close-button',
|
|
333
|
+
'[data-dismiss="modal"]',
|
|
334
|
+
];
|
|
335
|
+
for (const selector of closeSelectors) {
|
|
336
|
+
const closeButton = page.locator(selector).first();
|
|
337
|
+
if (await closeButton.isVisible({ timeout: 500 }).catch(() => false)) {
|
|
338
|
+
await closeButton.click({ timeout: 1000 });
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// Fallback: press Escape
|
|
343
|
+
await page.keyboard.press('Escape');
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
// Fail silently - modal dismissal is best-effort
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=step-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-handlers.js","sourceRoot":"","sources":["../../src/execution/step-handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predefined test data for reproducible form filling
|
|
3
|
+
*/
|
|
4
|
+
export declare const TEST_DATA: {
|
|
5
|
+
readonly personal: {
|
|
6
|
+
readonly firstName: "John";
|
|
7
|
+
readonly lastName: "Doe";
|
|
8
|
+
readonly fullName: "John Doe";
|
|
9
|
+
readonly email: "test@example.com";
|
|
10
|
+
readonly phone: "555-0100";
|
|
11
|
+
readonly phoneFormatted: "(555) 010-0100";
|
|
12
|
+
};
|
|
13
|
+
readonly address: {
|
|
14
|
+
readonly street: "123 Test Street";
|
|
15
|
+
readonly street2: "Apt 4B";
|
|
16
|
+
readonly city: "Testville";
|
|
17
|
+
readonly state: "California";
|
|
18
|
+
readonly stateCode: "CA";
|
|
19
|
+
readonly zip: "90210";
|
|
20
|
+
readonly zipCode: "90210";
|
|
21
|
+
readonly postalCode: "90210";
|
|
22
|
+
readonly country: "United States";
|
|
23
|
+
readonly countryCode: "US";
|
|
24
|
+
};
|
|
25
|
+
readonly account: {
|
|
26
|
+
readonly username: "testuser";
|
|
27
|
+
readonly password: "Test1234!";
|
|
28
|
+
readonly confirmPassword: "Test1234!";
|
|
29
|
+
readonly securityQuestion: "What is your favorite color?";
|
|
30
|
+
readonly securityAnswer: "Blue";
|
|
31
|
+
};
|
|
32
|
+
readonly payment: {
|
|
33
|
+
readonly cardNumber: "4242424242424242";
|
|
34
|
+
readonly cardExpiry: "12/34";
|
|
35
|
+
readonly expiryMonth: "12";
|
|
36
|
+
readonly expiryYear: "2034";
|
|
37
|
+
readonly cardCVV: "123";
|
|
38
|
+
readonly cvv: "123";
|
|
39
|
+
readonly cardholderName: "John Doe";
|
|
40
|
+
};
|
|
41
|
+
readonly dates: {
|
|
42
|
+
readonly date: "2020-02-02";
|
|
43
|
+
readonly time: "13:15";
|
|
44
|
+
readonly datetime: "2020-02-02T13:15";
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Map field name/type to appropriate test data value
|
|
49
|
+
*/
|
|
50
|
+
export declare function getTestValueForField(fieldName: string, fieldType: string): string | null;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Fixed test data constants for form filling and workflow execution
|
|
2
|
+
/**
|
|
3
|
+
* Predefined test data for reproducible form filling
|
|
4
|
+
*/
|
|
5
|
+
export const TEST_DATA = {
|
|
6
|
+
personal: {
|
|
7
|
+
firstName: 'John',
|
|
8
|
+
lastName: 'Doe',
|
|
9
|
+
fullName: 'John Doe',
|
|
10
|
+
email: 'test@example.com',
|
|
11
|
+
phone: '555-0100',
|
|
12
|
+
phoneFormatted: '(555) 010-0100',
|
|
13
|
+
},
|
|
14
|
+
address: {
|
|
15
|
+
street: '123 Test Street',
|
|
16
|
+
street2: 'Apt 4B',
|
|
17
|
+
city: 'Testville',
|
|
18
|
+
state: 'California',
|
|
19
|
+
stateCode: 'CA',
|
|
20
|
+
zip: '90210',
|
|
21
|
+
zipCode: '90210',
|
|
22
|
+
postalCode: '90210',
|
|
23
|
+
country: 'United States',
|
|
24
|
+
countryCode: 'US',
|
|
25
|
+
},
|
|
26
|
+
account: {
|
|
27
|
+
username: 'testuser',
|
|
28
|
+
password: 'Test1234!',
|
|
29
|
+
confirmPassword: 'Test1234!',
|
|
30
|
+
securityQuestion: 'What is your favorite color?',
|
|
31
|
+
securityAnswer: 'Blue',
|
|
32
|
+
},
|
|
33
|
+
payment: {
|
|
34
|
+
cardNumber: '4242424242424242',
|
|
35
|
+
cardExpiry: '12/34',
|
|
36
|
+
expiryMonth: '12',
|
|
37
|
+
expiryYear: '2034',
|
|
38
|
+
cardCVV: '123',
|
|
39
|
+
cvv: '123',
|
|
40
|
+
cardholderName: 'John Doe',
|
|
41
|
+
},
|
|
42
|
+
dates: {
|
|
43
|
+
date: '2020-02-02',
|
|
44
|
+
time: '13:15',
|
|
45
|
+
datetime: '2020-02-02T13:15',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Map field name/type to appropriate test data value
|
|
50
|
+
*/
|
|
51
|
+
export function getTestValueForField(fieldName, fieldType) {
|
|
52
|
+
const lowerName = fieldName.toLowerCase();
|
|
53
|
+
const lowerType = fieldType.toLowerCase();
|
|
54
|
+
// Email fields
|
|
55
|
+
if (lowerType === 'email' || lowerName.includes('email')) {
|
|
56
|
+
return TEST_DATA.personal.email;
|
|
57
|
+
}
|
|
58
|
+
// Password fields
|
|
59
|
+
if (lowerType === 'password' || lowerName.includes('password')) {
|
|
60
|
+
if (lowerName.includes('confirm')) {
|
|
61
|
+
return TEST_DATA.account.confirmPassword;
|
|
62
|
+
}
|
|
63
|
+
return TEST_DATA.account.password;
|
|
64
|
+
}
|
|
65
|
+
// Phone fields
|
|
66
|
+
if (lowerType === 'tel' || lowerName.includes('phone') || lowerName.includes('tel')) {
|
|
67
|
+
return TEST_DATA.personal.phone;
|
|
68
|
+
}
|
|
69
|
+
// Name fields
|
|
70
|
+
if (lowerName.includes('firstname') || lowerName.includes('first-name') || lowerName.includes('first_name')) {
|
|
71
|
+
return TEST_DATA.personal.firstName;
|
|
72
|
+
}
|
|
73
|
+
if (lowerName.includes('lastname') || lowerName.includes('last-name') || lowerName.includes('last_name')) {
|
|
74
|
+
return TEST_DATA.personal.lastName;
|
|
75
|
+
}
|
|
76
|
+
if (lowerName.includes('fullname') || lowerName.includes('full-name') || lowerName.includes('name')) {
|
|
77
|
+
return TEST_DATA.personal.fullName;
|
|
78
|
+
}
|
|
79
|
+
// Address fields
|
|
80
|
+
if (lowerName.includes('street') || lowerName.includes('address1') || lowerName.includes('address-1')) {
|
|
81
|
+
return TEST_DATA.address.street;
|
|
82
|
+
}
|
|
83
|
+
if (lowerName.includes('address2') || lowerName.includes('address-2') || lowerName.includes('apt') || lowerName.includes('suite')) {
|
|
84
|
+
return TEST_DATA.address.street2;
|
|
85
|
+
}
|
|
86
|
+
if (lowerName.includes('city')) {
|
|
87
|
+
return TEST_DATA.address.city;
|
|
88
|
+
}
|
|
89
|
+
if (lowerName.includes('state') && !lowerName.includes('country')) {
|
|
90
|
+
return lowerName.includes('code') ? TEST_DATA.address.stateCode : TEST_DATA.address.state;
|
|
91
|
+
}
|
|
92
|
+
if (lowerName.includes('zip') || lowerName.includes('postal')) {
|
|
93
|
+
return TEST_DATA.address.zip;
|
|
94
|
+
}
|
|
95
|
+
if (lowerName.includes('country')) {
|
|
96
|
+
return lowerName.includes('code') ? TEST_DATA.address.countryCode : TEST_DATA.address.country;
|
|
97
|
+
}
|
|
98
|
+
// Account fields
|
|
99
|
+
if (lowerName.includes('username') || lowerName.includes('user-name')) {
|
|
100
|
+
return TEST_DATA.account.username;
|
|
101
|
+
}
|
|
102
|
+
if (lowerName.includes('security') && lowerName.includes('question')) {
|
|
103
|
+
return TEST_DATA.account.securityQuestion;
|
|
104
|
+
}
|
|
105
|
+
if (lowerName.includes('security') && lowerName.includes('answer')) {
|
|
106
|
+
return TEST_DATA.account.securityAnswer;
|
|
107
|
+
}
|
|
108
|
+
// Payment fields
|
|
109
|
+
if (lowerName.includes('card') && (lowerName.includes('number') || lowerName.includes('num'))) {
|
|
110
|
+
return TEST_DATA.payment.cardNumber;
|
|
111
|
+
}
|
|
112
|
+
if (lowerName.includes('expir') || lowerName.includes('expiry')) {
|
|
113
|
+
if (lowerName.includes('month')) {
|
|
114
|
+
return TEST_DATA.payment.expiryMonth;
|
|
115
|
+
}
|
|
116
|
+
if (lowerName.includes('year')) {
|
|
117
|
+
return TEST_DATA.payment.expiryYear;
|
|
118
|
+
}
|
|
119
|
+
return TEST_DATA.payment.cardExpiry;
|
|
120
|
+
}
|
|
121
|
+
if (lowerName.includes('cvv') || lowerName.includes('cvc') || lowerName.includes('security-code')) {
|
|
122
|
+
return TEST_DATA.payment.cvv;
|
|
123
|
+
}
|
|
124
|
+
if (lowerName.includes('cardholder') || (lowerName.includes('card') && lowerName.includes('name'))) {
|
|
125
|
+
return TEST_DATA.payment.cardholderName;
|
|
126
|
+
}
|
|
127
|
+
// Date/time fields
|
|
128
|
+
if (lowerType === 'date' || lowerName.includes('date')) {
|
|
129
|
+
return TEST_DATA.dates.date;
|
|
130
|
+
}
|
|
131
|
+
if (lowerType === 'time' || lowerName.includes('time')) {
|
|
132
|
+
return TEST_DATA.dates.time;
|
|
133
|
+
}
|
|
134
|
+
if (lowerType === 'datetime-local' || lowerName.includes('datetime')) {
|
|
135
|
+
return TEST_DATA.dates.datetime;
|
|
136
|
+
}
|
|
137
|
+
// URL fields
|
|
138
|
+
if (lowerType === 'url' || lowerName.includes('url') || lowerName.includes('website')) {
|
|
139
|
+
return 'https://example.com';
|
|
140
|
+
}
|
|
141
|
+
// Textarea fields
|
|
142
|
+
if (lowerType === 'textarea') {
|
|
143
|
+
return 'This is a test message for the form.';
|
|
144
|
+
}
|
|
145
|
+
// Number fields
|
|
146
|
+
if (lowerType === 'number' || lowerType === 'range') {
|
|
147
|
+
return '5';
|
|
148
|
+
}
|
|
149
|
+
// Generic text input (fallback)
|
|
150
|
+
if (lowerType === 'text' || lowerType === 'search') {
|
|
151
|
+
return 'Test input';
|
|
152
|
+
}
|
|
153
|
+
// Hidden/submit/button/file — skip these intentionally
|
|
154
|
+
if (['hidden', 'submit', 'button', 'file', 'image', 'reset'].includes(lowerType)) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
// Fallback for any other fillable input type
|
|
158
|
+
return 'Test input';
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=test-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-data.js","sourceRoot":"","sources":["../../src/execution/test-data.ts"],"names":[],"mappings":"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"}
|