playwright-mimic 0.1.0 → 0.1.1
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 +633 -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 +11 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -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 +20 -0
- package/dist/mimic/annotations.d.ts.map +1 -0
- package/dist/mimic/annotations.js +30 -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 +233 -0
- package/dist/mimic/click.js.map +1 -0
- package/dist/mimic/forms.d.ts +47 -0
- package/dist/mimic/forms.d.ts.map +1 -0
- package/dist/mimic/forms.js +264 -0
- package/dist/mimic/forms.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 +117 -0
- package/dist/mimic/navigation.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 +133 -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 +204 -0
- package/dist/mimic/schema/action.js.map +1 -0
- package/dist/mimic/selector.d.ts +139 -0
- package/dist/mimic/selector.d.ts.map +1 -0
- package/dist/mimic/selector.js +1103 -0
- package/dist/mimic/selector.js.map +1 -0
- package/dist/mimic/selectorDescriptor.d.ts +13 -0
- package/dist/mimic/selectorDescriptor.d.ts.map +1 -0
- package/dist/mimic/selectorDescriptor.js +9 -0
- package/dist/mimic/selectorDescriptor.js.map +1 -0
- package/dist/mimic/selectorSerialization.d.ts +30 -0
- package/dist/mimic/selectorSerialization.d.ts.map +1 -0
- package/dist/mimic/selectorSerialization.js +170 -0
- package/dist/mimic/selectorSerialization.js.map +1 -0
- package/dist/mimic/selectorTypes.d.ts +200 -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 +26 -0
- package/dist/mimic/selectorUtils.d.ts.map +1 -0
- package/dist/mimic/selectorUtils.js +144 -0
- package/dist/mimic/selectorUtils.js.map +1 -0
- package/dist/mimic/storage.d.ts +75 -0
- package/dist/mimic/storage.d.ts.map +1 -0
- package/dist/mimic/storage.js +197 -0
- package/dist/mimic/storage.js.map +1 -0
- package/dist/mimic/types.d.ts +63 -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 +28 -4
- package/dist/mimic.d.ts.map +1 -1
- package/dist/mimic.js +374 -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 +5 -2
|
@@ -0,0 +1,233 @@
|
|
|
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
|
+
/**
|
|
6
|
+
* Get click action by matching Gherkin step against captured target elements
|
|
7
|
+
*
|
|
8
|
+
* This function uses AI to analyze a Gherkin step and match it against
|
|
9
|
+
* all available target elements on the page. It returns the top 5 most
|
|
10
|
+
* likely candidates along with the appropriate click type.
|
|
11
|
+
*
|
|
12
|
+
* @param page - Playwright Page object (currently unused but kept for consistency)
|
|
13
|
+
* @param brain - LanguageModel instance for AI analysis
|
|
14
|
+
* @param gherkinStep - The Gherkin step to match (e.g., "I click on the Submit button")
|
|
15
|
+
* @param targetElements - Array of captured target elements from the page
|
|
16
|
+
* @param testContext - Optional test context with previous steps and current state
|
|
17
|
+
* @returns Promise resolving to ClickActionResult with top candidates and click type
|
|
18
|
+
*/
|
|
19
|
+
export const getClickAction = async (_page, brain, gherkinStep, targetElements, testContext) => {
|
|
20
|
+
// Format target elements with their indices for the prompt
|
|
21
|
+
// Include all relevant identifying information
|
|
22
|
+
const elementsWithIndices = targetElements.map((element, index) => ({
|
|
23
|
+
index,
|
|
24
|
+
tag: element.tag,
|
|
25
|
+
text: element.text,
|
|
26
|
+
id: element.id,
|
|
27
|
+
role: element.role,
|
|
28
|
+
label: element.label,
|
|
29
|
+
ariaLabel: element.ariaLabel,
|
|
30
|
+
typeAttr: element.typeAttr,
|
|
31
|
+
nameAttr: element.nameAttr,
|
|
32
|
+
href: element.href,
|
|
33
|
+
dataset: element.dataset,
|
|
34
|
+
nthOfType: element.nthOfType,
|
|
35
|
+
}));
|
|
36
|
+
// Group elements by tag type
|
|
37
|
+
const elementsByTag = new Map();
|
|
38
|
+
for (const el of elementsWithIndices) {
|
|
39
|
+
const tagKey = el.tag === 'a' ? 'links' : el.tag === 'button' ? 'buttons' : el.tag === 'input' ? 'inputs' : el.tag;
|
|
40
|
+
if (!elementsByTag.has(tagKey)) {
|
|
41
|
+
elementsByTag.set(tagKey, []);
|
|
42
|
+
}
|
|
43
|
+
elementsByTag.get(tagKey).push(el);
|
|
44
|
+
}
|
|
45
|
+
// Format element fields in selector priority order, skipping null/empty values
|
|
46
|
+
const formatElement = (roleSection) => (el) => {
|
|
47
|
+
const parts = [];
|
|
48
|
+
// Priority order: testId → text → role → ariaLabel → label → name → type → href → dataAttributes → tag → id → nthOfType
|
|
49
|
+
if (el.dataset.testid) {
|
|
50
|
+
parts.push(` testId: "${el.dataset.testid}"`);
|
|
51
|
+
}
|
|
52
|
+
if (el.text && el.text.trim()) {
|
|
53
|
+
parts.push(` text: "${el.text.trim()}"`);
|
|
54
|
+
}
|
|
55
|
+
if (el.role && roleSection !== el.role) {
|
|
56
|
+
parts.push(` role: ${el.role}`);
|
|
57
|
+
}
|
|
58
|
+
if (el.ariaLabel) {
|
|
59
|
+
parts.push(` ariaLabel: "${el.ariaLabel}"`);
|
|
60
|
+
}
|
|
61
|
+
if (el.label) {
|
|
62
|
+
parts.push(` label: "${el.label}"`);
|
|
63
|
+
}
|
|
64
|
+
if (el.nameAttr) {
|
|
65
|
+
parts.push(` name: "${el.nameAttr}"`);
|
|
66
|
+
}
|
|
67
|
+
if (el.typeAttr) {
|
|
68
|
+
parts.push(` type: ${el.typeAttr}`);
|
|
69
|
+
}
|
|
70
|
+
if (el.href) {
|
|
71
|
+
parts.push(` href: "${el.href}"`);
|
|
72
|
+
}
|
|
73
|
+
if (Object.keys(el.dataset).length > 0) {
|
|
74
|
+
const dataKeys = Object.keys(el.dataset).filter(k => k !== 'testid');
|
|
75
|
+
if (dataKeys.length > 0) {
|
|
76
|
+
parts.push(` dataAttributes: ${JSON.stringify(dataKeys)}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
parts.push(` tag: ${el.tag}`);
|
|
80
|
+
// if (el.id) {
|
|
81
|
+
// parts.push(` id: "${el.id}"`);
|
|
82
|
+
// }
|
|
83
|
+
parts.push(` index: ${el.index}`);
|
|
84
|
+
if (el.nthOfType > 1) {
|
|
85
|
+
parts.push(` nthOfType: ${el.nthOfType}`);
|
|
86
|
+
}
|
|
87
|
+
return ` - ${parts.join('\n ')}`;
|
|
88
|
+
};
|
|
89
|
+
// Create formatted description grouped by tag
|
|
90
|
+
const elementsDescription = Array.from(elementsByTag.entries())
|
|
91
|
+
.map(([tagKey, elements]) => {
|
|
92
|
+
const formattedElements = elements.map(formatElement(tagKey)).join('\n');
|
|
93
|
+
return `${tagKey}:\n${formattedElements}`;
|
|
94
|
+
})
|
|
95
|
+
.join('\n\n');
|
|
96
|
+
// Build context description for the prompt
|
|
97
|
+
const contextDescription = testContext ? `
|
|
98
|
+
**Test Context:**
|
|
99
|
+
- Current URL: ${testContext.currentState.url}
|
|
100
|
+
- Current Page Title: ${testContext.currentState.pageTitle}
|
|
101
|
+
- Step ${testContext.currentStepIndex + 1} of ${testContext.totalSteps}
|
|
102
|
+
${testContext.previousSteps.length > 0 ? `
|
|
103
|
+
**Previous Steps Executed:**
|
|
104
|
+
${testContext.previousSteps.map((prevStep, idx) => `${idx + 1}. Step ${prevStep.stepIndex + 1}: "${prevStep.stepText}" (${prevStep.actionKind}${prevStep.url ? ` → ${prevStep.url}` : ''})`).join('\n')}
|
|
105
|
+
` : ''}
|
|
106
|
+
` : '';
|
|
107
|
+
const prompt = `You are an expert Playwright test engineer specializing in mapping Gherkin steps to concrete DOM interactions.
|
|
108
|
+
|
|
109
|
+
Your task is to analyze:
|
|
110
|
+
1. A single Gherkin step that implies a click action.
|
|
111
|
+
2. A list of candidate DOM elements extracted from the page.
|
|
112
|
+
|
|
113
|
+
You must return the **top 5 most likely elements** that the Gherkin step is referring to.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### IMPORTANT RULES
|
|
118
|
+
|
|
119
|
+
- Rank elements from **most likely (rank 1)** to **least likely (rank 5)**.
|
|
120
|
+
- Prefer **semantic matches** first:
|
|
121
|
+
- Visible text
|
|
122
|
+
- Accessible name (label, aria-label, role)
|
|
123
|
+
- Button / link intent
|
|
124
|
+
- Use "index" **only as a secondary disambiguation signal**, never as the primary reason.
|
|
125
|
+
- Do NOT invent elements or field values.
|
|
126
|
+
- Do NOT include more than 5 results.
|
|
127
|
+
- If fewer than 5 reasonable matches exist, return fewer.
|
|
128
|
+
- Do NOT assume navigation or side effects — this task is only about **what element is clicked**.
|
|
129
|
+
- For each candidate, provide a **clear, human-readable description** that identifies the element (e.g., "Submit button", "Login link with text 'Sign in'", "Email input field labeled 'Email address'"). This description will be used in test annotations.
|
|
130
|
+
- Consider the test context - what steps came before may help identify the correct element.
|
|
131
|
+
|
|
132
|
+
${contextDescription}
|
|
133
|
+
**Gherkin Step:**
|
|
134
|
+
${gherkinStep}
|
|
135
|
+
|
|
136
|
+
**Available Target Elements (${targetElements.length} total):**
|
|
137
|
+
${elementsDescription}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
## Reason and return up to the top 5 most likely elements that the Gherkin step is referring to.
|
|
141
|
+
`;
|
|
142
|
+
const res = await generateText({
|
|
143
|
+
model: brain,
|
|
144
|
+
prompt,
|
|
145
|
+
maxRetries: 3,
|
|
146
|
+
output: Output.object({ schema: zClickActionResult, name: 'clickActionResult' }),
|
|
147
|
+
});
|
|
148
|
+
await countTokens(res);
|
|
149
|
+
return res.output;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Execute a click action on a page element with plain English annotation
|
|
153
|
+
*
|
|
154
|
+
* This function performs the actual click interaction and logs what action
|
|
155
|
+
* is being performed in human-readable terms for better test traceability.
|
|
156
|
+
* Uses the LLM-generated description from the selected candidate.
|
|
157
|
+
*
|
|
158
|
+
* @param element - Playwright Locator for the target element to interact with
|
|
159
|
+
* @param clickActionResult - Click action result containing click type and target information
|
|
160
|
+
* @param selectedCandidate - The selected candidate element with LLM-generated description
|
|
161
|
+
* @param testInfo - Playwright TestInfo for adding annotations
|
|
162
|
+
* @param gherkinStep - The original Gherkin step for annotation type
|
|
163
|
+
* @returns Promise that resolves to an object containing the action result and selector (for snapshot storage)
|
|
164
|
+
*/
|
|
165
|
+
export const executeClickAction = async (element, clickActionResult, selectedCandidate, testInfo, gherkinStep) => {
|
|
166
|
+
// Use the LLM-generated description from the candidate
|
|
167
|
+
// This description was created by the AI when matching the element
|
|
168
|
+
const elementDescription = selectedCandidate.description || 'element';
|
|
169
|
+
// Check if element is valid before attempting click
|
|
170
|
+
if (!element) {
|
|
171
|
+
throw new Error(`Cannot click: element not found or page may be closed`);
|
|
172
|
+
}
|
|
173
|
+
// Build annotation description based on click type
|
|
174
|
+
let annotationDescription = '';
|
|
175
|
+
switch (clickActionResult.clickType) {
|
|
176
|
+
case 'left':
|
|
177
|
+
annotationDescription = `→ Clicking on ${elementDescription} with left mouse button`;
|
|
178
|
+
break;
|
|
179
|
+
case 'right':
|
|
180
|
+
annotationDescription = `→ Right-clicking on ${elementDescription} to open context menu`;
|
|
181
|
+
break;
|
|
182
|
+
case 'double':
|
|
183
|
+
annotationDescription = `→ Double-clicking on ${elementDescription} to activate`;
|
|
184
|
+
break;
|
|
185
|
+
case 'middle':
|
|
186
|
+
annotationDescription = `→ Clicking on ${elementDescription} with middle mouse button`;
|
|
187
|
+
break;
|
|
188
|
+
case 'hover':
|
|
189
|
+
annotationDescription = `→ Hovering over ${elementDescription} to reveal additional options`;
|
|
190
|
+
break;
|
|
191
|
+
default:
|
|
192
|
+
throw new Error(`Unknown click type: ${clickActionResult.clickType}`);
|
|
193
|
+
}
|
|
194
|
+
// Add annotation using centralized utility
|
|
195
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
196
|
+
// Get selector string for snapshot storage
|
|
197
|
+
// Try to get a CSS selector representation if possible
|
|
198
|
+
let selector = null;
|
|
199
|
+
try {
|
|
200
|
+
// Attempt to get a selector string from the locator
|
|
201
|
+
// This is best-effort and may not always work
|
|
202
|
+
const locatorString = element.toString();
|
|
203
|
+
if (locatorString && locatorString !== '[object Object]') {
|
|
204
|
+
selector = locatorString;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
// If we can't get selector, that's okay - we'll rebuild from TargetInfo
|
|
209
|
+
}
|
|
210
|
+
// Perform the click action
|
|
211
|
+
switch (clickActionResult.clickType) {
|
|
212
|
+
case 'left':
|
|
213
|
+
await element.click();
|
|
214
|
+
break;
|
|
215
|
+
case 'right':
|
|
216
|
+
await element.click({ button: 'right' });
|
|
217
|
+
break;
|
|
218
|
+
case 'double':
|
|
219
|
+
await element.dblclick();
|
|
220
|
+
break;
|
|
221
|
+
case 'middle':
|
|
222
|
+
await element.click({ button: 'middle' });
|
|
223
|
+
break;
|
|
224
|
+
case 'hover':
|
|
225
|
+
await element.hover();
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
throw new Error(`Unknown click type: ${clickActionResult.clickType}`);
|
|
229
|
+
}
|
|
230
|
+
// Return action result and selector for snapshot storage
|
|
231
|
+
return { actionResult: clickActionResult, selector };
|
|
232
|
+
};
|
|
233
|
+
//# 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,47 @@
|
|
|
1
|
+
import { Locator, Page, TestInfo } from '@playwright/test';
|
|
2
|
+
import { type LanguageModel } from 'ai';
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
import { TargetInfo } from './selector';
|
|
5
|
+
import type { TestContext } from '../mimic.js';
|
|
6
|
+
declare const zFormActionResult: z.ZodObject<{
|
|
7
|
+
type: z.ZodEnum<{
|
|
8
|
+
type: "type";
|
|
9
|
+
select: "select";
|
|
10
|
+
fill: "fill";
|
|
11
|
+
check: "check";
|
|
12
|
+
uncheck: "uncheck";
|
|
13
|
+
setInputFiles: "setInputFiles";
|
|
14
|
+
clear: "clear";
|
|
15
|
+
keypress: "keypress";
|
|
16
|
+
}>;
|
|
17
|
+
params: z.ZodObject<{
|
|
18
|
+
value: z.ZodString;
|
|
19
|
+
modifiers: z.ZodArray<z.ZodEnum<{
|
|
20
|
+
none: "none";
|
|
21
|
+
Alt: "Alt";
|
|
22
|
+
Control: "Control";
|
|
23
|
+
Meta: "Meta";
|
|
24
|
+
Shift: "Shift";
|
|
25
|
+
}>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
elementDescription: z.ZodString;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export type FormActionResult = z.infer<typeof zFormActionResult>;
|
|
30
|
+
export declare const getFormAction: (_page: Page, brain: LanguageModel, gherkinStep: string, targetElements: TargetInfo[], testContext?: TestContext) => Promise<FormActionResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Execute a form action on a page element with plain English annotation
|
|
33
|
+
*
|
|
34
|
+
* This function performs form interactions (typing, selecting, checking, etc.)
|
|
35
|
+
* and adds test annotations for better traceability and validation.
|
|
36
|
+
* Uses the LLM-generated element description from the form action result.
|
|
37
|
+
*
|
|
38
|
+
* @param page - Playwright Page object for keyboard actions
|
|
39
|
+
* @param formActionResult - Form action result containing action type, parameters, and element description
|
|
40
|
+
* @param targetElement - Playwright Locator for the target form element
|
|
41
|
+
* @param testInfo - Playwright TestInfo for adding annotations (optional)
|
|
42
|
+
* @param gherkinStep - The original Gherkin step for annotation type (optional)
|
|
43
|
+
* @returns Promise that resolves when the form action is complete
|
|
44
|
+
*/
|
|
45
|
+
export declare const executeFormAction: (page: Page, formActionResult: FormActionResult, targetElement: Locator | null, testInfo?: TestInfo, gherkinStep?: string) => Promise<void | string[]>;
|
|
46
|
+
export {};
|
|
47
|
+
//# 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;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;iBAWrB,CAAA;AAGF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,eAAO,MAAM,aAAa,GACxB,OAAO,IAAI,EACX,OAAO,aAAa,EACpB,aAAa,MAAM,EACnB,gBAAgB,UAAU,EAAE,EAC5B,cAAc,WAAW,KACxB,OAAO,CAAC,gBAAgB,CAmJ1B,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,IAAI,GAAG,MAAM,EAAE,CA+FzB,CAAA"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { generateText, Output } from 'ai';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
import { countTokens } from '../utils/token-counter';
|
|
4
|
+
import { addAnnotation } from './annotations.js';
|
|
5
|
+
const zFormActionResult = z.object({
|
|
6
|
+
type: z.enum(['keypress', 'type', 'fill', 'select', 'uncheck', 'check', 'setInputFiles', 'clear']),
|
|
7
|
+
params: z.object({
|
|
8
|
+
value: z.string().describe("Value to set for the form update."),
|
|
9
|
+
modifiers: z.array(z.enum(['Alt', 'Control', 'Meta', 'Shift', 'none'])).describe("Optional modifier keys to use for the form update."),
|
|
10
|
+
}),
|
|
11
|
+
/**
|
|
12
|
+
* Human-readable description of the target form element for test annotations
|
|
13
|
+
* Should clearly identify which form field is being interacted with (e.g., "Email input field", "Submit button", "Country dropdown")
|
|
14
|
+
*/
|
|
15
|
+
elementDescription: z.string().describe("Human-readable description of the target form element for test annotations"),
|
|
16
|
+
});
|
|
17
|
+
export const getFormAction = async (_page, brain, gherkinStep, targetElements, testContext) => {
|
|
18
|
+
// Format target elements with their indices for the prompt
|
|
19
|
+
// Include all relevant identifying information
|
|
20
|
+
const elementsWithIndices = targetElements.map((element, index) => ({
|
|
21
|
+
index,
|
|
22
|
+
tag: element.tag,
|
|
23
|
+
text: element.text,
|
|
24
|
+
id: element.id,
|
|
25
|
+
role: element.role,
|
|
26
|
+
label: element.label,
|
|
27
|
+
ariaLabel: element.ariaLabel,
|
|
28
|
+
typeAttr: element.typeAttr,
|
|
29
|
+
nameAttr: element.nameAttr,
|
|
30
|
+
href: element.href,
|
|
31
|
+
dataset: element.dataset,
|
|
32
|
+
nthOfType: element.nthOfType,
|
|
33
|
+
}));
|
|
34
|
+
// Group elements by tag type
|
|
35
|
+
const elementsByTag = new Map();
|
|
36
|
+
for (const el of elementsWithIndices) {
|
|
37
|
+
const tagKey = el.tag === 'a' ? 'links' : el.tag === 'button' ? 'buttons' : el.tag === 'input' ? 'inputs' : el.tag;
|
|
38
|
+
if (!elementsByTag.has(tagKey)) {
|
|
39
|
+
elementsByTag.set(tagKey, []);
|
|
40
|
+
}
|
|
41
|
+
elementsByTag.get(tagKey).push(el);
|
|
42
|
+
}
|
|
43
|
+
// Format element fields in selector priority order, skipping null/empty values
|
|
44
|
+
const formatElement = (roleSection) => (el) => {
|
|
45
|
+
const parts = [];
|
|
46
|
+
// Priority order: testId → text → role → ariaLabel → label → name → type → href → dataAttributes → tag → id → nthOfType
|
|
47
|
+
if (el.dataset.testid) {
|
|
48
|
+
parts.push(` testId: "${el.dataset.testid}"`);
|
|
49
|
+
}
|
|
50
|
+
if (el.text && el.text.trim()) {
|
|
51
|
+
parts.push(` text: "${el.text.trim()}"`);
|
|
52
|
+
}
|
|
53
|
+
if (el.role && roleSection !== el.role) {
|
|
54
|
+
parts.push(` role: ${el.role}`);
|
|
55
|
+
}
|
|
56
|
+
if (el.ariaLabel) {
|
|
57
|
+
parts.push(` ariaLabel: "${el.ariaLabel}"`);
|
|
58
|
+
}
|
|
59
|
+
if (el.label) {
|
|
60
|
+
parts.push(` label: "${el.label}"`);
|
|
61
|
+
}
|
|
62
|
+
if (el.nameAttr) {
|
|
63
|
+
parts.push(` name: "${el.nameAttr}"`);
|
|
64
|
+
}
|
|
65
|
+
if (el.typeAttr) {
|
|
66
|
+
parts.push(` type: ${el.typeAttr}`);
|
|
67
|
+
}
|
|
68
|
+
if (el.href) {
|
|
69
|
+
parts.push(` href: "${el.href}"`);
|
|
70
|
+
}
|
|
71
|
+
if (Object.keys(el.dataset).length > 0) {
|
|
72
|
+
const dataKeys = Object.keys(el.dataset).filter(k => k !== 'testid');
|
|
73
|
+
if (dataKeys.length > 0) {
|
|
74
|
+
parts.push(` dataAttributes: ${JSON.stringify(dataKeys)}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
parts.push(` tag: ${el.tag}`);
|
|
78
|
+
// if (el.id) {
|
|
79
|
+
// parts.push(` id: "${el.id}"`);
|
|
80
|
+
// }
|
|
81
|
+
parts.push(` index: ${el.index}`);
|
|
82
|
+
if (el.nthOfType > 1) {
|
|
83
|
+
parts.push(` nthOfType: ${el.nthOfType}`);
|
|
84
|
+
}
|
|
85
|
+
return ` - ${parts.join('\n ')}`;
|
|
86
|
+
};
|
|
87
|
+
// Create formatted description grouped by tag
|
|
88
|
+
const elementsDescription = Array.from(elementsByTag.entries())
|
|
89
|
+
.map(([tagKey, elements]) => {
|
|
90
|
+
const formattedElements = elements.map(formatElement(tagKey)).join('\n');
|
|
91
|
+
return `${tagKey}:\n${formattedElements}`;
|
|
92
|
+
})
|
|
93
|
+
.join('\n\n');
|
|
94
|
+
// Build context description for the prompt
|
|
95
|
+
const contextDescription = testContext ? `
|
|
96
|
+
**Test Context:**
|
|
97
|
+
- Current URL: ${testContext.currentState.url}
|
|
98
|
+
- Current Page Title: ${testContext.currentState.pageTitle}
|
|
99
|
+
- Step ${testContext.currentStepIndex + 1} of ${testContext.totalSteps}
|
|
100
|
+
${testContext.previousSteps.length > 0 ? `
|
|
101
|
+
**Previous Steps Executed:**
|
|
102
|
+
${testContext.previousSteps.map((prevStep, idx) => `${idx + 1}. Step ${prevStep.stepIndex + 1}: "${prevStep.stepText}" (${prevStep.actionKind}${prevStep.url ? ` → ${prevStep.url}` : ''})`).join('\n')}
|
|
103
|
+
` : ''}
|
|
104
|
+
` : '';
|
|
105
|
+
const res = await generateText({
|
|
106
|
+
model: brain,
|
|
107
|
+
prompt: `You are an expert Playwright test engineer specializing in mapping Gherkin steps to form interactions.
|
|
108
|
+
|
|
109
|
+
Your task is to analyze:
|
|
110
|
+
1. A single Gherkin step that implies a form update action (typing, filling, selecting, checking, etc.).
|
|
111
|
+
2. A list of candidate form elements extracted from the page.
|
|
112
|
+
|
|
113
|
+
You must determine:
|
|
114
|
+
- The type of form action (fill, type, select, check, uncheck, clear, etc.)
|
|
115
|
+
- The value to use (text to type, option to select, etc.)
|
|
116
|
+
|
|
117
|
+
${contextDescription}
|
|
118
|
+
**Gherkin Step:**
|
|
119
|
+
${gherkinStep}
|
|
120
|
+
|
|
121
|
+
**Available Form Elements (${targetElements.length} total):**
|
|
122
|
+
${elementsDescription}
|
|
123
|
+
|
|
124
|
+
**Action Types:**
|
|
125
|
+
- fill: Replace all content in a field with text (USE THIS for typing text like email addresses, names, etc.)
|
|
126
|
+
- type: Type text character by character (slower, simulates real typing - use when needed for special cases)
|
|
127
|
+
- select: Select an option from dropdown/select element
|
|
128
|
+
- check: Check a checkbox (USE THIS when step says "check" or "select" a checkbox)
|
|
129
|
+
- uncheck: Uncheck a checkbox (USE THIS when step says "uncheck" or "deselect" a checkbox)
|
|
130
|
+
- clear: Clear field content
|
|
131
|
+
- keypress: Press a SINGLE KEY ONLY (e.g., "Enter", "Tab", "Escape", "ArrowDown") - DO NOT use for typing text strings or checkboxes
|
|
132
|
+
- setInputFiles: Upload a file
|
|
133
|
+
|
|
134
|
+
**IMPORTANT:**
|
|
135
|
+
- For typing text (email addresses, names, messages, etc.), ALWAYS use "fill" or "type", NEVER "keypress"
|
|
136
|
+
- For checkboxes, ALWAYS use "check" or "uncheck", NEVER "keypress"
|
|
137
|
+
- "keypress" is ONLY for single keyboard keys like "Enter", "Tab", "Escape", "ArrowUp", "ArrowDown", etc.
|
|
138
|
+
- If the step says "type X into Y" or "fill Y with X", use "fill" (preferred) or "type", NOT "keypress"
|
|
139
|
+
- If the step says "check" or "select" a checkbox, use "check", NOT "keypress"
|
|
140
|
+
|
|
141
|
+
**Instructions:**
|
|
142
|
+
1. Identify what form action is being requested
|
|
143
|
+
2. Extract the value from the step (text to type, option to select, etc.)
|
|
144
|
+
3. Identify which form element is being targeted (name field, email field, submit button, etc.)
|
|
145
|
+
4. Return the appropriate action type, value, and a clear description of the target element
|
|
146
|
+
- The elementDescription should clearly identify the form field (e.g., "Email input field", "Name field labeled 'Full Name'", "Submit button", "Country dropdown")
|
|
147
|
+
|
|
148
|
+
Think step-by-step about what the user wants to do with the form.`,
|
|
149
|
+
output: Output.object({ schema: zFormActionResult, name: 'formActionResult' }),
|
|
150
|
+
maxRetries: 3,
|
|
151
|
+
});
|
|
152
|
+
await countTokens(res);
|
|
153
|
+
return res.output;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Execute a form action on a page element with plain English annotation
|
|
157
|
+
*
|
|
158
|
+
* This function performs form interactions (typing, selecting, checking, etc.)
|
|
159
|
+
* and adds test annotations for better traceability and validation.
|
|
160
|
+
* Uses the LLM-generated element description from the form action result.
|
|
161
|
+
*
|
|
162
|
+
* @param page - Playwright Page object for keyboard actions
|
|
163
|
+
* @param formActionResult - Form action result containing action type, parameters, and element description
|
|
164
|
+
* @param targetElement - Playwright Locator for the target form element
|
|
165
|
+
* @param testInfo - Playwright TestInfo for adding annotations (optional)
|
|
166
|
+
* @param gherkinStep - The original Gherkin step for annotation type (optional)
|
|
167
|
+
* @returns Promise that resolves when the form action is complete
|
|
168
|
+
*/
|
|
169
|
+
export const executeFormAction = async (page, formActionResult, targetElement, testInfo, gherkinStep) => {
|
|
170
|
+
if (targetElement === null) {
|
|
171
|
+
throw new Error('No target element found');
|
|
172
|
+
}
|
|
173
|
+
// Use LLM-generated description from the form action result
|
|
174
|
+
const elementDescription = formActionResult.elementDescription || 'form field';
|
|
175
|
+
let annotationDescription = '';
|
|
176
|
+
// Get selector string for snapshot storage
|
|
177
|
+
// Try to get a CSS selector representation if possible
|
|
178
|
+
let selector = null;
|
|
179
|
+
try {
|
|
180
|
+
// Attempt to get a selector string from the locator
|
|
181
|
+
// This is best-effort and may not always work
|
|
182
|
+
const locatorString = targetElement.toString();
|
|
183
|
+
if (locatorString && locatorString !== '[object Object]') {
|
|
184
|
+
selector = locatorString;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
// If we can't get selector, that's okay - we'll rebuild from TargetInfo
|
|
189
|
+
}
|
|
190
|
+
// Perform the form action with appropriate plain English annotation
|
|
191
|
+
switch (formActionResult.type) {
|
|
192
|
+
case 'keypress':
|
|
193
|
+
// Validate that keypress is only used for single keys, not text strings
|
|
194
|
+
const keyValue = formActionResult.params.value;
|
|
195
|
+
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'];
|
|
196
|
+
// Handle empty or invalid keypress values
|
|
197
|
+
if (!keyValue || keyValue.trim() === '') {
|
|
198
|
+
// If empty value and step mentions "check", convert to check action
|
|
199
|
+
const stepLower = (gherkinStep || '').toLowerCase();
|
|
200
|
+
if (stepLower.includes('check') || stepLower.includes('select')) {
|
|
201
|
+
console.warn(`⚠️ keypress action received empty value for checkbox operation - converting to check action`);
|
|
202
|
+
annotationDescription = `→ Checking ${elementDescription} to select the option`;
|
|
203
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
204
|
+
await targetElement.check();
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
throw new Error(`keypress action requires a valid key value, but received empty string. Use 'check' for checkboxes, 'fill' for text input, etc.`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else if (keyValue.length > 1 && !validSingleKeys.includes(keyValue)) {
|
|
211
|
+
// If it's not a valid single key and looks like text, use fill instead
|
|
212
|
+
console.warn(`⚠️ keypress action received text "${keyValue}" - converting to fill action`);
|
|
213
|
+
annotationDescription = `→ Filling ${elementDescription} with value "${keyValue}"`;
|
|
214
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
215
|
+
await targetElement.fill(keyValue);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
annotationDescription = `→ Pressing key "${keyValue}" on the keyboard`;
|
|
219
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
220
|
+
await page.keyboard.press(keyValue);
|
|
221
|
+
}
|
|
222
|
+
break;
|
|
223
|
+
case 'type':
|
|
224
|
+
annotationDescription = `→ Typing "${formActionResult.params.value}" using keyboard input`;
|
|
225
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
226
|
+
await page.keyboard.type(formActionResult.params.value);
|
|
227
|
+
break;
|
|
228
|
+
case 'fill':
|
|
229
|
+
annotationDescription = `→ Filling ${elementDescription} with value "${formActionResult.params.value}"`;
|
|
230
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
231
|
+
await targetElement.fill(formActionResult.params.value);
|
|
232
|
+
break;
|
|
233
|
+
case 'select':
|
|
234
|
+
annotationDescription = `→ Selecting option "${formActionResult.params.value}" from ${elementDescription}`;
|
|
235
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
236
|
+
await targetElement.selectOption(formActionResult.params.value);
|
|
237
|
+
break;
|
|
238
|
+
case 'uncheck':
|
|
239
|
+
annotationDescription = `→ Unchecking ${elementDescription} to deselect the option`;
|
|
240
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
241
|
+
await targetElement.uncheck();
|
|
242
|
+
break;
|
|
243
|
+
case 'check':
|
|
244
|
+
annotationDescription = `→ Checking ${elementDescription} to select the option`;
|
|
245
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
246
|
+
await targetElement.check();
|
|
247
|
+
break;
|
|
248
|
+
case 'setInputFiles':
|
|
249
|
+
annotationDescription = `→ Uploading file "${formActionResult.params.value}" to ${elementDescription}`;
|
|
250
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
251
|
+
await targetElement.setInputFiles(formActionResult.params.value);
|
|
252
|
+
break;
|
|
253
|
+
case 'clear':
|
|
254
|
+
annotationDescription = `→ Clearing the contents of ${elementDescription}`;
|
|
255
|
+
addAnnotation(testInfo, gherkinStep, annotationDescription);
|
|
256
|
+
await targetElement.clear();
|
|
257
|
+
break;
|
|
258
|
+
default:
|
|
259
|
+
throw new Error(`Unknown form action type: ${formActionResult.type}`);
|
|
260
|
+
}
|
|
261
|
+
// Return action result and selector for snapshot storage
|
|
262
|
+
return { actionResult: formActionResult, selector };
|
|
263
|
+
};
|
|
264
|
+
//# 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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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type LanguageModel } from 'ai';
|
|
2
|
+
import { Page, TestInfo } from '@playwright/test';
|
|
3
|
+
import { type NavigationAction } from './schema/action.js';
|
|
4
|
+
import type { TestContext } from '../mimic.js';
|
|
5
|
+
export declare const getNavigationAction: (_page: Page, brain: LanguageModel, action: string, testContext?: TestContext) => Promise<NavigationAction>;
|
|
6
|
+
/**
|
|
7
|
+
* Execute a navigation action on the page with plain English annotation
|
|
8
|
+
*
|
|
9
|
+
* This function performs browser navigation actions (navigate, go back, refresh, etc.)
|
|
10
|
+
* and adds test annotations for better traceability and validation.
|
|
11
|
+
*
|
|
12
|
+
* @param page - Playwright Page object to perform navigation on
|
|
13
|
+
* @param navigationAction - Navigation action containing type, parameters, and description
|
|
14
|
+
* @param testInfo - Playwright TestInfo for adding annotations (optional)
|
|
15
|
+
* @param gherkinStep - The original Gherkin step for annotation type (optional)
|
|
16
|
+
* @returns Promise that resolves to the navigation action (for snapshot storage)
|
|
17
|
+
*/
|
|
18
|
+
export declare const executeNavigationAction: (page: Page, navigationAction: NavigationAction, testInfo?: TestInfo, gherkinStep?: string) => Promise<NavigationAction>;
|
|
19
|
+
//# sourceMappingURL=navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/mimic/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,IAAI,CAAA;AAC7D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEjD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,mBAAmB,GAC9B,OAAO,IAAI,EACX,OAAO,aAAa,EACpB,QAAQ,MAAM,EACd,cAAc,WAAW,KACxB,OAAO,CAAC,gBAAgB,CA8C1B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,IAAI,EACV,kBAAkB,gBAAgB,EAClC,WAAW,QAAQ,EACnB,cAAc,MAAM,KACnB,OAAO,CAAC,gBAAgB,CAwD1B,CAAC"}
|