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.
Files changed (188) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +281 -0
  3. package/dist/ai/gemini-client.d.ts +21 -0
  4. package/dist/ai/gemini-client.js +105 -0
  5. package/dist/ai/gemini-client.js.map +1 -0
  6. package/dist/ai/index.d.ts +1 -0
  7. package/dist/ai/index.js +3 -0
  8. package/dist/ai/index.js.map +1 -0
  9. package/dist/analysis/diagnosis-schema.d.ts +106 -0
  10. package/dist/analysis/diagnosis-schema.js +54 -0
  11. package/dist/analysis/diagnosis-schema.js.map +1 -0
  12. package/dist/analysis/error-analyzer.d.ts +9 -0
  13. package/dist/analysis/error-analyzer.js +573 -0
  14. package/dist/analysis/error-analyzer.js.map +1 -0
  15. package/dist/analysis/index.d.ts +4 -0
  16. package/dist/analysis/index.js +6 -0
  17. package/dist/analysis/index.js.map +1 -0
  18. package/dist/analysis/source-mapper.d.ts +19 -0
  19. package/dist/analysis/source-mapper.js +329 -0
  20. package/dist/analysis/source-mapper.js.map +1 -0
  21. package/dist/analysis/ui-auditor.d.ts +9 -0
  22. package/dist/analysis/ui-auditor.js +104 -0
  23. package/dist/analysis/ui-auditor.js.map +1 -0
  24. package/dist/artifacts/artifact-storage.d.ts +44 -0
  25. package/dist/artifacts/artifact-storage.js +99 -0
  26. package/dist/artifacts/artifact-storage.js.map +1 -0
  27. package/dist/artifacts/index.d.ts +1 -0
  28. package/dist/artifacts/index.js +3 -0
  29. package/dist/artifacts/index.js.map +1 -0
  30. package/dist/browser/browser-manager.d.ts +45 -0
  31. package/dist/browser/browser-manager.js +88 -0
  32. package/dist/browser/browser-manager.js.map +1 -0
  33. package/dist/browser/challenge-detector.d.ts +10 -0
  34. package/dist/browser/challenge-detector.js +58 -0
  35. package/dist/browser/challenge-detector.js.map +1 -0
  36. package/dist/browser/cookie-dismisser.d.ts +18 -0
  37. package/dist/browser/cookie-dismisser.js +76 -0
  38. package/dist/browser/cookie-dismisser.js.map +1 -0
  39. package/dist/browser/index.d.ts +4 -0
  40. package/dist/browser/index.js +6 -0
  41. package/dist/browser/index.js.map +1 -0
  42. package/dist/browser/stealth-browser.d.ts +13 -0
  43. package/dist/browser/stealth-browser.js +59 -0
  44. package/dist/browser/stealth-browser.js.map +1 -0
  45. package/dist/cli/commander-cli.d.ts +2 -0
  46. package/dist/cli/commander-cli.js +150 -0
  47. package/dist/cli/commander-cli.js.map +1 -0
  48. package/dist/cli/doctor.d.ts +34 -0
  49. package/dist/cli/doctor.js +124 -0
  50. package/dist/cli/doctor.js.map +1 -0
  51. package/dist/cli/first-run.d.ts +6 -0
  52. package/dist/cli/first-run.js +58 -0
  53. package/dist/cli/first-run.js.map +1 -0
  54. package/dist/cli/index.d.ts +3 -0
  55. package/dist/cli/index.js +5 -0
  56. package/dist/cli/index.js.map +1 -0
  57. package/dist/cli/progress.d.ts +11 -0
  58. package/dist/cli/progress.js +30 -0
  59. package/dist/cli/progress.js.map +1 -0
  60. package/dist/core/engine.d.ts +33 -0
  61. package/dist/core/engine.js +269 -0
  62. package/dist/core/engine.js.map +1 -0
  63. package/dist/core/index.d.ts +3 -0
  64. package/dist/core/index.js +4 -0
  65. package/dist/core/index.js.map +1 -0
  66. package/dist/core/validation.d.ts +52 -0
  67. package/dist/core/validation.js +228 -0
  68. package/dist/core/validation.js.map +1 -0
  69. package/dist/discovery/crawler.d.ts +58 -0
  70. package/dist/discovery/crawler.js +240 -0
  71. package/dist/discovery/crawler.js.map +1 -0
  72. package/dist/discovery/discovery-pipeline.d.ts +22 -0
  73. package/dist/discovery/discovery-pipeline.js +256 -0
  74. package/dist/discovery/discovery-pipeline.js.map +1 -0
  75. package/dist/discovery/element-mapper.d.ts +21 -0
  76. package/dist/discovery/element-mapper.js +422 -0
  77. package/dist/discovery/element-mapper.js.map +1 -0
  78. package/dist/discovery/index.d.ts +8 -0
  79. package/dist/discovery/index.js +8 -0
  80. package/dist/discovery/index.js.map +1 -0
  81. package/dist/discovery/link-validator.d.ts +15 -0
  82. package/dist/discovery/link-validator.js +137 -0
  83. package/dist/discovery/link-validator.js.map +1 -0
  84. package/dist/discovery/sitemap-builder.d.ts +19 -0
  85. package/dist/discovery/sitemap-builder.js +166 -0
  86. package/dist/discovery/sitemap-builder.js.map +1 -0
  87. package/dist/discovery/spa-detector.d.ts +12 -0
  88. package/dist/discovery/spa-detector.js +271 -0
  89. package/dist/discovery/spa-detector.js.map +1 -0
  90. package/dist/execution/error-detector.d.ts +10 -0
  91. package/dist/execution/error-detector.js +87 -0
  92. package/dist/execution/error-detector.js.map +1 -0
  93. package/dist/execution/evidence-capture.d.ts +8 -0
  94. package/dist/execution/evidence-capture.js +37 -0
  95. package/dist/execution/evidence-capture.js.map +1 -0
  96. package/dist/execution/index.d.ts +5 -0
  97. package/dist/execution/index.js +7 -0
  98. package/dist/execution/index.js.map +1 -0
  99. package/dist/execution/step-handlers.d.ts +48 -0
  100. package/dist/execution/step-handlers.js +349 -0
  101. package/dist/execution/step-handlers.js.map +1 -0
  102. package/dist/execution/test-data.d.ts +50 -0
  103. package/dist/execution/test-data.js +160 -0
  104. package/dist/execution/test-data.js.map +1 -0
  105. package/dist/execution/workflow-executor.d.ts +56 -0
  106. package/dist/execution/workflow-executor.js +331 -0
  107. package/dist/execution/workflow-executor.js.map +1 -0
  108. package/dist/index.d.ts +2 -0
  109. package/dist/index.js +5 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/mcp/entry.d.ts +2 -0
  112. package/dist/mcp/entry.js +5 -0
  113. package/dist/mcp/entry.js.map +1 -0
  114. package/dist/mcp/index.d.ts +2 -0
  115. package/dist/mcp/index.js +4 -0
  116. package/dist/mcp/index.js.map +1 -0
  117. package/dist/mcp/server.d.ts +3 -0
  118. package/dist/mcp/server.js +19 -0
  119. package/dist/mcp/server.js.map +1 -0
  120. package/dist/mcp/tools.d.ts +2 -0
  121. package/dist/mcp/tools.js +162 -0
  122. package/dist/mcp/tools.js.map +1 -0
  123. package/dist/planning/heuristic-planner.d.ts +7 -0
  124. package/dist/planning/heuristic-planner.js +238 -0
  125. package/dist/planning/heuristic-planner.js.map +1 -0
  126. package/dist/planning/index.d.ts +3 -0
  127. package/dist/planning/index.js +5 -0
  128. package/dist/planning/index.js.map +1 -0
  129. package/dist/planning/plan-schema.d.ts +74 -0
  130. package/dist/planning/plan-schema.js +39 -0
  131. package/dist/planning/plan-schema.js.map +1 -0
  132. package/dist/planning/workflow-planner.d.ts +39 -0
  133. package/dist/planning/workflow-planner.js +211 -0
  134. package/dist/planning/workflow-planner.js.map +1 -0
  135. package/dist/reports/health-scorer.d.ts +14 -0
  136. package/dist/reports/health-scorer.js +88 -0
  137. package/dist/reports/health-scorer.js.map +1 -0
  138. package/dist/reports/html-generator.d.ts +10 -0
  139. package/dist/reports/html-generator.js +155 -0
  140. package/dist/reports/html-generator.js.map +1 -0
  141. package/dist/reports/index.d.ts +4 -0
  142. package/dist/reports/index.js +6 -0
  143. package/dist/reports/index.js.map +1 -0
  144. package/dist/reports/markdown-generator.d.ts +10 -0
  145. package/dist/reports/markdown-generator.js +334 -0
  146. package/dist/reports/markdown-generator.js.map +1 -0
  147. package/dist/reports/priority-ranker.d.ts +22 -0
  148. package/dist/reports/priority-ranker.js +608 -0
  149. package/dist/reports/priority-ranker.js.map +1 -0
  150. package/dist/screenshots/dual-format.d.ts +14 -0
  151. package/dist/screenshots/dual-format.js +59 -0
  152. package/dist/screenshots/dual-format.js.map +1 -0
  153. package/dist/screenshots/index.d.ts +2 -0
  154. package/dist/screenshots/index.js +4 -0
  155. package/dist/screenshots/index.js.map +1 -0
  156. package/dist/screenshots/screenshot-manager.d.ts +33 -0
  157. package/dist/screenshots/screenshot-manager.js +86 -0
  158. package/dist/screenshots/screenshot-manager.js.map +1 -0
  159. package/dist/testing/accessibility-auditor.d.ts +23 -0
  160. package/dist/testing/accessibility-auditor.js +44 -0
  161. package/dist/testing/accessibility-auditor.js.map +1 -0
  162. package/dist/testing/index.d.ts +4 -0
  163. package/dist/testing/index.js +5 -0
  164. package/dist/testing/index.js.map +1 -0
  165. package/dist/testing/meta-auditor.d.ts +16 -0
  166. package/dist/testing/meta-auditor.js +268 -0
  167. package/dist/testing/meta-auditor.js.map +1 -0
  168. package/dist/testing/performance-monitor.d.ts +15 -0
  169. package/dist/testing/performance-monitor.js +64 -0
  170. package/dist/testing/performance-monitor.js.map +1 -0
  171. package/dist/types/artifacts.d.ts +58 -0
  172. package/dist/types/artifacts.js +3 -0
  173. package/dist/types/artifacts.js.map +1 -0
  174. package/dist/types/discovery.d.ts +124 -0
  175. package/dist/types/discovery.js +3 -0
  176. package/dist/types/discovery.js.map +1 -0
  177. package/dist/types/execution.d.ts +154 -0
  178. package/dist/types/execution.js +3 -0
  179. package/dist/types/execution.js.map +1 -0
  180. package/dist/types/index.d.ts +2 -0
  181. package/dist/types/index.js +4 -0
  182. package/dist/types/index.js.map +1 -0
  183. package/dist/utils/sanitizer.d.ts +25 -0
  184. package/dist/utils/sanitizer.js +98 -0
  185. package/dist/utils/sanitizer.js.map +1 -0
  186. package/package.json +86 -0
  187. package/templates/report.hbs +202 -0
  188. 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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"}