playwright-mimic 0.1.0 → 0.1.2
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/README.md +695 -446
- package/dist/agentic/agent.d.ts +106 -0
- package/dist/agentic/agent.d.ts.map +1 -0
- package/dist/agentic/agent.js +528 -0
- package/dist/agentic/agent.js.map +1 -0
- package/dist/agentic/index.d.ts +13 -0
- package/dist/agentic/index.d.ts.map +1 -0
- package/dist/agentic/index.js +12 -0
- package/dist/agentic/index.js.map +1 -0
- package/dist/agentic/planner.d.ts +41 -0
- package/dist/agentic/planner.d.ts.map +1 -0
- package/dist/agentic/planner.js +136 -0
- package/dist/agentic/planner.js.map +1 -0
- package/dist/agentic/react.d.ts +35 -0
- package/dist/agentic/react.d.ts.map +1 -0
- package/dist/agentic/react.js +170 -0
- package/dist/agentic/react.js.map +1 -0
- package/dist/agentic/recovery.d.ts +55 -0
- package/dist/agentic/recovery.d.ts.map +1 -0
- package/dist/agentic/recovery.js +200 -0
- package/dist/agentic/recovery.js.map +1 -0
- package/dist/agentic/reflection.d.ts +40 -0
- package/dist/agentic/reflection.d.ts.map +1 -0
- package/dist/agentic/reflection.js +142 -0
- package/dist/agentic/reflection.js.map +1 -0
- package/dist/agentic/types.d.ts +177 -0
- package/dist/agentic/types.d.ts.map +1 -0
- package/dist/agentic/types.js +8 -0
- package/dist/agentic/types.js.map +1 -0
- package/dist/agentic/wait.d.ts +50 -0
- package/dist/agentic/wait.d.ts.map +1 -0
- package/dist/agentic/wait.js +140 -0
- package/dist/agentic/wait.js.map +1 -0
- package/dist/agentic-mimic.d.ts +56 -0
- package/dist/agentic-mimic.d.ts.map +1 -0
- package/dist/agentic-mimic.js +98 -0
- package/dist/agentic-mimic.js.map +1 -0
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/mimic/actionType.d.ts +7 -0
- package/dist/mimic/actionType.d.ts.map +1 -0
- package/dist/mimic/actionType.js +44 -0
- package/dist/mimic/actionType.js.map +1 -0
- package/dist/mimic/annotations.d.ts +21 -0
- package/dist/mimic/annotations.d.ts.map +1 -0
- package/dist/mimic/annotations.js +36 -0
- package/dist/mimic/annotations.js.map +1 -0
- package/dist/mimic/cli.d.ts +15 -0
- package/dist/mimic/cli.d.ts.map +1 -0
- package/dist/mimic/cli.js +17 -0
- package/dist/mimic/cli.js.map +1 -0
- package/dist/mimic/click.d.ts +39 -0
- package/dist/mimic/click.d.ts.map +1 -0
- package/dist/mimic/click.js +348 -0
- package/dist/mimic/click.js.map +1 -0
- package/dist/mimic/forms.d.ts +52 -0
- package/dist/mimic/forms.d.ts.map +1 -0
- package/dist/mimic/forms.js +511 -0
- package/dist/mimic/forms.js.map +1 -0
- package/dist/mimic/markers.d.ts +133 -0
- package/dist/mimic/markers.d.ts.map +1 -0
- package/dist/mimic/markers.js +589 -0
- package/dist/mimic/markers.js.map +1 -0
- package/dist/mimic/navigation.d.ts +19 -0
- package/dist/mimic/navigation.d.ts.map +1 -0
- package/dist/mimic/navigation.js +136 -0
- package/dist/mimic/navigation.js.map +1 -0
- package/dist/mimic/playwrightCodeGenerator.d.ts +55 -0
- package/dist/mimic/playwrightCodeGenerator.d.ts.map +1 -0
- package/dist/mimic/playwrightCodeGenerator.js +270 -0
- package/dist/mimic/playwrightCodeGenerator.js.map +1 -0
- package/dist/mimic/replay.d.ts +21 -0
- package/dist/mimic/replay.d.ts.map +1 -0
- package/dist/mimic/replay.js +142 -0
- package/dist/mimic/replay.js.map +1 -0
- package/dist/mimic/schema/action.d.ts +315 -0
- package/dist/mimic/schema/action.d.ts.map +1 -0
- package/dist/mimic/schema/action.js +186 -0
- package/dist/mimic/schema/action.js.map +1 -0
- package/dist/mimic/selector.d.ts +143 -0
- package/dist/mimic/selector.d.ts.map +1 -0
- package/dist/mimic/selector.js +1515 -0
- package/dist/mimic/selector.js.map +1 -0
- package/dist/mimic/selectorDescriptor.d.ts +25 -0
- package/dist/mimic/selectorDescriptor.d.ts.map +1 -0
- package/dist/mimic/selectorDescriptor.js +32 -0
- package/dist/mimic/selectorDescriptor.js.map +1 -0
- package/dist/mimic/selectorSerialization.d.ts +18 -0
- package/dist/mimic/selectorSerialization.d.ts.map +1 -0
- package/dist/mimic/selectorSerialization.js +32 -0
- package/dist/mimic/selectorSerialization.js.map +1 -0
- package/dist/mimic/selectorTypes.d.ts +122 -0
- package/dist/mimic/selectorTypes.d.ts.map +1 -0
- package/dist/mimic/selectorTypes.js +2 -0
- package/dist/mimic/selectorTypes.js.map +1 -0
- package/dist/mimic/selectorUtils.d.ts +52 -0
- package/dist/mimic/selectorUtils.d.ts.map +1 -0
- package/dist/mimic/selectorUtils.js +251 -0
- package/dist/mimic/selectorUtils.js.map +1 -0
- package/dist/mimic/storage.d.ts +110 -0
- package/dist/mimic/storage.d.ts.map +1 -0
- package/dist/mimic/storage.js +409 -0
- package/dist/mimic/storage.js.map +1 -0
- package/dist/mimic/types.d.ts +85 -0
- package/dist/mimic/types.d.ts.map +1 -0
- package/dist/mimic/types.js +7 -0
- package/dist/mimic/types.js.map +1 -0
- package/dist/mimic.d.ts +29 -4
- package/dist/mimic.d.ts.map +1 -1
- package/dist/mimic.js +530 -32
- package/dist/mimic.js.map +1 -1
- package/dist/mimicry.d.ts +4 -4
- package/dist/mimicry.d.ts.map +1 -1
- package/dist/mimicry.js +22 -13
- package/dist/mimicry.js.map +1 -1
- package/package.json +30 -6
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import { generateText, Output } from 'ai';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
import { countTokens } from '../utils/token-counter';
|
|
4
|
+
import { generateBestSelectorForElement } from './selector';
|
|
5
|
+
import { addAnnotation } from './annotations.js';
|
|
6
|
+
import { selectorToPlaywrightCode, generateFormCode } from './playwrightCodeGenerator.js';
|
|
7
|
+
import { captureScreenshot, generateAriaSnapshot } from './markers.js';
|
|
8
|
+
const zFormActionResult = z.object({
|
|
9
|
+
/**
|
|
10
|
+
* The mimic ID (marker number) of the target form element
|
|
11
|
+
* This is the number shown on the element's badge in the screenshot
|
|
12
|
+
*/
|
|
13
|
+
mimicId: z.number().int().min(1).describe("The mimic ID (marker number) shown on the form element's badge in the screenshot"),
|
|
14
|
+
type: z.enum(['keypress', 'type', 'fill', 'select', 'uncheck', 'check', 'click', 'setInputFiles', 'clear']),
|
|
15
|
+
params: z.object({
|
|
16
|
+
value: z.string().describe("Value to set for the form update."),
|
|
17
|
+
modifiers: z.array(z.enum(['Alt', 'Control', 'Meta', 'Shift', 'none'])).describe("Optional modifier keys to use for the form update."),
|
|
18
|
+
}),
|
|
19
|
+
/**
|
|
20
|
+
* Human-readable description of the target form element for test annotations
|
|
21
|
+
* Should clearly identify which form field is being interacted with (e.g., "Email input field", "Submit button", "Country dropdown")
|
|
22
|
+
*/
|
|
23
|
+
elementDescription: z.string().describe("Human-readable description of the target form element for test annotations"),
|
|
24
|
+
});
|
|
25
|
+
export const getFormAction = async (page, brain, gherkinStep, testContext) => {
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
// Capture screenshot with markers and positioning data
|
|
28
|
+
console.log('📸 [getFormAction] Starting screenshot capture with markers...');
|
|
29
|
+
const screenshotStart = Date.now();
|
|
30
|
+
const { image: screenshot, markers: markerData } = await captureScreenshot(page);
|
|
31
|
+
const screenshotTime = Date.now() - screenshotStart;
|
|
32
|
+
console.log(`📸 [getFormAction] Screenshot captured in ${screenshotTime}ms (${(screenshotTime / 1000).toFixed(2)}s)`);
|
|
33
|
+
const base64Start = Date.now();
|
|
34
|
+
const screenshotBase64 = screenshot.toString('base64');
|
|
35
|
+
const base64Time = Date.now() - base64Start;
|
|
36
|
+
console.log(`📸 [getFormAction] Screenshot converted to base64 in ${base64Time}ms (${(base64Time / 1000).toFixed(2)}s), size: ${(screenshotBase64.length / 1024).toFixed(2)}KB`);
|
|
37
|
+
// Generate accessibility snapshot to explain the screenshot structure
|
|
38
|
+
console.log('🔍 [getFormAction] Generating accessibility snapshot...');
|
|
39
|
+
const ariaSnapshotStart = Date.now();
|
|
40
|
+
const ariaSnapshot = await generateAriaSnapshot(page);
|
|
41
|
+
const ariaSnapshotTime = Date.now() - ariaSnapshotStart;
|
|
42
|
+
console.log(`🔍 [getFormAction] Accessibility snapshot generated in ${ariaSnapshotTime}ms (${(ariaSnapshotTime / 1000).toFixed(2)}s), length: ${ariaSnapshot.length} chars`);
|
|
43
|
+
// Convert marker data to format expected by prompt
|
|
44
|
+
const markerStart = Date.now();
|
|
45
|
+
// Defensive check: ensure markerData is an array before mapping
|
|
46
|
+
// This prevents "Cannot read properties of undefined (reading 'map')" errors
|
|
47
|
+
const markerInfo = (Array.isArray(markerData) ? markerData : []).map(m => {
|
|
48
|
+
return {
|
|
49
|
+
id: m.mimicId,
|
|
50
|
+
tag: m.tag,
|
|
51
|
+
text: m.text,
|
|
52
|
+
role: m.role,
|
|
53
|
+
ariaLabel: m.ariaLabel,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
const markerTime = Date.now() - markerStart;
|
|
57
|
+
console.log(`🔍 [getFormAction] Processed ${markerInfo.length} markers in ${markerTime}ms (${(markerTime / 1000).toFixed(2)}s)`);
|
|
58
|
+
// Filter to form elements only (inputs, textareas, selects, buttons)
|
|
59
|
+
const filterStart = Date.now();
|
|
60
|
+
const formMarkers = markerInfo.filter(m => m.tag === 'input' || m.tag === 'textarea' || m.tag === 'select' || m.tag === 'button');
|
|
61
|
+
const filterTime = Date.now() - filterStart;
|
|
62
|
+
console.log(`🔍 [getFormAction] Filtered to ${formMarkers.length} form elements in ${filterTime}ms`);
|
|
63
|
+
// Build marker summary for the prompt
|
|
64
|
+
const summaryStart = Date.now();
|
|
65
|
+
const markerSummary = formMarkers
|
|
66
|
+
.slice(0, 50) // Limit to first 50 markers to avoid prompt size issues
|
|
67
|
+
.map(m => ` Marker ${m.id}: ${m.tag}${m.role ? ` (role: ${m.role})` : ''}${m.text ? ` - "${m.text.substring(0, 50)}"` : ''}${m.ariaLabel ? ` [aria-label: "${m.ariaLabel}"]` : ''}`)
|
|
68
|
+
.join('\n');
|
|
69
|
+
const summaryTime = Date.now() - summaryStart;
|
|
70
|
+
console.log(`📝 [getFormAction] Built marker summary in ${summaryTime}ms`);
|
|
71
|
+
// Build context description for the prompt
|
|
72
|
+
const promptStart = Date.now();
|
|
73
|
+
// Build context description with defensive checks for optional testContext
|
|
74
|
+
// Ensure previousSteps exists and is an array before calling .map()
|
|
75
|
+
const contextDescription = testContext ? `
|
|
76
|
+
**Test Context:**
|
|
77
|
+
- Current URL: ${testContext.currentState.url}
|
|
78
|
+
- Current Page Title: ${testContext.currentState.pageTitle}
|
|
79
|
+
- Step ${testContext.currentStepIndex + 1} of ${testContext.totalSteps}
|
|
80
|
+
${testContext.previousSteps && Array.isArray(testContext.previousSteps) && testContext.previousSteps.length > 0 ? `
|
|
81
|
+
**Previous Steps Executed:**
|
|
82
|
+
${testContext.previousSteps.map((prevStep, idx) => `${idx + 1}. Step ${prevStep.stepIndex + 1}: "${prevStep.stepText}" (${prevStep.actionKind}${prevStep.url ? ` → ${prevStep.url}` : ''})`).join('\n')}
|
|
83
|
+
` : ''}
|
|
84
|
+
` : '';
|
|
85
|
+
const prompt = `You are an expert Playwright test engineer specializing in mapping Gherkin steps to form interactions using visual analysis.
|
|
86
|
+
|
|
87
|
+
Your task is to analyze:
|
|
88
|
+
1. A screenshot of the page with numbered marker badges on elements
|
|
89
|
+
2. An accessibility snapshot (provided below) that describes the page structure with roles, names, data-testid, and data-mimic-* attributes
|
|
90
|
+
3. A single Gherkin step that implies a form update action (typing, filling, selecting, checking, etc.)
|
|
91
|
+
|
|
92
|
+
**IMPORTANT**: Look at the screenshot to identify form elements by their marker numbers. Each element has a numbered badge:
|
|
93
|
+
- **RED badges** = Interactive elements (buttons, links, inputs, etc.)
|
|
94
|
+
- **BLUE badges** = Display-only content elements
|
|
95
|
+
- **GREEN badges** = Structure/test anchor elements
|
|
96
|
+
|
|
97
|
+
You must determine:
|
|
98
|
+
- The **mimicId** (marker number) of the target form element from the screenshot
|
|
99
|
+
- The type of form action (fill, type, select, check, uncheck, clear, etc.)
|
|
100
|
+
- The value to use (text to type, option to select, etc.)
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### IMPORTANT RULES
|
|
105
|
+
|
|
106
|
+
- **ALWAYS use the marker ID (mimicId)** from the screenshot - this is the number shown on the form element's badge
|
|
107
|
+
- Do NOT invent elements or marker IDs - only use marker IDs that are visible in the screenshot
|
|
108
|
+
- For typing text (email addresses, names, messages, etc.), ALWAYS use "fill" or "type", NEVER "keypress"
|
|
109
|
+
- For checkboxes, ALWAYS use "check" or "uncheck", NEVER "keypress" or "click"
|
|
110
|
+
- For radio buttons, ALWAYS use "click", NEVER "check" (radio buttons should be clicked, not checked)
|
|
111
|
+
- "keypress" is ONLY for single keyboard keys like "Enter", "Tab", "Escape", "ArrowUp", "ArrowDown", etc.
|
|
112
|
+
- If the step says "type X into Y" or "fill Y with X", use "fill" (preferred) or "type", NOT "keypress"
|
|
113
|
+
- If the step says "check" or "select" a checkbox, use "check", NOT "keypress" or "click"
|
|
114
|
+
- If the step says "select" or "click" a radio button, use "click", NOT "check"
|
|
115
|
+
- Provide a clear, human-readable description of the target element (e.g., "Email input field", "Name field labeled 'Full Name'", "Submit button", "Country dropdown")
|
|
116
|
+
- Consider the test context - what steps came before may help identify the correct element
|
|
117
|
+
|
|
118
|
+
${contextDescription}
|
|
119
|
+
**Gherkin Step:**
|
|
120
|
+
${gherkinStep}
|
|
121
|
+
|
|
122
|
+
**Available Form Elements (${formMarkers.length} total):**
|
|
123
|
+
${markerSummary}
|
|
124
|
+
${formMarkers.length > 50 ? `\n... and ${formMarkers.length - 50} more form elements` : ''}
|
|
125
|
+
|
|
126
|
+
**Accessibility Snapshot (explains the screenshot structure):**
|
|
127
|
+
The following accessibility snapshot describes the page structure with roles, accessible names, data-testid attributes, and data-mimic-* attributes. Use this to understand the page structure alongside the screenshot:
|
|
128
|
+
\`\`\`
|
|
129
|
+
${ariaSnapshot}
|
|
130
|
+
\`\`\`
|
|
131
|
+
|
|
132
|
+
**Action Types:**
|
|
133
|
+
- fill: Replace all content in a field with text (USE THIS for typing text like email addresses, names, etc.)
|
|
134
|
+
- type: Type text character by character (slower, simulates real typing - use when needed for special cases)
|
|
135
|
+
- select: Select an option from dropdown/select element
|
|
136
|
+
- check: Check a checkbox (USE THIS when step says "check" or "select" a checkbox) - DO NOT use for radio buttons
|
|
137
|
+
- uncheck: Uncheck a checkbox (USE THIS when step says "uncheck" or "deselect" a checkbox)
|
|
138
|
+
- click: Click on a radio button to select it (USE THIS for radio buttons, NOT "check")
|
|
139
|
+
- clear: Clear field content
|
|
140
|
+
- keypress: Press a SINGLE KEY ONLY (e.g., "Enter", "Tab", "Escape", "ArrowDown") - DO NOT use for typing text strings, checkboxes, or radio buttons
|
|
141
|
+
- setInputFiles: Upload a file
|
|
142
|
+
|
|
143
|
+
## Analyze the screenshot and determine:
|
|
144
|
+
1. Which form element (by mimicId/marker number) is being targeted
|
|
145
|
+
2. What action type to perform
|
|
146
|
+
3. What value to use
|
|
147
|
+
4. A clear description of the target element
|
|
148
|
+
|
|
149
|
+
Use the marker ID numbers (mimicId) shown on the badges in the screenshot and referenced in the accessibility snapshot to identify the form element.`;
|
|
150
|
+
const promptTime = Date.now() - promptStart;
|
|
151
|
+
console.log(`📝 [getFormAction] Built prompt in ${promptTime}ms, prompt length: ${prompt.length} chars`);
|
|
152
|
+
// Build message content - try without image first, then retry with image if needed
|
|
153
|
+
const messageStart = Date.now();
|
|
154
|
+
// First attempt: text-only (no image) - faster and cheaper
|
|
155
|
+
const messageContentTextOnly = [
|
|
156
|
+
{ type: 'text', text: prompt }
|
|
157
|
+
];
|
|
158
|
+
// Second attempt: with image (if first attempt fails)
|
|
159
|
+
const messageContentWithImage = [
|
|
160
|
+
{ type: 'text', text: prompt },
|
|
161
|
+
{ type: 'image', image: screenshotBase64 }
|
|
162
|
+
];
|
|
163
|
+
const messageTime = Date.now() - messageStart;
|
|
164
|
+
console.log(`📨 [getFormAction] Built message content in ${messageTime}ms`);
|
|
165
|
+
// Set explicit timeout for AI calls to prevent indefinite hangs
|
|
166
|
+
// 2 minutes should be sufficient for most AI responses, even with retries
|
|
167
|
+
const aiTimeout = 120_000; // 2 minutes
|
|
168
|
+
let res;
|
|
169
|
+
let aiTime;
|
|
170
|
+
let usedImage = false;
|
|
171
|
+
// First attempt: try without image (text-only with accessibility snapshot)
|
|
172
|
+
console.log('🤖 [getFormAction] Calling AI model (text-only, no image)...');
|
|
173
|
+
const aiStart = Date.now();
|
|
174
|
+
try {
|
|
175
|
+
res = await Promise.race([
|
|
176
|
+
generateText({
|
|
177
|
+
model: brain,
|
|
178
|
+
messages: [
|
|
179
|
+
{
|
|
180
|
+
role: 'user',
|
|
181
|
+
content: messageContentTextOnly
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
maxRetries: 2, // Fewer retries for first attempt
|
|
185
|
+
output: Output.object({ schema: zFormActionResult, name: 'formActionResult' }),
|
|
186
|
+
}),
|
|
187
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`AI model call timed out after ${aiTimeout}ms`)), aiTimeout))
|
|
188
|
+
]);
|
|
189
|
+
// Validate the response
|
|
190
|
+
if (!res.output || !res.output.mimicId || typeof res.output.mimicId !== 'number') {
|
|
191
|
+
throw new Error('First attempt returned invalid result, retrying with image...');
|
|
192
|
+
}
|
|
193
|
+
aiTime = Date.now() - aiStart;
|
|
194
|
+
console.log(`✅ [getFormAction] AI model responded successfully (text-only) in ${aiTime}ms (${(aiTime / 1000).toFixed(2)}s)`);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
// First attempt failed - retry with image
|
|
198
|
+
console.log(`⚠️ [getFormAction] First attempt failed, retrying with image: ${error instanceof Error ? error.message : String(error)}`);
|
|
199
|
+
const retryStart = Date.now();
|
|
200
|
+
usedImage = true;
|
|
201
|
+
try {
|
|
202
|
+
res = await Promise.race([
|
|
203
|
+
generateText({
|
|
204
|
+
model: brain,
|
|
205
|
+
messages: [
|
|
206
|
+
{
|
|
207
|
+
role: 'user',
|
|
208
|
+
content: messageContentWithImage
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
maxRetries: 3,
|
|
212
|
+
output: Output.object({ schema: zFormActionResult, name: 'formActionResult' }),
|
|
213
|
+
}),
|
|
214
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`AI model call timed out after ${aiTimeout}ms`)), aiTimeout))
|
|
215
|
+
]);
|
|
216
|
+
aiTime = Date.now() - retryStart;
|
|
217
|
+
console.log(`✅ [getFormAction] AI model responded successfully (with image) in ${aiTime}ms (${(aiTime / 1000).toFixed(2)}s)`);
|
|
218
|
+
}
|
|
219
|
+
catch (retryError) {
|
|
220
|
+
const elapsed = Date.now() - aiStart;
|
|
221
|
+
throw new Error(`AI model call failed after ${elapsed}ms (tried both text-only and with image): ${retryError instanceof Error ? retryError.message : String(retryError)}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
await countTokens(res);
|
|
225
|
+
const totalTime = Date.now() - startTime;
|
|
226
|
+
console.log(`⏱️ [getFormAction] Total time: ${totalTime}ms (${(totalTime / 1000).toFixed(2)}s)${usedImage ? ' (used image on retry)' : ' (text-only, no image needed)'}`);
|
|
227
|
+
console.log(` Breakdown: screenshot=${screenshotTime}ms, base64=${base64Time}ms, markers=${markerTime}ms, filter=${filterTime}ms, summary=${summaryTime}ms, prompt=${promptTime}ms, message=${messageTime}ms, AI=${aiTime}ms`);
|
|
228
|
+
// Validate that the AI model returned a valid structured output
|
|
229
|
+
// The output should always be defined when using structured outputs, but add defensive check
|
|
230
|
+
if (!res.output) {
|
|
231
|
+
throw new Error('AI model failed to generate valid form action result. The output is undefined.');
|
|
232
|
+
}
|
|
233
|
+
// Validate that mimicId exists and is valid
|
|
234
|
+
if (!res.output.mimicId || typeof res.output.mimicId !== 'number') {
|
|
235
|
+
throw new Error(`AI model returned invalid form action result: mimicId is missing or invalid. Received: ${JSON.stringify(res.output)}`);
|
|
236
|
+
}
|
|
237
|
+
return res.output;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Execute a form action on a page element with plain English annotation
|
|
241
|
+
*
|
|
242
|
+
* This function performs form interactions (typing, selecting, checking, etc.)
|
|
243
|
+
* and adds test annotations for better traceability and validation.
|
|
244
|
+
* Uses the LLM-generated element description from the form action result.
|
|
245
|
+
*
|
|
246
|
+
* @param page - Playwright Page object for keyboard actions
|
|
247
|
+
* @param formActionResult - Form action result containing action type, parameters, and element description
|
|
248
|
+
* @param targetElement - Playwright Locator for the target form element
|
|
249
|
+
* @param testInfo - Playwright TestInfo for adding annotations (optional)
|
|
250
|
+
* @param gherkinStep - The original Gherkin step for annotation type (optional)
|
|
251
|
+
* @returns Promise that resolves when the form action is complete
|
|
252
|
+
*/
|
|
253
|
+
export const executeFormAction = async (page, formActionResult, targetElement, testInfo, gherkinStep) => {
|
|
254
|
+
if (targetElement === null) {
|
|
255
|
+
throw new Error('No target element found');
|
|
256
|
+
}
|
|
257
|
+
// Use LLM-generated description from the form action result
|
|
258
|
+
const elementDescription = formActionResult.elementDescription || 'form field';
|
|
259
|
+
let annotationDescription = '';
|
|
260
|
+
// Generate Playwright code equivalent BEFORE performing the action
|
|
261
|
+
// This ensures the element is still available (before navigation/closure)
|
|
262
|
+
let playwrightCode;
|
|
263
|
+
let selector = null;
|
|
264
|
+
try {
|
|
265
|
+
// Generate the best selector descriptor from the element
|
|
266
|
+
// This gives us a descriptive, stable selector for snapshot storage
|
|
267
|
+
// Use 30-second timeout for selector generation
|
|
268
|
+
const selectorDescriptor = await generateBestSelectorForElement(targetElement, { timeout: 30000 });
|
|
269
|
+
const selectorCode = selectorToPlaywrightCode(selectorDescriptor);
|
|
270
|
+
playwrightCode = generateFormCode(selectorCode, formActionResult.type, formActionResult.params.value);
|
|
271
|
+
// Store the selector descriptor for snapshot storage
|
|
272
|
+
selector = selectorDescriptor;
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
// If generating from element fails, fall back to mimicId if available
|
|
276
|
+
// This can happen if the element is not available or page is closing
|
|
277
|
+
const errorMessage = error?.message || String(error);
|
|
278
|
+
// Check if page closed - this is a common issue with form submissions
|
|
279
|
+
if (errorMessage.includes('closed') || errorMessage.includes('Target page')) {
|
|
280
|
+
console.warn('Page closed during selector generation, using mimicId fallback');
|
|
281
|
+
}
|
|
282
|
+
if (formActionResult.mimicId) {
|
|
283
|
+
const selectorCode = `page.locator('[data-mimic-id="${formActionResult.mimicId}"]')`;
|
|
284
|
+
playwrightCode = generateFormCode(selectorCode, formActionResult.type, formActionResult.params.value);
|
|
285
|
+
// Create a CSS selector descriptor as fallback
|
|
286
|
+
selector = {
|
|
287
|
+
type: 'css',
|
|
288
|
+
selector: `[data-mimic-id="${formActionResult.mimicId}"]`
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
// If we can't generate the code and no mimicId, log the error
|
|
293
|
+
console.warn('Could not generate Playwright code for form action:', errorMessage);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Perform the form action with appropriate plain English annotation
|
|
297
|
+
switch (formActionResult.type) {
|
|
298
|
+
case 'keypress':
|
|
299
|
+
// Validate that keypress is only used for single keys, not text strings
|
|
300
|
+
const keyValue = formActionResult.params.value;
|
|
301
|
+
const validSingleKeys = ['Enter', 'Tab', 'Escape', 'Backspace', 'Delete', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'];
|
|
302
|
+
// Handle empty or invalid keypress values
|
|
303
|
+
if (!keyValue || keyValue.trim() === '') {
|
|
304
|
+
// If empty value and step mentions "check", convert to check action
|
|
305
|
+
const stepLower = (gherkinStep || '').toLowerCase();
|
|
306
|
+
if (stepLower.includes('check') || stepLower.includes('select')) {
|
|
307
|
+
console.warn(`⚠️ keypress action received empty value for checkbox operation - converting to check action`);
|
|
308
|
+
annotationDescription = `→ Checking ${elementDescription} to select the option`;
|
|
309
|
+
// Update Playwright code and selector for check action
|
|
310
|
+
// Regenerate selector to ensure we have the best one for this specific action
|
|
311
|
+
try {
|
|
312
|
+
const selectorDescriptor = await generateBestSelectorForElement(targetElement, { timeout: 30000 });
|
|
313
|
+
const selectorCode = selectorToPlaywrightCode(selectorDescriptor);
|
|
314
|
+
playwrightCode = generateFormCode(selectorCode, 'check');
|
|
315
|
+
// Store the updated selector descriptor
|
|
316
|
+
selector = selectorDescriptor;
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
// Fallback to mimicId if available
|
|
320
|
+
if (formActionResult.mimicId) {
|
|
321
|
+
const selectorCode = `page.locator('[data-mimic-id="${formActionResult.mimicId}"]')`;
|
|
322
|
+
playwrightCode = generateFormCode(selectorCode, 'check');
|
|
323
|
+
// Ensure selector is set even in fallback case
|
|
324
|
+
if (!selector) {
|
|
325
|
+
selector = {
|
|
326
|
+
type: 'css',
|
|
327
|
+
selector: `[data-mimic-id="${formActionResult.mimicId}"]`
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
console.debug('Could not generate Playwright code for check action:', error);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
336
|
+
await targetElement.check();
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
throw new Error(`keypress action requires a valid key value, but received empty string. Use 'check' for checkboxes, 'fill' for text input, etc.`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
else if (keyValue.length > 1 && !validSingleKeys.includes(keyValue)) {
|
|
343
|
+
// If it's not a valid single key and looks like text, use fill instead
|
|
344
|
+
console.warn(`⚠️ keypress action received text "${keyValue}" - converting to fill action`);
|
|
345
|
+
annotationDescription = `→ Filling ${elementDescription} with value "${keyValue}"`;
|
|
346
|
+
// Update Playwright code and selector for fill action
|
|
347
|
+
// Regenerate selector to ensure we have the best one for this specific action
|
|
348
|
+
try {
|
|
349
|
+
const selectorDescriptor = await generateBestSelectorForElement(targetElement, { timeout: 30000 });
|
|
350
|
+
const selectorCode = selectorToPlaywrightCode(selectorDescriptor);
|
|
351
|
+
playwrightCode = generateFormCode(selectorCode, 'fill', keyValue);
|
|
352
|
+
// Store the updated selector descriptor
|
|
353
|
+
selector = selectorDescriptor;
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
// Fallback to mimicId if available
|
|
357
|
+
if (formActionResult.mimicId) {
|
|
358
|
+
const selectorCode = `page.locator('[data-mimic-id="${formActionResult.mimicId}"]')`;
|
|
359
|
+
playwrightCode = generateFormCode(selectorCode, 'fill', keyValue);
|
|
360
|
+
// Ensure selector is set even in fallback case
|
|
361
|
+
if (!selector) {
|
|
362
|
+
selector = {
|
|
363
|
+
type: 'css',
|
|
364
|
+
selector: `[data-mimic-id="${formActionResult.mimicId}"]`
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
console.debug('Could not generate Playwright code for fill action:', error);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
373
|
+
await targetElement.fill(keyValue);
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
annotationDescription = `→ Pressing key "${keyValue}" on the keyboard`;
|
|
377
|
+
// For keypress action, ensure we have a selector stored even though we use page.keyboard
|
|
378
|
+
// This ensures we have a selector stored for snapshot/replay purposes
|
|
379
|
+
if (!selector) {
|
|
380
|
+
// If selector wasn't generated earlier, try to generate it now
|
|
381
|
+
try {
|
|
382
|
+
selector = await generateBestSelectorForElement(targetElement, { timeout: 30000 });
|
|
383
|
+
const selectorCode = selectorToPlaywrightCode(selector);
|
|
384
|
+
// Use the selector to focus the element before pressing key
|
|
385
|
+
playwrightCode = `${selectorCode}.focus();\nawait page.keyboard.press(${JSON.stringify(keyValue)});`;
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
// Fallback to mimicId if available
|
|
389
|
+
if (formActionResult.mimicId) {
|
|
390
|
+
const selectorCode = `page.locator('[data-mimic-id="${formActionResult.mimicId}"]')`;
|
|
391
|
+
playwrightCode = `${selectorCode}.focus();\nawait page.keyboard.press(${JSON.stringify(keyValue)});`;
|
|
392
|
+
selector = {
|
|
393
|
+
type: 'css',
|
|
394
|
+
selector: `[data-mimic-id="${formActionResult.mimicId}"]`
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
// Last resort: use generic keyboard press without selector
|
|
399
|
+
playwrightCode = `await page.keyboard.press(${JSON.stringify(keyValue)});`;
|
|
400
|
+
console.warn('Could not generate selector for keypress action, using generic keyboard press');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
// Use the already-generated selector
|
|
406
|
+
const selectorCode = selectorToPlaywrightCode(selector);
|
|
407
|
+
playwrightCode = `${selectorCode}.focus();\nawait page.keyboard.press(${JSON.stringify(keyValue)});`;
|
|
408
|
+
}
|
|
409
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
410
|
+
// Focus the element first, then press the key
|
|
411
|
+
await targetElement.focus();
|
|
412
|
+
await page.keyboard.press(keyValue);
|
|
413
|
+
}
|
|
414
|
+
break;
|
|
415
|
+
case 'type':
|
|
416
|
+
annotationDescription = `→ Typing "${formActionResult.params.value}" using keyboard input`;
|
|
417
|
+
// For type action, we still want to use the generated selector for the target element
|
|
418
|
+
// even though the actual action uses page.keyboard.type
|
|
419
|
+
// This ensures we have a selector stored for snapshot/replay purposes
|
|
420
|
+
if (!selector) {
|
|
421
|
+
// If selector wasn't generated earlier, try to generate it now
|
|
422
|
+
try {
|
|
423
|
+
selector = await generateBestSelectorForElement(targetElement, { timeout: 30000 });
|
|
424
|
+
const selectorCode = selectorToPlaywrightCode(selector);
|
|
425
|
+
// Use the selector to focus the element before typing
|
|
426
|
+
playwrightCode = `${selectorCode}.focus();\nawait page.keyboard.type(${JSON.stringify(formActionResult.params.value)});`;
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
// Fallback to mimicId if available
|
|
430
|
+
if (formActionResult.mimicId) {
|
|
431
|
+
const selectorCode = `page.locator('[data-mimic-id="${formActionResult.mimicId}"]')`;
|
|
432
|
+
playwrightCode = `${selectorCode}.focus();\nawait page.keyboard.type(${JSON.stringify(formActionResult.params.value)});`;
|
|
433
|
+
selector = {
|
|
434
|
+
type: 'css',
|
|
435
|
+
selector: `[data-mimic-id="${formActionResult.mimicId}"]`
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
// Last resort: use generic keyboard type without selector
|
|
440
|
+
playwrightCode = `await page.keyboard.type(${JSON.stringify(formActionResult.params.value)});`;
|
|
441
|
+
console.warn('Could not generate selector for type action, using generic keyboard type');
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
// Use the already-generated selector
|
|
447
|
+
const selectorCode = selectorToPlaywrightCode(selector);
|
|
448
|
+
playwrightCode = `${selectorCode}.focus();\nawait page.keyboard.type(${JSON.stringify(formActionResult.params.value)});`;
|
|
449
|
+
}
|
|
450
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
451
|
+
// Focus the element first, then type
|
|
452
|
+
await targetElement.focus();
|
|
453
|
+
await page.keyboard.type(formActionResult.params.value);
|
|
454
|
+
break;
|
|
455
|
+
case 'fill':
|
|
456
|
+
annotationDescription = `→ Filling ${elementDescription} with value "${formActionResult.params.value}"`;
|
|
457
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
458
|
+
await targetElement.fill(formActionResult.params.value);
|
|
459
|
+
break;
|
|
460
|
+
case 'select':
|
|
461
|
+
annotationDescription = `→ Selecting option "${formActionResult.params.value}" from ${elementDescription}`;
|
|
462
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
463
|
+
await targetElement.selectOption(formActionResult.params.value);
|
|
464
|
+
break;
|
|
465
|
+
case 'uncheck':
|
|
466
|
+
annotationDescription = `→ Unchecking ${elementDescription} to deselect the option`;
|
|
467
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
468
|
+
await targetElement.uncheck();
|
|
469
|
+
break;
|
|
470
|
+
case 'check':
|
|
471
|
+
annotationDescription = `→ Checking ${elementDescription} to select the option`;
|
|
472
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
473
|
+
await targetElement.check();
|
|
474
|
+
break;
|
|
475
|
+
case 'click':
|
|
476
|
+
annotationDescription = `→ Clicking on ${elementDescription} to select the radio button`;
|
|
477
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
478
|
+
await targetElement.click();
|
|
479
|
+
break;
|
|
480
|
+
case 'setInputFiles':
|
|
481
|
+
annotationDescription = `→ Uploading file "${formActionResult.params.value}" to ${elementDescription}`;
|
|
482
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
483
|
+
await targetElement.setInputFiles(formActionResult.params.value);
|
|
484
|
+
break;
|
|
485
|
+
case 'clear':
|
|
486
|
+
annotationDescription = `→ Clearing the contents of ${elementDescription}`;
|
|
487
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
488
|
+
await targetElement.clear();
|
|
489
|
+
break;
|
|
490
|
+
default:
|
|
491
|
+
throw new Error(`Unknown form action type: ${formActionResult.type}`);
|
|
492
|
+
}
|
|
493
|
+
// Ensure selector is always set before returning
|
|
494
|
+
// This is critical for snapshot storage and replay functionality
|
|
495
|
+
if (!selector) {
|
|
496
|
+
// Last resort: use mimicId as fallback selector
|
|
497
|
+
if (formActionResult.mimicId) {
|
|
498
|
+
selector = {
|
|
499
|
+
type: 'css',
|
|
500
|
+
selector: `[data-mimic-id="${formActionResult.mimicId}"]`
|
|
501
|
+
};
|
|
502
|
+
console.warn(`⚠️ Using mimicId fallback selector for form action: ${formActionResult.type}`);
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
throw new Error(`Could not generate or determine selector for form action: ${formActionResult.type}. This is required for snapshot storage.`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
// Return action result and selector for snapshot storage
|
|
509
|
+
return { actionResult: formActionResult, selector };
|
|
510
|
+
};
|
|
511
|
+
//# sourceMappingURL=forms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forms.js","sourceRoot":"","sources":["../../src/mimic/forms.ts"],"names":[],"mappings":"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"}
|