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 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SitemapNode, WorkflowPlan } from '../types/discovery.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates workflow plans from sitemap data using heuristics instead of AI.
|
|
4
|
+
* Produces the same WorkflowPlan[] format that Gemini returns, so downstream
|
|
5
|
+
* pipeline stages (executor, analyzer, reporter) work unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateHeuristicPlans(sitemap: SitemapNode): WorkflowPlan[];
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// Generates basic workflow plans from discovered page elements without AI (fallback when GEMINI_API_KEY is not set)
|
|
2
|
+
/** Maximum number of workflows to generate (keeps runtime manageable) */
|
|
3
|
+
const MAX_WORKFLOWS = 8;
|
|
4
|
+
/**
|
|
5
|
+
* Generates workflow plans from sitemap data using heuristics instead of AI.
|
|
6
|
+
* Produces the same WorkflowPlan[] format that Gemini returns, so downstream
|
|
7
|
+
* pipeline stages (executor, analyzer, reporter) work unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export function generateHeuristicPlans(sitemap) {
|
|
10
|
+
const pages = collectAllPages(sitemap);
|
|
11
|
+
const plans = [];
|
|
12
|
+
// 1. Form workflows — highest value (signup, login, contact, search)
|
|
13
|
+
for (const page of pages) {
|
|
14
|
+
for (const form of page.pageData.forms) {
|
|
15
|
+
if (plans.length >= MAX_WORKFLOWS)
|
|
16
|
+
break;
|
|
17
|
+
const plan = buildFormWorkflow(page, form);
|
|
18
|
+
if (plan)
|
|
19
|
+
plans.push(plan);
|
|
20
|
+
}
|
|
21
|
+
if (plans.length >= MAX_WORKFLOWS)
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
// 2. CTA / prominent button workflows
|
|
25
|
+
for (const page of pages) {
|
|
26
|
+
const ctaButtons = page.pageData.buttons
|
|
27
|
+
.filter(b => b.visible && b.text.trim().length > 0)
|
|
28
|
+
.slice(0, 3); // top 3 visible buttons per page
|
|
29
|
+
for (const button of ctaButtons) {
|
|
30
|
+
if (plans.length >= MAX_WORKFLOWS)
|
|
31
|
+
break;
|
|
32
|
+
const plan = buildButtonWorkflow(page, button);
|
|
33
|
+
if (plan)
|
|
34
|
+
plans.push(plan);
|
|
35
|
+
}
|
|
36
|
+
if (plans.length >= MAX_WORKFLOWS)
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
// 3. Navigation workflows — verify key internal links load without errors
|
|
40
|
+
const navPlan = buildNavigationWorkflow(pages);
|
|
41
|
+
if (navPlan && plans.length < MAX_WORKFLOWS) {
|
|
42
|
+
plans.push(navPlan);
|
|
43
|
+
}
|
|
44
|
+
// Sort: critical first, then important, then nice-to-have
|
|
45
|
+
const priorityOrder = { critical: 0, important: 1, 'nice-to-have': 2 };
|
|
46
|
+
plans.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
|
|
47
|
+
return plans;
|
|
48
|
+
}
|
|
49
|
+
// ─── Workflow builders ───────────────────────────────────────────────
|
|
50
|
+
function buildFormWorkflow(page, form) {
|
|
51
|
+
if (form.fields.length === 0)
|
|
52
|
+
return null;
|
|
53
|
+
const steps = [];
|
|
54
|
+
// Step 1: Navigate to the page containing the form
|
|
55
|
+
steps.push({
|
|
56
|
+
action: 'navigate',
|
|
57
|
+
selector: page.url,
|
|
58
|
+
value: undefined,
|
|
59
|
+
expectedResult: `Page "${page.pageData.title}" loads successfully`,
|
|
60
|
+
confidence: 1.0,
|
|
61
|
+
});
|
|
62
|
+
// Step 2-N: Fill each field with synthetic test data
|
|
63
|
+
for (const field of form.fields) {
|
|
64
|
+
const testValue = syntheticValue(field.type, field.name, field.label);
|
|
65
|
+
const label = field.label || field.name || field.type;
|
|
66
|
+
steps.push({
|
|
67
|
+
action: 'fill',
|
|
68
|
+
selector: fieldSelector(form, field),
|
|
69
|
+
value: testValue,
|
|
70
|
+
expectedResult: `Field "${label}" accepts input`,
|
|
71
|
+
confidence: 0.7,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// Final step: Submit (click submit button or the form's submit element)
|
|
75
|
+
steps.push({
|
|
76
|
+
action: 'click',
|
|
77
|
+
selector: `${form.selector} [type="submit"], ${form.selector} button:last-of-type`,
|
|
78
|
+
value: undefined,
|
|
79
|
+
expectedResult: 'Form submits without errors',
|
|
80
|
+
confidence: 0.6,
|
|
81
|
+
});
|
|
82
|
+
// Add an expect step to verify no console errors
|
|
83
|
+
steps.push({
|
|
84
|
+
action: 'expect',
|
|
85
|
+
selector: 'body',
|
|
86
|
+
value: undefined,
|
|
87
|
+
expectedResult: 'Page does not show error messages after submission',
|
|
88
|
+
confidence: 0.7,
|
|
89
|
+
});
|
|
90
|
+
const formName = classifyForm(form);
|
|
91
|
+
const priority = formName.includes('login') || formName.includes('signup') || formName.includes('search')
|
|
92
|
+
? 'critical'
|
|
93
|
+
: 'important';
|
|
94
|
+
return {
|
|
95
|
+
workflowName: `${capitalize(formName)} Form Submission`,
|
|
96
|
+
description: `Fill and submit the ${formName} form on ${page.pageData.title} to verify it works without errors`,
|
|
97
|
+
steps,
|
|
98
|
+
priority,
|
|
99
|
+
estimatedDuration: 10 + form.fields.length * 2,
|
|
100
|
+
source: 'auto-discovered',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function buildButtonWorkflow(page, button) {
|
|
104
|
+
const text = button.text.trim();
|
|
105
|
+
if (!text)
|
|
106
|
+
return null;
|
|
107
|
+
const steps = [
|
|
108
|
+
{
|
|
109
|
+
action: 'navigate',
|
|
110
|
+
selector: page.url,
|
|
111
|
+
value: undefined,
|
|
112
|
+
expectedResult: `Page "${page.pageData.title}" loads successfully`,
|
|
113
|
+
confidence: 1.0,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
action: 'click',
|
|
117
|
+
selector: button.selector,
|
|
118
|
+
value: undefined,
|
|
119
|
+
expectedResult: `Button "${text}" responds to click without errors`,
|
|
120
|
+
confidence: 0.7,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
action: 'expect',
|
|
124
|
+
selector: 'body',
|
|
125
|
+
value: undefined,
|
|
126
|
+
expectedResult: 'Page does not show error state after button click',
|
|
127
|
+
confidence: 0.7,
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
return {
|
|
131
|
+
workflowName: `Click "${text}" Button`,
|
|
132
|
+
description: `Click the "${text}" button on ${page.pageData.title} and verify no errors occur`,
|
|
133
|
+
steps,
|
|
134
|
+
priority: 'nice-to-have',
|
|
135
|
+
estimatedDuration: 8,
|
|
136
|
+
source: 'auto-discovered',
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function buildNavigationWorkflow(pages) {
|
|
140
|
+
// Pick up to 5 unique internal pages (prefer shallow depth)
|
|
141
|
+
const navTargets = pages
|
|
142
|
+
.filter(p => p.depth <= 2)
|
|
143
|
+
.slice(0, 5);
|
|
144
|
+
if (navTargets.length === 0)
|
|
145
|
+
return null;
|
|
146
|
+
const steps = navTargets.map(page => ({
|
|
147
|
+
action: 'navigate',
|
|
148
|
+
selector: page.url,
|
|
149
|
+
value: undefined,
|
|
150
|
+
expectedResult: `"${page.pageData.title}" loads without errors`,
|
|
151
|
+
confidence: 1.0,
|
|
152
|
+
}));
|
|
153
|
+
return {
|
|
154
|
+
workflowName: 'Core Page Navigation',
|
|
155
|
+
description: `Navigate to ${navTargets.length} key pages and verify they load without errors`,
|
|
156
|
+
steps,
|
|
157
|
+
priority: 'important',
|
|
158
|
+
estimatedDuration: navTargets.length * 5,
|
|
159
|
+
source: 'auto-discovered',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// ─── Helpers ─────────────────────────────────────────────────────────
|
|
163
|
+
/** Recursively collect all pages from sitemap tree, sorted by importance */
|
|
164
|
+
function collectAllPages(node) {
|
|
165
|
+
const pages = [node];
|
|
166
|
+
for (const child of node.children) {
|
|
167
|
+
pages.push(...collectAllPages(child));
|
|
168
|
+
}
|
|
169
|
+
// Sort: pages with forms first, then by number of interactive elements, then by depth
|
|
170
|
+
pages.sort((a, b) => {
|
|
171
|
+
const aScore = a.pageData.forms.length * 10 + a.pageData.buttons.length * 2;
|
|
172
|
+
const bScore = b.pageData.forms.length * 10 + b.pageData.buttons.length * 2;
|
|
173
|
+
if (aScore !== bScore)
|
|
174
|
+
return bScore - aScore;
|
|
175
|
+
return a.depth - b.depth;
|
|
176
|
+
});
|
|
177
|
+
return pages;
|
|
178
|
+
}
|
|
179
|
+
/** Build a Playwright selector for a form field */
|
|
180
|
+
function fieldSelector(form, field) {
|
|
181
|
+
if (field.label) {
|
|
182
|
+
return `${form.selector} [aria-label="${field.label}"], ${form.selector} input[name="${field.name}"]`;
|
|
183
|
+
}
|
|
184
|
+
if (field.name) {
|
|
185
|
+
return `${form.selector} [name="${field.name}"]`;
|
|
186
|
+
}
|
|
187
|
+
return `${form.selector} input[type="${field.type}"]`;
|
|
188
|
+
}
|
|
189
|
+
/** Generate synthetic test data based on field type */
|
|
190
|
+
function syntheticValue(type, name, label) {
|
|
191
|
+
const hint = `${type} ${name} ${label}`.toLowerCase();
|
|
192
|
+
if (hint.includes('email'))
|
|
193
|
+
return 'test@example.com';
|
|
194
|
+
if (hint.includes('password') || hint.includes('pass'))
|
|
195
|
+
return 'TestPass123!';
|
|
196
|
+
if (hint.includes('phone') || hint.includes('tel'))
|
|
197
|
+
return '555-0100';
|
|
198
|
+
if (hint.includes('url') || hint.includes('website'))
|
|
199
|
+
return 'https://example.com';
|
|
200
|
+
if (hint.includes('zip') || hint.includes('postal'))
|
|
201
|
+
return '90210';
|
|
202
|
+
if (hint.includes('name') && hint.includes('first'))
|
|
203
|
+
return 'Test';
|
|
204
|
+
if (hint.includes('name') && hint.includes('last'))
|
|
205
|
+
return 'User';
|
|
206
|
+
if (hint.includes('name'))
|
|
207
|
+
return 'Test User';
|
|
208
|
+
if (hint.includes('search') || hint.includes('query') || hint.includes('q'))
|
|
209
|
+
return 'test search query';
|
|
210
|
+
if (hint.includes('message') || hint.includes('comment') || hint.includes('textarea'))
|
|
211
|
+
return 'This is a test message from Afterburn.';
|
|
212
|
+
if (type === 'number')
|
|
213
|
+
return '42';
|
|
214
|
+
if (type === 'date')
|
|
215
|
+
return '2025-01-15';
|
|
216
|
+
return 'test input';
|
|
217
|
+
}
|
|
218
|
+
/** Classify a form by its fields and action */
|
|
219
|
+
function classifyForm(form) {
|
|
220
|
+
const fieldHints = form.fields.map(f => `${f.type} ${f.name} ${f.label}`.toLowerCase()).join(' ');
|
|
221
|
+
const action = (form.action || '').toLowerCase();
|
|
222
|
+
if (fieldHints.includes('password') && fieldHints.includes('email')) {
|
|
223
|
+
return fieldHints.includes('confirm') || fieldHints.includes('register') ? 'signup' : 'login';
|
|
224
|
+
}
|
|
225
|
+
if (action.includes('search') || fieldHints.includes('search') || fieldHints.includes('query'))
|
|
226
|
+
return 'search';
|
|
227
|
+
if (action.includes('contact') || fieldHints.includes('message') || fieldHints.includes('subject'))
|
|
228
|
+
return 'contact';
|
|
229
|
+
if (action.includes('subscribe') || fieldHints.includes('newsletter'))
|
|
230
|
+
return 'subscribe';
|
|
231
|
+
if (fieldHints.includes('password'))
|
|
232
|
+
return 'login';
|
|
233
|
+
return 'general';
|
|
234
|
+
}
|
|
235
|
+
function capitalize(s) {
|
|
236
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=heuristic-planner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristic-planner.js","sourceRoot":"","sources":["../../src/planning/heuristic-planner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/planning/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AAEjC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Single step in a workflow plan
|
|
4
|
+
*/
|
|
5
|
+
export declare const WorkflowStepSchema: z.ZodObject<{
|
|
6
|
+
action: z.ZodEnum<{
|
|
7
|
+
select: "select";
|
|
8
|
+
navigate: "navigate";
|
|
9
|
+
click: "click";
|
|
10
|
+
fill: "fill";
|
|
11
|
+
wait: "wait";
|
|
12
|
+
expect: "expect";
|
|
13
|
+
}>;
|
|
14
|
+
selector: z.ZodString;
|
|
15
|
+
value: z.ZodOptional<z.ZodString>;
|
|
16
|
+
expectedResult: z.ZodString;
|
|
17
|
+
confidence: z.ZodNumber;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
/**
|
|
20
|
+
* Complete AI-generated workflow test plan
|
|
21
|
+
*/
|
|
22
|
+
export declare const WorkflowPlanSchema: z.ZodObject<{
|
|
23
|
+
workflowName: z.ZodString;
|
|
24
|
+
description: z.ZodString;
|
|
25
|
+
steps: z.ZodArray<z.ZodObject<{
|
|
26
|
+
action: z.ZodEnum<{
|
|
27
|
+
select: "select";
|
|
28
|
+
navigate: "navigate";
|
|
29
|
+
click: "click";
|
|
30
|
+
fill: "fill";
|
|
31
|
+
wait: "wait";
|
|
32
|
+
expect: "expect";
|
|
33
|
+
}>;
|
|
34
|
+
selector: z.ZodString;
|
|
35
|
+
value: z.ZodOptional<z.ZodString>;
|
|
36
|
+
expectedResult: z.ZodString;
|
|
37
|
+
confidence: z.ZodNumber;
|
|
38
|
+
}, z.core.$strip>>;
|
|
39
|
+
priority: z.ZodEnum<{
|
|
40
|
+
critical: "critical";
|
|
41
|
+
important: "important";
|
|
42
|
+
"nice-to-have": "nice-to-have";
|
|
43
|
+
}>;
|
|
44
|
+
estimatedDuration: z.ZodNumber;
|
|
45
|
+
}, z.core.$strip>;
|
|
46
|
+
/**
|
|
47
|
+
* Gemini structured output wrapper (array of workflows)
|
|
48
|
+
*/
|
|
49
|
+
export declare const WorkflowPlansResponseSchema: z.ZodObject<{
|
|
50
|
+
workflows: z.ZodArray<z.ZodObject<{
|
|
51
|
+
workflowName: z.ZodString;
|
|
52
|
+
description: z.ZodString;
|
|
53
|
+
steps: z.ZodArray<z.ZodObject<{
|
|
54
|
+
action: z.ZodEnum<{
|
|
55
|
+
select: "select";
|
|
56
|
+
navigate: "navigate";
|
|
57
|
+
click: "click";
|
|
58
|
+
fill: "fill";
|
|
59
|
+
wait: "wait";
|
|
60
|
+
expect: "expect";
|
|
61
|
+
}>;
|
|
62
|
+
selector: z.ZodString;
|
|
63
|
+
value: z.ZodOptional<z.ZodString>;
|
|
64
|
+
expectedResult: z.ZodString;
|
|
65
|
+
confidence: z.ZodNumber;
|
|
66
|
+
}, z.core.$strip>>;
|
|
67
|
+
priority: z.ZodEnum<{
|
|
68
|
+
critical: "critical";
|
|
69
|
+
important: "important";
|
|
70
|
+
"nice-to-have": "nice-to-have";
|
|
71
|
+
}>;
|
|
72
|
+
estimatedDuration: z.ZodNumber;
|
|
73
|
+
}, z.core.$strip>>;
|
|
74
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Zod schemas for AI-generated workflow plans (structured output validation)
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Single step in a workflow plan
|
|
5
|
+
*/
|
|
6
|
+
export const WorkflowStepSchema = z.object({
|
|
7
|
+
action: z.enum(['navigate', 'click', 'fill', 'select', 'wait', 'expect'])
|
|
8
|
+
.describe('Action to perform'),
|
|
9
|
+
selector: z.string()
|
|
10
|
+
.describe('Playwright selector for the target element (role=, label=, text=, or CSS)'),
|
|
11
|
+
value: z.string().optional()
|
|
12
|
+
.describe('Value to fill or select'),
|
|
13
|
+
expectedResult: z.string()
|
|
14
|
+
.describe('What should happen after this step'),
|
|
15
|
+
confidence: z.number().min(0).max(1)
|
|
16
|
+
.describe('How confident are you this step will work (0-1)'),
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Complete AI-generated workflow test plan
|
|
20
|
+
*/
|
|
21
|
+
export const WorkflowPlanSchema = z.object({
|
|
22
|
+
workflowName: z.string()
|
|
23
|
+
.describe('Human-readable name like "User Signup Flow"'),
|
|
24
|
+
description: z.string()
|
|
25
|
+
.describe('What this workflow tests in plain English'),
|
|
26
|
+
steps: z.array(WorkflowStepSchema).min(1).max(20)
|
|
27
|
+
.describe('Step-by-step test actions'),
|
|
28
|
+
priority: z.enum(['critical', 'important', 'nice-to-have'])
|
|
29
|
+
.describe('Importance level'),
|
|
30
|
+
estimatedDuration: z.number()
|
|
31
|
+
.describe('Estimated seconds to execute'),
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Gemini structured output wrapper (array of workflows)
|
|
35
|
+
*/
|
|
36
|
+
export const WorkflowPlansResponseSchema = z.object({
|
|
37
|
+
workflows: z.array(WorkflowPlanSchema),
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=plan-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-schema.js","sourceRoot":"","sources":["../../src/planning/plan-schema.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;SACtE,QAAQ,CAAC,mBAAmB,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;SACjB,QAAQ,CAAC,2EAA2E,CAAC;IACxF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SACzB,QAAQ,CAAC,yBAAyB,CAAC;IACtC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;SACvB,QAAQ,CAAC,oCAAoC,CAAC;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SACjC,QAAQ,CAAC,iDAAiD,CAAC;CAC/D,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;SACrB,QAAQ,CAAC,6CAA6C,CAAC;IAC1D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;SACpB,QAAQ,CAAC,2CAA2C,CAAC;IACxD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;SAC9C,QAAQ,CAAC,2BAA2B,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;SACxD,QAAQ,CAAC,kBAAkB,CAAC;IAC/B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;SAC1B,QAAQ,CAAC,8BAA8B,CAAC;CAC5C,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;CACvC,CAAC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { GeminiClient } from '../ai/index.js';
|
|
2
|
+
import type { SitemapNode, WorkflowPlan } from '../types/discovery.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generates realistic user workflow test plans from sitemap using Gemini AI.
|
|
5
|
+
* Plans include step-by-step actions with Playwright selectors and confidence scores.
|
|
6
|
+
*/
|
|
7
|
+
export declare class WorkflowPlanner {
|
|
8
|
+
private gemini;
|
|
9
|
+
constructor(geminiClient: GeminiClient);
|
|
10
|
+
/**
|
|
11
|
+
* Generate workflow test plans from sitemap structure
|
|
12
|
+
* @param sitemap Hierarchical sitemap tree from Phase 2 discovery
|
|
13
|
+
* @param userHints Optional user-specified workflows to prioritize (from --flows flag)
|
|
14
|
+
* @returns Array of workflow plans sorted by priority
|
|
15
|
+
*/
|
|
16
|
+
generatePlans(sitemap: SitemapNode, userHints?: string[]): Promise<WorkflowPlan[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Create condensed text summary of sitemap for LLM prompt
|
|
19
|
+
* Truncates at maxChars to stay within token limits
|
|
20
|
+
*/
|
|
21
|
+
private summarizeSitemap;
|
|
22
|
+
/**
|
|
23
|
+
* Recursively collect all pages from sitemap tree
|
|
24
|
+
*/
|
|
25
|
+
private collectPages;
|
|
26
|
+
/**
|
|
27
|
+
* Score page importance for prioritization
|
|
28
|
+
* Higher score = more likely to contain important workflows
|
|
29
|
+
*/
|
|
30
|
+
private getPageImportance;
|
|
31
|
+
/**
|
|
32
|
+
* Format a single page as text summary
|
|
33
|
+
*/
|
|
34
|
+
private formatPageSummary;
|
|
35
|
+
/**
|
|
36
|
+
* Format form as concise description
|
|
37
|
+
*/
|
|
38
|
+
private formatForm;
|
|
39
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
// AI-powered workflow plan generator from sitemap data
|
|
2
|
+
import { WorkflowPlansResponseSchema } from './plan-schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generates realistic user workflow test plans from sitemap using Gemini AI.
|
|
5
|
+
* Plans include step-by-step actions with Playwright selectors and confidence scores.
|
|
6
|
+
*/
|
|
7
|
+
export class WorkflowPlanner {
|
|
8
|
+
gemini;
|
|
9
|
+
constructor(geminiClient) {
|
|
10
|
+
this.gemini = geminiClient;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generate workflow test plans from sitemap structure
|
|
14
|
+
* @param sitemap Hierarchical sitemap tree from Phase 2 discovery
|
|
15
|
+
* @param userHints Optional user-specified workflows to prioritize (from --flows flag)
|
|
16
|
+
* @returns Array of workflow plans sorted by priority
|
|
17
|
+
*/
|
|
18
|
+
async generatePlans(sitemap, userHints) {
|
|
19
|
+
try {
|
|
20
|
+
// Create condensed sitemap summary for LLM (token-efficient)
|
|
21
|
+
const sitemapSummary = this.summarizeSitemap(sitemap, { maxChars: 40000 });
|
|
22
|
+
// Build prompt with sitemap and user hints
|
|
23
|
+
let prompt = `You are analyzing a website to identify realistic user workflows that should be tested.
|
|
24
|
+
|
|
25
|
+
SITE STRUCTURE:
|
|
26
|
+
${sitemapSummary}
|
|
27
|
+
`;
|
|
28
|
+
if (userHints && userHints.length > 0) {
|
|
29
|
+
prompt += `
|
|
30
|
+
USER-SPECIFIED WORKFLOWS TO PRIORITIZE:
|
|
31
|
+
${userHints.map(hint => `- ${hint}`).join('\n')}
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
prompt += `
|
|
35
|
+
Generate workflow test plans for this website. For each workflow:
|
|
36
|
+
|
|
37
|
+
1. Identify a realistic user journey (signup, login, checkout, search, contact form, navigation, etc.)
|
|
38
|
+
2. Create step-by-step plan using Playwright selectors
|
|
39
|
+
3. Use selector syntax that works directly with page.click/fill/select/isVisible:
|
|
40
|
+
- Preferred: role=button[name="Sign Up"], role=textbox[name="Email"]
|
|
41
|
+
- Also valid: label=Email, text=Sign Up, CSS selectors
|
|
42
|
+
- Do NOT use JS helper strings like getByRole(...) or getByLabel(...)
|
|
43
|
+
4. Include expected result for each step (what the user should see after the action)
|
|
44
|
+
5. Assign confidence 0-1 for each step (1.0 = selector definitely exists, 0.5 = guessing)
|
|
45
|
+
6. Assign priority: critical (auth, core features), important (secondary features), nice-to-have (edge cases)
|
|
46
|
+
|
|
47
|
+
Focus on workflows that a real user would actually do. Skip admin/internal paths.
|
|
48
|
+
If user provided hints, those workflows are top priority.
|
|
49
|
+
|
|
50
|
+
Return JSON with a "workflows" array.`;
|
|
51
|
+
// Call Gemini with structured output
|
|
52
|
+
let response;
|
|
53
|
+
try {
|
|
54
|
+
response = await this.gemini.generateStructured(prompt, WorkflowPlansResponseSchema);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
// Retry once with simpler prompt if JSON parsing fails
|
|
58
|
+
console.warn('Gemini API call failed, retrying with simpler prompt:', error);
|
|
59
|
+
const simplerPrompt = `Analyze this website and generate 3-5 realistic user workflow test plans.
|
|
60
|
+
|
|
61
|
+
${sitemapSummary}
|
|
62
|
+
|
|
63
|
+
Return JSON with a "workflows" array where each workflow has: workflowName, description, steps (action, selector, value, expectedResult, confidence), priority, estimatedDuration.`;
|
|
64
|
+
response = await this.gemini.generateStructured(simplerPrompt, WorkflowPlansResponseSchema);
|
|
65
|
+
}
|
|
66
|
+
// Post-process workflows
|
|
67
|
+
const workflows = response.workflows
|
|
68
|
+
.map(workflow => {
|
|
69
|
+
// Filter out very low-confidence steps (likely hallucinated)
|
|
70
|
+
const filteredSteps = workflow.steps.filter(step => step.confidence >= 0.3);
|
|
71
|
+
// Flag workflows with low-confidence steps
|
|
72
|
+
const hasLowConfidence = filteredSteps.some(step => step.confidence < 0.7);
|
|
73
|
+
const description = hasLowConfidence
|
|
74
|
+
? `${workflow.description} [Low confidence - verify selectors]`
|
|
75
|
+
: workflow.description;
|
|
76
|
+
// Determine source
|
|
77
|
+
const isUserHint = userHints?.some(hint => workflow.workflowName.toLowerCase().includes(hint.toLowerCase()) ||
|
|
78
|
+
workflow.description.toLowerCase().includes(hint.toLowerCase())) ?? false;
|
|
79
|
+
return {
|
|
80
|
+
...workflow,
|
|
81
|
+
description,
|
|
82
|
+
steps: filteredSteps,
|
|
83
|
+
source: isUserHint ? 'user-hint' : 'auto-discovered',
|
|
84
|
+
};
|
|
85
|
+
})
|
|
86
|
+
// Remove workflows with no valid steps
|
|
87
|
+
.filter(workflow => workflow.steps.length > 0)
|
|
88
|
+
// Sort by priority
|
|
89
|
+
.sort((a, b) => {
|
|
90
|
+
const priorityOrder = { critical: 0, important: 1, 'nice-to-have': 2 };
|
|
91
|
+
const aPriority = priorityOrder[a.priority];
|
|
92
|
+
const bPriority = priorityOrder[b.priority];
|
|
93
|
+
// User hints first within same priority
|
|
94
|
+
if (aPriority === bPriority) {
|
|
95
|
+
if (a.source === 'user-hint' && b.source !== 'user-hint')
|
|
96
|
+
return -1;
|
|
97
|
+
if (a.source !== 'user-hint' && b.source === 'user-hint')
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
return aPriority - bPriority;
|
|
101
|
+
});
|
|
102
|
+
return workflows;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
// Graceful degradation: don't crash, return empty array
|
|
106
|
+
console.warn('Failed to generate workflow plans:', error);
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create condensed text summary of sitemap for LLM prompt
|
|
112
|
+
* Truncates at maxChars to stay within token limits
|
|
113
|
+
*/
|
|
114
|
+
summarizeSitemap(node, options) {
|
|
115
|
+
const maxChars = options?.maxChars ?? 40000;
|
|
116
|
+
let output = '';
|
|
117
|
+
let charCount = 0;
|
|
118
|
+
let pageCount = 0;
|
|
119
|
+
let truncated = false;
|
|
120
|
+
// Sort pages by importance: forms first, then interactive elements, then depth
|
|
121
|
+
const sortedPages = this.collectPages(node).sort((a, b) => {
|
|
122
|
+
const aScore = this.getPageImportance(a.pageData);
|
|
123
|
+
const bScore = this.getPageImportance(b.pageData);
|
|
124
|
+
if (aScore !== bScore)
|
|
125
|
+
return bScore - aScore; // Higher score first
|
|
126
|
+
return a.depth - b.depth; // Shallower first
|
|
127
|
+
});
|
|
128
|
+
// Add pages until we hit the char limit
|
|
129
|
+
for (const page of sortedPages) {
|
|
130
|
+
const pageSummary = this.formatPageSummary(page, page.depth);
|
|
131
|
+
if (charCount + pageSummary.length > maxChars) {
|
|
132
|
+
truncated = true;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
output += pageSummary;
|
|
136
|
+
charCount += pageSummary.length;
|
|
137
|
+
pageCount++;
|
|
138
|
+
}
|
|
139
|
+
// Add truncation notice if needed
|
|
140
|
+
if (truncated) {
|
|
141
|
+
const remaining = sortedPages.length - pageCount;
|
|
142
|
+
output += `\n... and ${remaining} more pages (truncated for brevity). Focus workflows on the pages shown above.\n`;
|
|
143
|
+
}
|
|
144
|
+
return output;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Recursively collect all pages from sitemap tree
|
|
148
|
+
*/
|
|
149
|
+
collectPages(node) {
|
|
150
|
+
const pages = [node];
|
|
151
|
+
for (const child of node.children) {
|
|
152
|
+
pages.push(...this.collectPages(child));
|
|
153
|
+
}
|
|
154
|
+
return pages;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Score page importance for prioritization
|
|
158
|
+
* Higher score = more likely to contain important workflows
|
|
159
|
+
*/
|
|
160
|
+
getPageImportance(pageData) {
|
|
161
|
+
let score = 0;
|
|
162
|
+
// Forms are high priority (auth, search, contact, etc.)
|
|
163
|
+
score += pageData.forms.length * 10;
|
|
164
|
+
// Buttons indicate interactions
|
|
165
|
+
score += pageData.buttons.length * 2;
|
|
166
|
+
// Menus and other interactive elements
|
|
167
|
+
score += pageData.menus.length * 3;
|
|
168
|
+
score += pageData.otherInteractive.length * 1;
|
|
169
|
+
// Links indicate navigation structure
|
|
170
|
+
score += Math.min(pageData.links.length, 20) * 0.5;
|
|
171
|
+
return score;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Format a single page as text summary
|
|
175
|
+
*/
|
|
176
|
+
formatPageSummary(node, depth) {
|
|
177
|
+
const indent = ' '.repeat(depth);
|
|
178
|
+
const { pageData } = node;
|
|
179
|
+
let summary = `${indent}Page: ${pageData.title} (${node.path})\n`;
|
|
180
|
+
// Forms
|
|
181
|
+
if (pageData.forms.length > 0) {
|
|
182
|
+
const formDescriptions = pageData.forms.map(form => this.formatForm(form));
|
|
183
|
+
summary += `${indent} Forms: ${formDescriptions.join('; ')}\n`;
|
|
184
|
+
}
|
|
185
|
+
// Buttons
|
|
186
|
+
if (pageData.buttons.length > 0) {
|
|
187
|
+
const visibleButtons = pageData.buttons.filter(b => b.visible).slice(0, 10); // Limit to avoid token bloat
|
|
188
|
+
const buttonTexts = visibleButtons.map(b => `"${b.text}"`).join(', ');
|
|
189
|
+
summary += `${indent} Buttons: ${buttonTexts}\n`;
|
|
190
|
+
}
|
|
191
|
+
// Menus
|
|
192
|
+
if (pageData.menus.length > 0) {
|
|
193
|
+
const menuTexts = pageData.menus.slice(0, 5).map(m => `"${m.text}"`).join(', ');
|
|
194
|
+
summary += `${indent} Menus: ${menuTexts}\n`;
|
|
195
|
+
}
|
|
196
|
+
// Link counts
|
|
197
|
+
const internalLinks = pageData.links.filter(l => l.isInternal).length;
|
|
198
|
+
const externalLinks = pageData.links.filter(l => !l.isInternal).length;
|
|
199
|
+
summary += `${indent} Links: ${internalLinks} internal, ${externalLinks} external\n`;
|
|
200
|
+
summary += '\n';
|
|
201
|
+
return summary;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Format form as concise description
|
|
205
|
+
*/
|
|
206
|
+
formatForm(form) {
|
|
207
|
+
const fieldNames = form.fields.map(f => f.name || f.label).filter(Boolean).slice(0, 8);
|
|
208
|
+
return `${form.method} form (${fieldNames.join(', ')})`;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=workflow-planner.js.map
|