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,348 @@
|
|
|
1
|
+
import { generateText, Output } from 'ai';
|
|
2
|
+
import { zClickActionResult } from './schema/action.js';
|
|
3
|
+
import { countTokens } from '../utils/token-counter.js';
|
|
4
|
+
import { addAnnotation } from './annotations.js';
|
|
5
|
+
import { generateBestSelectorForElement } from './selector.js';
|
|
6
|
+
import { selectorToPlaywrightCode, generateClickCode } from './playwrightCodeGenerator.js';
|
|
7
|
+
import { captureScreenshot, generateAriaSnapshot } from './markers.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get click action by matching Gherkin step against captured target elements
|
|
10
|
+
*
|
|
11
|
+
* This function uses AI to analyze a Gherkin step and match it against
|
|
12
|
+
* all available target elements on the page. It returns the top 5 most
|
|
13
|
+
* likely candidates along with the appropriate click type.
|
|
14
|
+
*
|
|
15
|
+
* @param page - Playwright Page object (currently unused but kept for consistency)
|
|
16
|
+
* @param brain - LanguageModel instance for AI analysis
|
|
17
|
+
* @param gherkinStep - The Gherkin step to match (e.g., "I click on the Submit button")
|
|
18
|
+
* @param targetElements - Array of captured elements with marker IDs from the page
|
|
19
|
+
* @param testContext - Optional test context with previous steps and current state
|
|
20
|
+
* @returns Promise resolving to ClickActionResult with top candidates and click type
|
|
21
|
+
*/
|
|
22
|
+
export const getClickAction = async (page, brain, gherkinStep, testContext) => {
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
// Capture screenshot with markers and positioning data
|
|
25
|
+
console.log('📸 [getClickAction] Starting screenshot capture with markers...');
|
|
26
|
+
const screenshotStart = Date.now();
|
|
27
|
+
const { image: screenshot, markers: markerData } = await captureScreenshot(page);
|
|
28
|
+
const screenshotTime = Date.now() - screenshotStart;
|
|
29
|
+
console.log(`📸 [getClickAction] Screenshot captured in ${screenshotTime}ms (${(screenshotTime / 1000).toFixed(2)}s)`);
|
|
30
|
+
const base64Start = Date.now();
|
|
31
|
+
const screenshotBase64 = screenshot.toString('base64');
|
|
32
|
+
const base64Time = Date.now() - base64Start;
|
|
33
|
+
console.log(`📸 [getClickAction] Screenshot converted to base64 in ${base64Time}ms (${(base64Time / 1000).toFixed(2)}s), size: ${(screenshotBase64.length / 1024).toFixed(2)}KB`);
|
|
34
|
+
// Generate accessibility snapshot to explain the screenshot structure
|
|
35
|
+
console.log('🔍 [getClickAction] Generating accessibility snapshot...');
|
|
36
|
+
const ariaSnapshotStart = Date.now();
|
|
37
|
+
const ariaSnapshot = await generateAriaSnapshot(page);
|
|
38
|
+
const ariaSnapshotTime = Date.now() - ariaSnapshotStart;
|
|
39
|
+
console.log(`🔍 [getClickAction] Accessibility snapshot generated in ${ariaSnapshotTime}ms (${(ariaSnapshotTime / 1000).toFixed(2)}s), length: ${ariaSnapshot.length} chars`);
|
|
40
|
+
// Convert marker data to format expected by prompt
|
|
41
|
+
const markerStart = Date.now();
|
|
42
|
+
const markerInfo = markerData?.map(m => {
|
|
43
|
+
return {
|
|
44
|
+
id: m.mimicId,
|
|
45
|
+
tag: m.tag,
|
|
46
|
+
text: m.text,
|
|
47
|
+
role: m.role,
|
|
48
|
+
ariaLabel: m.ariaLabel,
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
const markerTime = Date.now() - markerStart;
|
|
52
|
+
console.log(`🔍 [getClickAction] Processed ${markerInfo.length} markers in ${markerTime}ms (${(markerTime / 1000).toFixed(2)}s)`);
|
|
53
|
+
// Build marker summary for the prompt
|
|
54
|
+
const summaryStart = Date.now();
|
|
55
|
+
const markerSummary = markerInfo
|
|
56
|
+
.slice(0, 50) // Limit to first 50 markers to avoid prompt size issues
|
|
57
|
+
.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}"]` : ''}`)
|
|
58
|
+
.join('\n');
|
|
59
|
+
const summaryTime = Date.now() - summaryStart;
|
|
60
|
+
console.log(`📝 [getClickAction] Built marker summary in ${summaryTime}ms`);
|
|
61
|
+
// Build context description for the prompt
|
|
62
|
+
const promptStart = Date.now();
|
|
63
|
+
// Build context description with defensive checks for optional testContext
|
|
64
|
+
// Ensure previousSteps exists and is an array before calling .map()
|
|
65
|
+
const contextDescription = testContext ? `
|
|
66
|
+
**Test Context:**
|
|
67
|
+
- Current URL: ${testContext.currentState.url}
|
|
68
|
+
- Current Page Title: ${testContext.currentState.pageTitle}
|
|
69
|
+
- Step ${testContext.currentStepIndex + 1} of ${testContext.totalSteps}
|
|
70
|
+
${testContext.previousSteps && Array.isArray(testContext.previousSteps) && testContext.previousSteps.length > 0 ? `
|
|
71
|
+
**Previous Steps Executed:**
|
|
72
|
+
${testContext.previousSteps.map((prevStep, idx) => `${idx + 1}. Step ${prevStep.stepIndex + 1}: "${prevStep.stepText}" (${prevStep.actionKind}${prevStep.url ? ` → ${prevStep.url}` : ''})`).join('\n')}
|
|
73
|
+
` : ''}
|
|
74
|
+
` : '';
|
|
75
|
+
const prompt = `You are an expert Playwright test engineer specializing in mapping Gherkin steps to concrete DOM interactions using visual analysis.
|
|
76
|
+
|
|
77
|
+
Your task is to analyze:
|
|
78
|
+
1. A screenshot of the page with numbered marker badges on elements
|
|
79
|
+
2. An accessibility snapshot (provided below) that describes the page structure with roles, names, data-testid, and data-mimic-* attributes
|
|
80
|
+
3. A single Gherkin step that implies a click action
|
|
81
|
+
|
|
82
|
+
**CRITICAL: Click Type Determination**
|
|
83
|
+
You must determine the correct click type from the Gherkin step. Use these rules:
|
|
84
|
+
|
|
85
|
+
**Click Type Equivalencies (these are the SAME):**
|
|
86
|
+
- "click", "left click", and "primary click" → use "primary"
|
|
87
|
+
- "right click" and "secondary click" → use "secondary"
|
|
88
|
+
- "middle click" and "tertiary click" → use "tertiary"
|
|
89
|
+
- "double click" or "double-click" → use "double"
|
|
90
|
+
|
|
91
|
+
**Default Behavior:**
|
|
92
|
+
- If the step just says "click" (without specifying left/right/middle/double), ALWAYS use "primary"
|
|
93
|
+
- "click" by itself means a standard left/primary click, NOT a hover
|
|
94
|
+
|
|
95
|
+
**Hover Rules (STRICT):**
|
|
96
|
+
- ONLY use "hover" when the Gherkin step EXPLICITLY mentions "hover", "hover over", or "move mouse over"
|
|
97
|
+
- NEVER use "hover" for a step that says "click" - these are DIFFERENT actions
|
|
98
|
+
- Hover is ONLY for revealing tooltips, dropdowns, or additional UI elements that appear on mouseover
|
|
99
|
+
- If the step says "click", it means click, NOT hover
|
|
100
|
+
|
|
101
|
+
**Modifier Keys:**
|
|
102
|
+
- Detect if modifier keys are mentioned: shift, control (ctrl), alt, meta (command)
|
|
103
|
+
- These are optional and should be included in the modifiers field if present
|
|
104
|
+
|
|
105
|
+
**IMPORTANT**: Look at the screenshot to identify elements by their marker numbers. Each element has a numbered badge:
|
|
106
|
+
- **RED badges** = Interactive elements (buttons, links, inputs, etc.)
|
|
107
|
+
- **BLUE badges** = Display-only content elements
|
|
108
|
+
- **GREEN badges** = Structure/test anchor elements
|
|
109
|
+
|
|
110
|
+
You must return the **top 5 most likely elements** that the Gherkin step is referring to, identified by their **marker ID numbers** (the numbers shown on the badges in the screenshot).
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### IMPORTANT RULES
|
|
115
|
+
|
|
116
|
+
- **ALWAYS use the marker ID (mimicId)** from the screenshot - this is the number shown on the element's badge
|
|
117
|
+
- Rank elements from **most likely (rank 1)** to **least likely (rank 5)**
|
|
118
|
+
- Prefer **semantic matches** first:
|
|
119
|
+
- Visible text (what you can read in the screenshot)
|
|
120
|
+
- Element position and visual appearance
|
|
121
|
+
- Accessible name (label, aria-label, role)
|
|
122
|
+
- Button / link intent
|
|
123
|
+
- Do NOT invent elements or marker IDs - only use marker IDs that are visible in the screenshot
|
|
124
|
+
- Do NOT include more than 5 results
|
|
125
|
+
- If fewer than 5 reasonable matches exist, return fewer
|
|
126
|
+
- Do NOT assume navigation or side effects — this task is only about **what element is clicked**
|
|
127
|
+
- For each candidate, provide:
|
|
128
|
+
- The **mimicId** (marker number from the screenshot badge)
|
|
129
|
+
- A **clear, human-readable description** that identifies the element (e.g., "Submit button", "Login link with text 'Sign in'")
|
|
130
|
+
- Element metadata (tag, text, role, etc.) based on what you can see in the screenshot and the marker information provided
|
|
131
|
+
- Consider the test context - what steps came before may help identify the correct element
|
|
132
|
+
|
|
133
|
+
${contextDescription}
|
|
134
|
+
**Gherkin Step:**
|
|
135
|
+
${gherkinStep}
|
|
136
|
+
|
|
137
|
+
**Available Markers (${markerInfo.length} total):**
|
|
138
|
+
${markerSummary}
|
|
139
|
+
${markerInfo.length > 50 ? `\n... and ${markerInfo.length - 50} more markers` : ''}
|
|
140
|
+
|
|
141
|
+
**Accessibility Snapshot (explains the screenshot structure):**
|
|
142
|
+
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:
|
|
143
|
+
\`\`\`
|
|
144
|
+
${ariaSnapshot}
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
## Analyze the screenshot and accessibility snapshot, then return up to the top 5 most likely elements that the Gherkin step is referring to.
|
|
148
|
+
Use the marker ID numbers (mimicId) shown on the badges in the screenshot and referenced in the accessibility snapshot to identify elements.
|
|
149
|
+
|
|
150
|
+
**Remember:**
|
|
151
|
+
- "click" = primary click (left click) - the default for any click action
|
|
152
|
+
- "hover" is ONLY for explicit hover instructions, NEVER for click steps
|
|
153
|
+
- When in doubt about click type, default to "primary"
|
|
154
|
+
`;
|
|
155
|
+
const promptTime = Date.now() - promptStart;
|
|
156
|
+
console.log(`📝 [getClickAction] Built prompt in ${promptTime}ms, prompt length: ${prompt.length} chars`);
|
|
157
|
+
// Build message content - try without image first, then retry with image if needed
|
|
158
|
+
const messageStart = Date.now();
|
|
159
|
+
// First attempt: text-only (no image) - faster and cheaper
|
|
160
|
+
const messageContentTextOnly = [
|
|
161
|
+
{ type: 'text', text: prompt }
|
|
162
|
+
];
|
|
163
|
+
// Second attempt: with image (if first attempt fails)
|
|
164
|
+
const messageContentWithImage = [
|
|
165
|
+
{ type: 'text', text: prompt },
|
|
166
|
+
{ type: 'image', image: screenshotBase64 }
|
|
167
|
+
];
|
|
168
|
+
const messageTime = Date.now() - messageStart;
|
|
169
|
+
console.log(`📨 [getClickAction] Built message content in ${messageTime}ms`);
|
|
170
|
+
// Set explicit timeout for AI calls to prevent indefinite hangs
|
|
171
|
+
// 2 minutes should be sufficient for most AI responses, even with retries
|
|
172
|
+
const aiTimeout = 120_000; // 2 minutes
|
|
173
|
+
let res;
|
|
174
|
+
let aiTime;
|
|
175
|
+
let usedImage = false;
|
|
176
|
+
// First attempt: try without image (text-only with accessibility snapshot)
|
|
177
|
+
console.log('🤖 [getClickAction] Calling AI model (text-only, no image)...');
|
|
178
|
+
const aiStart = Date.now();
|
|
179
|
+
try {
|
|
180
|
+
res = await Promise.race([
|
|
181
|
+
generateText({
|
|
182
|
+
model: brain,
|
|
183
|
+
messages: [
|
|
184
|
+
{
|
|
185
|
+
role: 'user',
|
|
186
|
+
content: messageContentTextOnly
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
maxRetries: 2, // Fewer retries for first attempt
|
|
190
|
+
output: Output.object({ schema: zClickActionResult, name: 'clickActionResult' }),
|
|
191
|
+
}),
|
|
192
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`AI model call timed out after ${aiTimeout}ms`)), aiTimeout))
|
|
193
|
+
]);
|
|
194
|
+
// Validate the response
|
|
195
|
+
if (!res.output || !res.output.candidates || !Array.isArray(res.output.candidates) || res.output.candidates.length === 0) {
|
|
196
|
+
throw new Error('First attempt returned invalid result, retrying with image...');
|
|
197
|
+
}
|
|
198
|
+
aiTime = Date.now() - aiStart;
|
|
199
|
+
console.log(`✅ [getClickAction] AI model responded successfully (text-only) in ${aiTime}ms (${(aiTime / 1000).toFixed(2)}s)`);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
// First attempt failed - retry with image
|
|
203
|
+
console.log(`⚠️ [getClickAction] First attempt failed, retrying with image: ${error instanceof Error ? error.message : String(error)}`);
|
|
204
|
+
const retryStart = Date.now();
|
|
205
|
+
usedImage = true;
|
|
206
|
+
try {
|
|
207
|
+
res = await Promise.race([
|
|
208
|
+
generateText({
|
|
209
|
+
model: brain,
|
|
210
|
+
messages: [
|
|
211
|
+
{
|
|
212
|
+
role: 'user',
|
|
213
|
+
content: messageContentWithImage
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
maxRetries: 3,
|
|
217
|
+
output: Output.object({ schema: zClickActionResult, name: 'clickActionResult' }),
|
|
218
|
+
}),
|
|
219
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`AI model call timed out after ${aiTimeout}ms`)), aiTimeout))
|
|
220
|
+
]);
|
|
221
|
+
aiTime = Date.now() - retryStart;
|
|
222
|
+
console.log(`✅ [getClickAction] AI model responded successfully (with image) in ${aiTime}ms (${(aiTime / 1000).toFixed(2)}s)`);
|
|
223
|
+
}
|
|
224
|
+
catch (retryError) {
|
|
225
|
+
const elapsed = Date.now() - aiStart;
|
|
226
|
+
throw new Error(`AI model call failed after ${elapsed}ms (tried both text-only and with image): ${retryError instanceof Error ? retryError.message : String(retryError)}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
await countTokens(res);
|
|
230
|
+
const totalTime = Date.now() - startTime;
|
|
231
|
+
console.log(`⏱️ [getClickAction] Total time: ${totalTime}ms (${(totalTime / 1000).toFixed(2)}s)${usedImage ? ' (used image on retry)' : ' (text-only, no image needed)'}`);
|
|
232
|
+
console.log(` Breakdown: screenshot=${screenshotTime}ms, base64=${base64Time}ms, markers=${markerTime}ms, summary=${summaryTime}ms, prompt=${promptTime}ms, message=${messageTime}ms, AI=${aiTime}ms`);
|
|
233
|
+
// Validate that the AI model returned a valid structured output
|
|
234
|
+
// The output should always be defined when using structured outputs, but add defensive check
|
|
235
|
+
if (!res.output) {
|
|
236
|
+
throw new Error('AI model failed to generate valid click action result. The output is undefined.');
|
|
237
|
+
}
|
|
238
|
+
// Validate that candidates array exists and is not empty
|
|
239
|
+
if (!res.output.candidates || !Array.isArray(res.output.candidates) || res.output.candidates.length === 0) {
|
|
240
|
+
throw new Error(`AI model returned invalid click action result: candidates array is missing, not an array, or empty. Received: ${JSON.stringify(res.output)}`);
|
|
241
|
+
}
|
|
242
|
+
return res.output;
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Execute a click action on a page element with plain English annotation
|
|
246
|
+
*
|
|
247
|
+
* This function performs the actual click interaction and logs what action
|
|
248
|
+
* is being performed in human-readable terms for better test traceability.
|
|
249
|
+
* Uses the LLM-generated description from the selected candidate.
|
|
250
|
+
*
|
|
251
|
+
* @param element - Playwright Locator for the target element to interact with
|
|
252
|
+
* @param clickActionResult - Click action result containing click type and target information
|
|
253
|
+
* @param selectedCandidate - The selected candidate element with LLM-generated description
|
|
254
|
+
* @param testInfo - Playwright TestInfo for adding annotations
|
|
255
|
+
* @param gherkinStep - The original Gherkin step for annotation type
|
|
256
|
+
* @returns Promise that resolves to an object containing the action result and selector (for snapshot storage)
|
|
257
|
+
*/
|
|
258
|
+
export const executeClickAction = async (element, clickActionResult, selectedCandidate, testInfo, gherkinStep) => {
|
|
259
|
+
// Use the LLM-generated description from the candidate
|
|
260
|
+
// This description was created by the AI when matching the element
|
|
261
|
+
const elementDescription = selectedCandidate.description || 'element';
|
|
262
|
+
// Check if element is valid before attempting click
|
|
263
|
+
if (!element) {
|
|
264
|
+
throw new Error(`Cannot click: element not found or page may be closed`);
|
|
265
|
+
}
|
|
266
|
+
// Build annotation description based on click type
|
|
267
|
+
let annotationDescription = '';
|
|
268
|
+
switch (clickActionResult.clickType) {
|
|
269
|
+
case 'primary':
|
|
270
|
+
annotationDescription = `→ Clicking on ${elementDescription} with left mouse button`;
|
|
271
|
+
break;
|
|
272
|
+
case 'secondary':
|
|
273
|
+
annotationDescription = `→ Right-clicking on ${elementDescription} to open context menu`;
|
|
274
|
+
break;
|
|
275
|
+
case 'double':
|
|
276
|
+
annotationDescription = `→ Double-clicking on ${elementDescription} to activate`;
|
|
277
|
+
break;
|
|
278
|
+
case 'tertiary':
|
|
279
|
+
annotationDescription = `→ Clicking on ${elementDescription} with middle mouse button`;
|
|
280
|
+
break;
|
|
281
|
+
case 'hover':
|
|
282
|
+
annotationDescription = `→ Hovering over ${elementDescription} to reveal additional options`;
|
|
283
|
+
break;
|
|
284
|
+
default:
|
|
285
|
+
throw new Error(`Unknown click type: ${clickActionResult.clickType}`);
|
|
286
|
+
}
|
|
287
|
+
// Generate Playwright code equivalent BEFORE performing the action
|
|
288
|
+
// This ensures the element is still available (before navigation/closure)
|
|
289
|
+
let playwrightCode;
|
|
290
|
+
let selector = null;
|
|
291
|
+
try {
|
|
292
|
+
// Generate the best selector descriptor from the element
|
|
293
|
+
// This gives us a descriptive, stable selector for snapshot storage
|
|
294
|
+
// Use 30-second timeout for selector generation
|
|
295
|
+
const selectorDescriptor = await generateBestSelectorForElement(element, { timeout: 30000 });
|
|
296
|
+
const selectorCode = selectorToPlaywrightCode(selectorDescriptor);
|
|
297
|
+
playwrightCode = generateClickCode(selectorCode, clickActionResult.clickType);
|
|
298
|
+
// Store the selector descriptor for snapshot storage
|
|
299
|
+
selector = selectorDescriptor;
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
// If generating from element fails, fall back to mimicId if available
|
|
303
|
+
// This can happen if the element is not available or page is closing
|
|
304
|
+
const errorMessage = error?.message || String(error);
|
|
305
|
+
// Check if page closed - this can happen with navigation after clicks
|
|
306
|
+
if (errorMessage.includes('closed') || errorMessage.includes('Target page')) {
|
|
307
|
+
console.warn('Page closed during selector generation, using mimicId fallback');
|
|
308
|
+
}
|
|
309
|
+
if (selectedCandidate.mimicId) {
|
|
310
|
+
const selectorCode = `page.locator('[data-mimic-id="${selectedCandidate.mimicId}"]')`;
|
|
311
|
+
playwrightCode = generateClickCode(selectorCode, clickActionResult.clickType);
|
|
312
|
+
// Create a CSS selector descriptor as fallback
|
|
313
|
+
selector = {
|
|
314
|
+
type: 'css',
|
|
315
|
+
selector: `[data-mimic-id="${selectedCandidate.mimicId}"]`
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
// If we can't generate the code, that's okay - just skip it
|
|
320
|
+
console.warn('Could not generate Playwright code for click action:', errorMessage);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// Add annotation using centralized utility (includes Playwright code if available)
|
|
324
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription, playwrightCode);
|
|
325
|
+
// Perform the click action
|
|
326
|
+
switch (clickActionResult.clickType) {
|
|
327
|
+
case 'primary':
|
|
328
|
+
await element.click();
|
|
329
|
+
break;
|
|
330
|
+
case 'secondary':
|
|
331
|
+
await element.click({ button: 'right' });
|
|
332
|
+
break;
|
|
333
|
+
case 'double':
|
|
334
|
+
await element.dblclick();
|
|
335
|
+
break;
|
|
336
|
+
case 'tertiary':
|
|
337
|
+
await element.click({ button: 'middle' });
|
|
338
|
+
break;
|
|
339
|
+
case 'hover':
|
|
340
|
+
await element.hover();
|
|
341
|
+
break;
|
|
342
|
+
default:
|
|
343
|
+
throw new Error(`Unknown click type: ${clickActionResult.clickType}`);
|
|
344
|
+
}
|
|
345
|
+
// Return action result and selector for snapshot storage
|
|
346
|
+
return { actionResult: clickActionResult, selector };
|
|
347
|
+
};
|
|
348
|
+
//# sourceMappingURL=click.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"click.js","sourceRoot":"","sources":["../../src/mimic/click.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Locator, Page, TestInfo } from '@playwright/test';
|
|
2
|
+
import { type LanguageModel } from 'ai';
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
import type { TestContext } from '../mimic.js';
|
|
5
|
+
import type { SelectorDescriptor } from './selectorTypes.js';
|
|
6
|
+
declare const zFormActionResult: z.ZodObject<{
|
|
7
|
+
mimicId: z.ZodNumber;
|
|
8
|
+
type: z.ZodEnum<{
|
|
9
|
+
click: "click";
|
|
10
|
+
type: "type";
|
|
11
|
+
fill: "fill";
|
|
12
|
+
select: "select";
|
|
13
|
+
uncheck: "uncheck";
|
|
14
|
+
check: "check";
|
|
15
|
+
setInputFiles: "setInputFiles";
|
|
16
|
+
clear: "clear";
|
|
17
|
+
keypress: "keypress";
|
|
18
|
+
}>;
|
|
19
|
+
params: z.ZodObject<{
|
|
20
|
+
value: z.ZodString;
|
|
21
|
+
modifiers: z.ZodArray<z.ZodEnum<{
|
|
22
|
+
Alt: "Alt";
|
|
23
|
+
Control: "Control";
|
|
24
|
+
Meta: "Meta";
|
|
25
|
+
Shift: "Shift";
|
|
26
|
+
none: "none";
|
|
27
|
+
}>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
elementDescription: z.ZodString;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
export type FormActionResult = z.infer<typeof zFormActionResult>;
|
|
32
|
+
export declare const getFormAction: (page: Page, brain: LanguageModel, gherkinStep: string, testContext?: TestContext) => Promise<FormActionResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Execute a form action on a page element with plain English annotation
|
|
35
|
+
*
|
|
36
|
+
* This function performs form interactions (typing, selecting, checking, etc.)
|
|
37
|
+
* and adds test annotations for better traceability and validation.
|
|
38
|
+
* Uses the LLM-generated element description from the form action result.
|
|
39
|
+
*
|
|
40
|
+
* @param page - Playwright Page object for keyboard actions
|
|
41
|
+
* @param formActionResult - Form action result containing action type, parameters, and element description
|
|
42
|
+
* @param targetElement - Playwright Locator for the target form element
|
|
43
|
+
* @param testInfo - Playwright TestInfo for adding annotations (optional)
|
|
44
|
+
* @param gherkinStep - The original Gherkin step for annotation type (optional)
|
|
45
|
+
* @returns Promise that resolves when the form action is complete
|
|
46
|
+
*/
|
|
47
|
+
export declare const executeFormAction: (page: Page, formActionResult: FormActionResult, targetElement: Locator | null, testInfo?: TestInfo, gherkinStep?: string) => Promise<{
|
|
48
|
+
actionResult: FormActionResult;
|
|
49
|
+
selector: SelectorDescriptor | null;
|
|
50
|
+
}>;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=forms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../../src/mimic/forms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,IAAI,CAAA;AAC7D,OAAO,CAAC,MAAM,KAAK,CAAC;AAIpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;iBAgBrB,CAAA;AAGF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,eAAO,MAAM,aAAa,GACxB,MAAM,IAAI,EACV,OAAO,aAAa,EACpB,aAAa,MAAM,EACnB,cAAc,WAAW,KACxB,OAAO,CAAC,gBAAgB,CAsP1B,CAAA;AAGD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,IAAI,EACV,kBAAkB,gBAAgB,EAClC,eAAe,OAAO,GAAG,IAAI,EAC7B,WAAW,QAAQ,EACnB,cAAc,MAAM,KACnB,OAAO,CAAC;IAAE,YAAY,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAA;CAAE,CAmQjF,CAAA"}
|