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.
Files changed (110) hide show
  1. package/README.md +633 -446
  2. package/dist/agentic/agent.d.ts +106 -0
  3. package/dist/agentic/agent.d.ts.map +1 -0
  4. package/dist/agentic/agent.js +528 -0
  5. package/dist/agentic/agent.js.map +1 -0
  6. package/dist/agentic/index.d.ts +13 -0
  7. package/dist/agentic/index.d.ts.map +1 -0
  8. package/dist/agentic/index.js +12 -0
  9. package/dist/agentic/index.js.map +1 -0
  10. package/dist/agentic/planner.d.ts +41 -0
  11. package/dist/agentic/planner.d.ts.map +1 -0
  12. package/dist/agentic/planner.js +136 -0
  13. package/dist/agentic/planner.js.map +1 -0
  14. package/dist/agentic/react.d.ts +35 -0
  15. package/dist/agentic/react.d.ts.map +1 -0
  16. package/dist/agentic/react.js +170 -0
  17. package/dist/agentic/react.js.map +1 -0
  18. package/dist/agentic/recovery.d.ts +55 -0
  19. package/dist/agentic/recovery.d.ts.map +1 -0
  20. package/dist/agentic/recovery.js +200 -0
  21. package/dist/agentic/recovery.js.map +1 -0
  22. package/dist/agentic/reflection.d.ts +40 -0
  23. package/dist/agentic/reflection.d.ts.map +1 -0
  24. package/dist/agentic/reflection.js +142 -0
  25. package/dist/agentic/reflection.js.map +1 -0
  26. package/dist/agentic/types.d.ts +177 -0
  27. package/dist/agentic/types.d.ts.map +1 -0
  28. package/dist/agentic/types.js +8 -0
  29. package/dist/agentic/types.js.map +1 -0
  30. package/dist/agentic/wait.d.ts +50 -0
  31. package/dist/agentic/wait.d.ts.map +1 -0
  32. package/dist/agentic/wait.js +140 -0
  33. package/dist/agentic/wait.js.map +1 -0
  34. package/dist/agentic-mimic.d.ts +56 -0
  35. package/dist/agentic-mimic.d.ts.map +1 -0
  36. package/dist/agentic-mimic.js +98 -0
  37. package/dist/agentic-mimic.js.map +1 -0
  38. package/dist/index.d.ts +11 -8
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +12 -9
  41. package/dist/index.js.map +1 -1
  42. package/dist/mimic/actionType.d.ts +7 -0
  43. package/dist/mimic/actionType.d.ts.map +1 -0
  44. package/dist/mimic/actionType.js +44 -0
  45. package/dist/mimic/actionType.js.map +1 -0
  46. package/dist/mimic/annotations.d.ts +20 -0
  47. package/dist/mimic/annotations.d.ts.map +1 -0
  48. package/dist/mimic/annotations.js +30 -0
  49. package/dist/mimic/annotations.js.map +1 -0
  50. package/dist/mimic/cli.d.ts +15 -0
  51. package/dist/mimic/cli.d.ts.map +1 -0
  52. package/dist/mimic/cli.js +17 -0
  53. package/dist/mimic/cli.js.map +1 -0
  54. package/dist/mimic/click.d.ts +39 -0
  55. package/dist/mimic/click.d.ts.map +1 -0
  56. package/dist/mimic/click.js +233 -0
  57. package/dist/mimic/click.js.map +1 -0
  58. package/dist/mimic/forms.d.ts +47 -0
  59. package/dist/mimic/forms.d.ts.map +1 -0
  60. package/dist/mimic/forms.js +264 -0
  61. package/dist/mimic/forms.js.map +1 -0
  62. package/dist/mimic/navigation.d.ts +19 -0
  63. package/dist/mimic/navigation.d.ts.map +1 -0
  64. package/dist/mimic/navigation.js +117 -0
  65. package/dist/mimic/navigation.js.map +1 -0
  66. package/dist/mimic/replay.d.ts +21 -0
  67. package/dist/mimic/replay.d.ts.map +1 -0
  68. package/dist/mimic/replay.js +133 -0
  69. package/dist/mimic/replay.js.map +1 -0
  70. package/dist/mimic/schema/action.d.ts +315 -0
  71. package/dist/mimic/schema/action.d.ts.map +1 -0
  72. package/dist/mimic/schema/action.js +204 -0
  73. package/dist/mimic/schema/action.js.map +1 -0
  74. package/dist/mimic/selector.d.ts +139 -0
  75. package/dist/mimic/selector.d.ts.map +1 -0
  76. package/dist/mimic/selector.js +1103 -0
  77. package/dist/mimic/selector.js.map +1 -0
  78. package/dist/mimic/selectorDescriptor.d.ts +13 -0
  79. package/dist/mimic/selectorDescriptor.d.ts.map +1 -0
  80. package/dist/mimic/selectorDescriptor.js +9 -0
  81. package/dist/mimic/selectorDescriptor.js.map +1 -0
  82. package/dist/mimic/selectorSerialization.d.ts +30 -0
  83. package/dist/mimic/selectorSerialization.d.ts.map +1 -0
  84. package/dist/mimic/selectorSerialization.js +170 -0
  85. package/dist/mimic/selectorSerialization.js.map +1 -0
  86. package/dist/mimic/selectorTypes.d.ts +200 -0
  87. package/dist/mimic/selectorTypes.d.ts.map +1 -0
  88. package/dist/mimic/selectorTypes.js +2 -0
  89. package/dist/mimic/selectorTypes.js.map +1 -0
  90. package/dist/mimic/selectorUtils.d.ts +26 -0
  91. package/dist/mimic/selectorUtils.d.ts.map +1 -0
  92. package/dist/mimic/selectorUtils.js +144 -0
  93. package/dist/mimic/selectorUtils.js.map +1 -0
  94. package/dist/mimic/storage.d.ts +75 -0
  95. package/dist/mimic/storage.d.ts.map +1 -0
  96. package/dist/mimic/storage.js +197 -0
  97. package/dist/mimic/storage.js.map +1 -0
  98. package/dist/mimic/types.d.ts +63 -0
  99. package/dist/mimic/types.d.ts.map +1 -0
  100. package/dist/mimic/types.js +7 -0
  101. package/dist/mimic/types.js.map +1 -0
  102. package/dist/mimic.d.ts +28 -4
  103. package/dist/mimic.d.ts.map +1 -1
  104. package/dist/mimic.js +374 -32
  105. package/dist/mimic.js.map +1 -1
  106. package/dist/mimicry.d.ts +4 -4
  107. package/dist/mimicry.d.ts.map +1 -1
  108. package/dist/mimicry.js +22 -13
  109. package/dist/mimicry.js.map +1 -1
  110. 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"}