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
package/dist/mimic.js
CHANGED
|
@@ -2,52 +2,382 @@
|
|
|
2
2
|
* Minimal flow example function
|
|
3
3
|
*/
|
|
4
4
|
import { test } from '@playwright/test';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { dirname } from 'path';
|
|
6
|
+
import { generateText, Output } from 'ai';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { getBaseAction } from './mimic/actionType.js';
|
|
9
|
+
import { getNavigationAction, executeNavigationAction } from './mimic/navigation.js';
|
|
10
|
+
import { buildSelectorForTarget, captureTargets } from './mimic/selector.js';
|
|
11
|
+
import { executeClickAction, getClickAction } from './mimic/click.js';
|
|
12
|
+
import { getFormAction, executeFormAction } from './mimic/forms.js';
|
|
13
|
+
import { startTestCase, countTokens } from './utils/token-counter.js';
|
|
14
|
+
import { hashTestText, getSnapshot, saveSnapshot, recordFailure, shouldUseSnapshot } from './mimic/storage.js';
|
|
15
|
+
import { replayFromSnapshot } from './mimic/replay.js';
|
|
16
|
+
import { isTroubleshootMode } from './mimic/cli.js';
|
|
17
|
+
import { addAnnotation } from './mimic/annotations.js';
|
|
18
|
+
/**
|
|
19
|
+
* Schema for intent accomplishment check result
|
|
20
|
+
*
|
|
21
|
+
* Note: All fields must be required (no .optional()) for AI SDK structured output compatibility.
|
|
22
|
+
* Use empty string for remainingActions when accomplished is true.
|
|
23
|
+
*/
|
|
24
|
+
const zIntentAccomplished = z.object({
|
|
25
|
+
accomplished: z.boolean().describe('Whether the step intent has been fully accomplished'),
|
|
26
|
+
reasoning: z.string().describe('Brief explanation of why the intent is or is not accomplished'),
|
|
27
|
+
remainingActions: z.string().describe('What actions might still be needed if not accomplished (provide empty string "" if accomplished is true)'),
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Check if a step's intent has been accomplished
|
|
31
|
+
*
|
|
32
|
+
* Uses the LLM to analyze the current page state and determine if the step's
|
|
33
|
+
* intent has been fully fulfilled. This allows the system to continue
|
|
34
|
+
* executing actions for a single step until the intent is complete.
|
|
35
|
+
*
|
|
36
|
+
* @param page - Playwright Page object
|
|
37
|
+
* @param brain - Language model for intent analysis
|
|
38
|
+
* @param stepText - The original step text to check intent for
|
|
39
|
+
* @param actionsTaken - Array of actions already taken for this step
|
|
40
|
+
* @returns Promise resolving to whether the intent is accomplished
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Check if a step's intent has been accomplished
|
|
44
|
+
*
|
|
45
|
+
* Uses the LLM to analyze the current page state and determine if the step's
|
|
46
|
+
* intent has been fully fulfilled. This allows the system to continue
|
|
47
|
+
* executing actions for a single step until the intent is complete.
|
|
48
|
+
*
|
|
49
|
+
* @param page - Playwright Page object
|
|
50
|
+
* @param brain - Language model for intent analysis
|
|
51
|
+
* @param stepText - The original step text to check intent for
|
|
52
|
+
* @param actionsTaken - Array of actions already taken for this step
|
|
53
|
+
* @returns Promise resolving to whether the intent is accomplished
|
|
54
|
+
*/
|
|
55
|
+
async function checkIntentAccomplished(page, brain, stepText, actionsTaken) {
|
|
56
|
+
try {
|
|
57
|
+
// Capture current page state
|
|
58
|
+
const currentUrl = page.url();
|
|
59
|
+
const pageTitle = await page.title();
|
|
60
|
+
const pageContent = await page.textContent('body') || '';
|
|
61
|
+
const pageContentPreview = pageContent.substring(0, 2000); // Limit content size
|
|
62
|
+
// Build description of actions taken
|
|
63
|
+
const actionsDescription = actionsTaken.length > 0
|
|
64
|
+
? actionsTaken.map((action, idx) => `${idx + 1}. ${action.actionKind}: ${action.stepText}`).join('\n')
|
|
65
|
+
: 'No actions taken yet';
|
|
66
|
+
const prompt = `You are analyzing whether a test step's intent has been fully accomplished.
|
|
67
|
+
|
|
68
|
+
**Step Intent:**
|
|
69
|
+
${stepText}
|
|
70
|
+
|
|
71
|
+
**Actions Taken So Far:**
|
|
72
|
+
${actionsDescription}
|
|
73
|
+
|
|
74
|
+
**Current Page State:**
|
|
75
|
+
- URL: ${currentUrl}
|
|
76
|
+
- Page Title: ${pageTitle}
|
|
77
|
+
- Page Content Preview: ${pageContentPreview.substring(0, 500)}...
|
|
78
|
+
|
|
79
|
+
**Instructions:**
|
|
80
|
+
Analyze whether the step's intent has been FULLY accomplished based on:
|
|
81
|
+
1. The literal meaning of the step text
|
|
82
|
+
2. The actions that have been taken
|
|
83
|
+
3. The current state of the page
|
|
84
|
+
|
|
85
|
+
Consider:
|
|
86
|
+
- Has the step's primary goal been achieved?
|
|
87
|
+
- Are there any remaining sub-tasks implied by the step?
|
|
88
|
+
- Would a reasonable person reading the step consider it complete?
|
|
89
|
+
|
|
90
|
+
Be strict: only mark as accomplished if the intent is FULLY satisfied. If the step requires multiple actions (e.g., "fill in the form and submit it"), it's not accomplished until ALL parts are done.
|
|
91
|
+
|
|
92
|
+
**Important:** Always provide all fields:
|
|
93
|
+
- If accomplished is true, set remainingActions to an empty string ""
|
|
94
|
+
- If accomplished is false, describe what actions are still needed in remainingActions`;
|
|
95
|
+
const result = await generateText({
|
|
96
|
+
model: brain,
|
|
97
|
+
prompt,
|
|
98
|
+
output: Output.object({ schema: zIntentAccomplished, name: 'intentAccomplished' }),
|
|
99
|
+
});
|
|
100
|
+
await countTokens(result);
|
|
101
|
+
const output = result.output;
|
|
102
|
+
if (!output.accomplished && output.remainingActions && output.remainingActions.trim()) {
|
|
103
|
+
console.log(`→ Step intent not yet accomplished. ${output.reasoning}`);
|
|
104
|
+
console.log(`→ Remaining: ${output.remainingActions}`);
|
|
105
|
+
}
|
|
106
|
+
else if (output.accomplished) {
|
|
107
|
+
console.log(`✓ Step intent accomplished: ${output.reasoning}`);
|
|
108
|
+
}
|
|
109
|
+
return output.accomplished;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
// If intent check fails, default to false (continue trying)
|
|
113
|
+
console.warn(`Failed to check intent accomplishment: ${error instanceof Error ? error.message : String(error)}`);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
10
117
|
/**
|
|
11
118
|
* Minimal flow function that takes a Playwright page and input string
|
|
12
119
|
*
|
|
13
120
|
* @param page - Playwright Page object
|
|
14
121
|
* @param input - Input string to process
|
|
122
|
+
* @param testFilePath - Directory path of the test file (for snapshot storage)
|
|
123
|
+
* @param troubleshootMode - Whether troubleshoot mode is enabled
|
|
15
124
|
* @returns Flow execution result with validated context
|
|
16
125
|
*/
|
|
17
|
-
export async function mimic(input, { page, brains, testInfo }) {
|
|
126
|
+
export async function mimic(input, { page, brains, testInfo, testFilePath, troubleshootMode }) {
|
|
18
127
|
if (testInfo?.title)
|
|
19
128
|
await startTestCase(testInfo.title);
|
|
129
|
+
// Generate test hash for snapshot identification
|
|
130
|
+
const testHash = hashTestText(input);
|
|
131
|
+
const isTroubleshoot = troubleshootMode ?? isTroubleshootMode();
|
|
132
|
+
// Normal execution with LLM - track steps for snapshot creation
|
|
20
133
|
const steps = input.split('\n')
|
|
21
134
|
// lets clean up things
|
|
22
135
|
.map(step => step.trim())
|
|
23
136
|
// and remove empty steps
|
|
24
|
-
.filter(step => step.length > 0);
|
|
137
|
+
.filter((step) => step.length > 0);
|
|
138
|
+
const expectedStepCount = steps.length;
|
|
139
|
+
// Check if we should use an existing snapshot
|
|
140
|
+
// Even in troubleshoot mode, try to use snapshot first - only regenerate on failure
|
|
141
|
+
const useSnapshot = testFilePath && await shouldUseSnapshot(testFilePath, testHash, isTroubleshoot, expectedStepCount);
|
|
142
|
+
if (useSnapshot) {
|
|
143
|
+
const snapshot = await getSnapshot(testFilePath, testHash);
|
|
144
|
+
if (snapshot) {
|
|
145
|
+
// Add annotation indicating we're loading from snapshot
|
|
146
|
+
addAnnotation(testInfo, 'snapshot-load', `📦 Loading test from mimic snapshot file (${snapshot.steps.length} step${snapshot.steps.length !== 1 ? 's' : ''} cached)`);
|
|
147
|
+
try {
|
|
148
|
+
// Replay from snapshot (skip LLM calls for faster execution)
|
|
149
|
+
await replayFromSnapshot(page, snapshot, testInfo);
|
|
150
|
+
// If replay succeeds, we're done
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
// Replay failed - regenerate actions
|
|
155
|
+
// Add annotation at the top indicating test is being updated
|
|
156
|
+
addAnnotation(testInfo, 'test-update', `🔄 Test snapshot replay failed, regenerating actions: ${error instanceof Error ? error.message : String(error)}`);
|
|
157
|
+
// Record the failure before regenerating
|
|
158
|
+
if (testFilePath) {
|
|
159
|
+
await recordFailure(testFilePath, testHash, undefined, undefined, error instanceof Error ? error.message : String(error));
|
|
160
|
+
}
|
|
161
|
+
// Fall through to regenerate actions below
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (testFilePath) {
|
|
166
|
+
// No snapshot exists or snapshot shouldn't be used - check if we're updating
|
|
167
|
+
const existingSnapshot = await getSnapshot(testFilePath, testHash);
|
|
168
|
+
if (existingSnapshot && existingSnapshot.lastFailedAt) {
|
|
169
|
+
// We have a failed snapshot - add annotation that we're regenerating
|
|
170
|
+
addAnnotation(testInfo, 'test-update', '🔄 Regenerating test actions due to previous failure');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// executedSteps will be populated during step execution below
|
|
174
|
+
const executedSteps = [];
|
|
25
175
|
// now lets process each step
|
|
26
|
-
for (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
176
|
+
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
|
|
177
|
+
const step = steps[stepIndex];
|
|
178
|
+
// Type guard: ensure step is defined (should always be true after filter)
|
|
179
|
+
if (!step) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
await test.step(step, async () => {
|
|
184
|
+
// Build test context from previous steps and current state
|
|
185
|
+
const currentUrl = page.url();
|
|
186
|
+
const currentPageTitle = await page.title().catch(() => 'Unknown');
|
|
187
|
+
const testContext = {
|
|
188
|
+
previousSteps: executedSteps.map((executedStep) => ({
|
|
189
|
+
stepIndex: executedStep.stepIndex,
|
|
190
|
+
stepText: executedStep.stepText,
|
|
191
|
+
actionKind: executedStep.actionKind,
|
|
192
|
+
// Extract URL from navigation actions if available
|
|
193
|
+
url: executedStep.actionKind === 'navigation'
|
|
194
|
+
? executedStep.actionDetails.params?.url || undefined
|
|
195
|
+
: undefined,
|
|
196
|
+
})),
|
|
197
|
+
currentState: {
|
|
198
|
+
url: currentUrl,
|
|
199
|
+
pageTitle: currentPageTitle,
|
|
200
|
+
},
|
|
201
|
+
totalSteps: steps.length,
|
|
202
|
+
currentStepIndex: stepIndex,
|
|
203
|
+
};
|
|
204
|
+
// Track all actions taken for this step
|
|
205
|
+
const stepActions = [];
|
|
206
|
+
const maxActionsPerStep = 10; // Prevent infinite loops
|
|
207
|
+
let actionCount = 0;
|
|
208
|
+
let intentAccomplished = false;
|
|
209
|
+
// Loop until intent is accomplished or max actions reached
|
|
210
|
+
while (!intentAccomplished && actionCount < maxActionsPerStep) {
|
|
211
|
+
actionCount++;
|
|
212
|
+
// Check if intent is already accomplished (skip check on first action)
|
|
213
|
+
if (actionCount > 1) {
|
|
214
|
+
intentAccomplished = await checkIntentAccomplished(page, brains, step, stepActions);
|
|
215
|
+
if (intentAccomplished) {
|
|
216
|
+
console.log(`✓ Step intent accomplished after ${actionCount - 1} action(s)`);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
console.log(`→ Continuing to add actions for step (attempt ${actionCount})...`);
|
|
220
|
+
}
|
|
221
|
+
// Get the next action to execute for this step
|
|
222
|
+
const baseAction = await getBaseAction(page, brains, step, testContext);
|
|
223
|
+
let stepResult;
|
|
224
|
+
switch (baseAction.kind) {
|
|
225
|
+
case 'navigation':
|
|
226
|
+
// Navigation actions will log their own plain English annotations
|
|
227
|
+
const navigationAction = await getNavigationAction(page, brains, step, testContext);
|
|
228
|
+
const executedNavAction = await executeNavigationAction(page, navigationAction, testInfo, step);
|
|
229
|
+
stepResult = {
|
|
230
|
+
stepIndex,
|
|
231
|
+
stepText: step,
|
|
232
|
+
actionKind: 'navigation',
|
|
233
|
+
actionDetails: executedNavAction,
|
|
234
|
+
};
|
|
235
|
+
break;
|
|
236
|
+
case 'click':
|
|
237
|
+
// Click actions will log their own plain English annotations
|
|
238
|
+
const targetElements = await captureTargets(page, { interactableOnly: true });
|
|
239
|
+
const clickActionResult = await getClickAction(page, brains, step, targetElements, testContext);
|
|
240
|
+
// TODO: better way to work out if the top priority candidate is a clickable element
|
|
241
|
+
const selectedCandidate = clickActionResult.candidates.find(Boolean);
|
|
242
|
+
if (!selectedCandidate) {
|
|
243
|
+
throw new Error(`No candidate element found for click action: ${step}`);
|
|
244
|
+
}
|
|
245
|
+
const targetElement = targetElements[selectedCandidate.index];
|
|
246
|
+
if (!targetElement) {
|
|
247
|
+
throw new Error(`Target element not found at index ${selectedCandidate.index}`);
|
|
248
|
+
}
|
|
249
|
+
const clickable = await buildSelectorForTarget(page, targetElement);
|
|
250
|
+
const clickResult = await executeClickAction(clickable, clickActionResult, selectedCandidate, testInfo, step);
|
|
251
|
+
// Build targetElement with optional selector
|
|
252
|
+
// Use Object.assign to preserve all required TargetInfo properties
|
|
253
|
+
const targetElementWithSelector = clickResult.selector
|
|
254
|
+
? Object.assign({}, targetElement, { selector: clickResult.selector })
|
|
255
|
+
: targetElement;
|
|
256
|
+
stepResult = {
|
|
257
|
+
stepIndex,
|
|
258
|
+
stepText: step,
|
|
259
|
+
actionKind: 'click',
|
|
260
|
+
actionDetails: clickResult.actionResult,
|
|
261
|
+
targetElement: targetElementWithSelector,
|
|
262
|
+
};
|
|
263
|
+
break;
|
|
264
|
+
case 'form update':
|
|
265
|
+
// Form actions will log their own plain English annotations
|
|
266
|
+
const formElements = await captureTargets(page, { interactableOnly: true });
|
|
267
|
+
const formActionResult = await getFormAction(page, brains, step, formElements, testContext);
|
|
268
|
+
// Find the target form element by matching step description
|
|
269
|
+
// Try to find element that matches keywords from the step (name, email, etc.)
|
|
270
|
+
const stepLower = step.toLowerCase();
|
|
271
|
+
let formElement = formElements.find(el => {
|
|
272
|
+
// Match by label, name, id, or placeholder
|
|
273
|
+
const labelMatch = el.label && stepLower.includes(el.label.toLowerCase());
|
|
274
|
+
const nameMatch = el.nameAttr && stepLower.includes(el.nameAttr.toLowerCase());
|
|
275
|
+
const idMatch = el.id && stepLower.includes(el.id.toLowerCase());
|
|
276
|
+
const ariaLabelMatch = el.ariaLabel && stepLower.includes(el.ariaLabel.toLowerCase());
|
|
277
|
+
// Also check if step mentions the element type (e.g., "name field", "email field")
|
|
278
|
+
const fieldTypeMatch = (stepLower.includes('name') && (el.nameAttr?.includes('name') || el.id?.includes('name') || el.label?.toLowerCase().includes('name'))) ||
|
|
279
|
+
(stepLower.includes('email') && (el.nameAttr?.includes('email') || el.id?.includes('email') || el.label?.toLowerCase().includes('email'))) ||
|
|
280
|
+
(stepLower.includes('phone') && (el.nameAttr?.includes('phone') || el.id?.includes('phone') || el.label?.toLowerCase().includes('phone'))) ||
|
|
281
|
+
(stepLower.includes('message') && (el.nameAttr?.includes('message') || el.id?.includes('message') || el.label?.toLowerCase().includes('message')));
|
|
282
|
+
return (labelMatch || nameMatch || idMatch || ariaLabelMatch || fieldTypeMatch) &&
|
|
283
|
+
(el.tag === 'input' || el.tag === 'textarea' || el.tag === 'select');
|
|
284
|
+
});
|
|
285
|
+
// Fallback to first form element if no match found
|
|
286
|
+
if (!formElement) {
|
|
287
|
+
formElement = formElements.find(el => el.tag === 'input' || el.tag === 'textarea' || el.tag === 'select') || formElements[0];
|
|
288
|
+
}
|
|
289
|
+
if (formElement) {
|
|
290
|
+
const targetFormElement = await buildSelectorForTarget(page, formElement);
|
|
291
|
+
const formResult = await executeFormAction(page, formActionResult, targetFormElement, testInfo, step);
|
|
292
|
+
// Handle the return type - executeFormAction may return void | string[] or { actionResult, selector }
|
|
293
|
+
let selector = undefined;
|
|
294
|
+
let actionDetails = formActionResult;
|
|
295
|
+
if (formResult && typeof formResult === 'object' && 'actionResult' in formResult) {
|
|
296
|
+
actionDetails = formResult.actionResult;
|
|
297
|
+
const resultSelector = formResult.selector;
|
|
298
|
+
if (resultSelector) {
|
|
299
|
+
selector = resultSelector;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
stepResult = {
|
|
303
|
+
stepIndex,
|
|
304
|
+
stepText: step,
|
|
305
|
+
actionKind: 'form update',
|
|
306
|
+
actionDetails,
|
|
307
|
+
targetElement: selector
|
|
308
|
+
? { ...formElement, selector }
|
|
309
|
+
: formElement,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
console.warn(`→ No form element found for step: ${step}`);
|
|
314
|
+
// Create a step result without target element
|
|
315
|
+
stepResult = {
|
|
316
|
+
stepIndex,
|
|
317
|
+
stepText: step,
|
|
318
|
+
actionKind: 'form update',
|
|
319
|
+
actionDetails: formActionResult,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
break;
|
|
323
|
+
default:
|
|
324
|
+
throw new Error(`Unknown base action type: ${baseAction.kind}`);
|
|
325
|
+
}
|
|
326
|
+
// Add this action to the step's actions
|
|
327
|
+
stepActions.push(stepResult);
|
|
328
|
+
// After executing an action, check if intent is accomplished
|
|
329
|
+
// (but skip if we just checked before this action)
|
|
330
|
+
if (actionCount === 1 || actionCount >= maxActionsPerStep) {
|
|
331
|
+
intentAccomplished = await checkIntentAccomplished(page, brains, step, stepActions);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// Add all actions for this step to executedSteps
|
|
335
|
+
// Each action represents a sub-action taken to accomplish the step
|
|
336
|
+
executedSteps.push(...stepActions);
|
|
337
|
+
if (actionCount >= maxActionsPerStep && !intentAccomplished) {
|
|
338
|
+
console.warn(`⚠️ Reached maximum actions (${maxActionsPerStep}) for step: ${step}. Intent may not be fully accomplished.`);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
// Record failure and rethrow with step information
|
|
344
|
+
if (testFilePath) {
|
|
345
|
+
await recordFailure(testFilePath, testHash, stepIndex, step, error instanceof Error ? error.message : String(error));
|
|
49
346
|
}
|
|
50
|
-
|
|
347
|
+
throw new Error(`Step ${stepIndex + 1} failed: ${step}\n${error instanceof Error ? error.message : String(error)}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Save snapshot on successful completion
|
|
351
|
+
// Only save if we executed at least as many steps as input lines
|
|
352
|
+
if (testFilePath && executedSteps.length > 0) {
|
|
353
|
+
// Count unique steps executed (by stepIndex)
|
|
354
|
+
const uniqueStepIndices = new Set(executedSteps.map(step => step.stepIndex));
|
|
355
|
+
const executedStepCount = uniqueStepIndices.size;
|
|
356
|
+
// Only save if we have at least as many steps as input lines
|
|
357
|
+
if (executedStepCount >= expectedStepCount) {
|
|
358
|
+
// Check if this was a regeneration (snapshot existed but we regenerated)
|
|
359
|
+
const existingSnapshot = await getSnapshot(testFilePath, testHash);
|
|
360
|
+
const wasRegeneration = existingSnapshot !== null;
|
|
361
|
+
await saveSnapshot(testFilePath, {
|
|
362
|
+
testHash,
|
|
363
|
+
testText: input,
|
|
364
|
+
createdAt: existingSnapshot?.createdAt || new Date().toISOString(),
|
|
365
|
+
lastPassedAt: new Date().toISOString(),
|
|
366
|
+
lastFailedAt: null,
|
|
367
|
+
steps: executedSteps.map(step => ({
|
|
368
|
+
...step,
|
|
369
|
+
executedAt: new Date().toISOString(),
|
|
370
|
+
})),
|
|
371
|
+
});
|
|
372
|
+
// Add annotation if this was a regeneration
|
|
373
|
+
if (wasRegeneration) {
|
|
374
|
+
addAnnotation(testInfo, 'test-update', '✅ Test actions successfully regenerated and saved');
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
// Not all steps were executed - don't save incomplete snapshot
|
|
379
|
+
console.warn(`⚠️ Not saving snapshot: only ${executedStepCount} of ${expectedStepCount} steps executed`);
|
|
380
|
+
}
|
|
51
381
|
}
|
|
52
382
|
}
|
|
53
383
|
function trimTemplate(strings, ...values) {
|
|
@@ -63,9 +393,21 @@ function trimTemplate(strings, ...values) {
|
|
|
63
393
|
.join('\n');
|
|
64
394
|
}
|
|
65
395
|
export const createMimic = (config) => {
|
|
396
|
+
// Extract test file path from TestInfo if available
|
|
397
|
+
const testFilePath = config.testInfo?.file
|
|
398
|
+
? dirname(config.testInfo.file)
|
|
399
|
+
: undefined;
|
|
400
|
+
// Check troubleshoot mode
|
|
401
|
+
const troubleshootMode = isTroubleshootMode();
|
|
66
402
|
return async (prompt, ...args) => {
|
|
67
403
|
const lines = trimTemplate(prompt, ...args);
|
|
68
|
-
return await mimic(lines,
|
|
404
|
+
return await mimic(lines, {
|
|
405
|
+
page: config.page,
|
|
406
|
+
brains: config.brains,
|
|
407
|
+
testInfo: config.testInfo,
|
|
408
|
+
...(testFilePath ? { testFilePath } : {}),
|
|
409
|
+
troubleshootMode,
|
|
410
|
+
});
|
|
69
411
|
};
|
|
70
412
|
};
|
|
71
413
|
//# sourceMappingURL=mimic.js.map
|
package/dist/mimic.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mimic.js","sourceRoot":"","sources":["../src/mimic.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mimic.js","sourceRoot":"","sources":["../src/mimic.ts"],"names":[],"mappings":"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"}
|
package/dist/mimicry.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Page, TestInfo } from '@playwright/test';
|
|
5
5
|
import type { LanguageModel } from 'ai';
|
|
6
|
-
export type
|
|
6
|
+
export type Mimic = (steps: TemplateStringsArray, ...args: unknown[]) => Promise<void>;
|
|
7
7
|
/**
|
|
8
8
|
* Minimal flow function that takes a Playwright page and input string
|
|
9
9
|
*
|
|
@@ -11,12 +11,12 @@ export type Mimicry = (steps: TemplateStringsArray, ...args: unknown[]) => Promi
|
|
|
11
11
|
* @param input - Input string to process
|
|
12
12
|
* @returns Flow execution result with validated context
|
|
13
13
|
*/
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function mimic(input: string, { page, brains, testInfo }: {
|
|
15
15
|
page: Page;
|
|
16
16
|
brains: LanguageModel;
|
|
17
|
-
testInfo
|
|
17
|
+
testInfo: TestInfo | undefined;
|
|
18
18
|
}): Promise<void>;
|
|
19
|
-
export declare const
|
|
19
|
+
export declare const createMimic: (config: {
|
|
20
20
|
page: Page;
|
|
21
21
|
brains: LanguageModel;
|
|
22
22
|
testInfo?: TestInfo;
|
package/dist/mimicry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mimicry.d.ts","sourceRoot":"","sources":["../src/mimicry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAQ,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAQxC,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"mimicry.d.ts","sourceRoot":"","sources":["../src/mimicry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAQ,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAQxC,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAGvF;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IACrE,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;CAChC,iBA6CA;AAeD,eAAO,MAAM,WAAW,GAAI,QAAQ;IAClC,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,MACe,QAAQ,oBAAoB,EAAE,GAAG,MAAM,OAAO,EAAE,kBAQ/D,CAAA"}
|
package/dist/mimicry.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Minimal flow example function
|
|
3
3
|
*/
|
|
4
4
|
import { test } from '@playwright/test';
|
|
5
|
-
import { getBaseAction } from './
|
|
6
|
-
import { getNavigationAction, executeNavigationAction } from './
|
|
7
|
-
import { buildSelectorForTarget, captureTargets } from './
|
|
8
|
-
import { executeClickAction, getClickAction } from './
|
|
5
|
+
import { getBaseAction } from './mimic/actionType.js';
|
|
6
|
+
import { getNavigationAction, executeNavigationAction } from './mimic/navigation.js';
|
|
7
|
+
import { buildSelectorForTarget, captureTargets } from './mimic/selector.js';
|
|
8
|
+
import { executeClickAction, getClickAction } from './mimic/click.js';
|
|
9
9
|
import { startTestCase } from './utils/token-counter.js';
|
|
10
10
|
/**
|
|
11
11
|
* Minimal flow function that takes a Playwright page and input string
|
|
@@ -14,7 +14,7 @@ import { startTestCase } from './utils/token-counter.js';
|
|
|
14
14
|
* @param input - Input string to process
|
|
15
15
|
* @returns Flow execution result with validated context
|
|
16
16
|
*/
|
|
17
|
-
export async function
|
|
17
|
+
export async function mimic(input, { page, brains, testInfo }) {
|
|
18
18
|
if (testInfo?.title)
|
|
19
19
|
await startTestCase(testInfo.title);
|
|
20
20
|
const steps = input.split('\n')
|
|
@@ -28,21 +28,26 @@ export async function mimicry(input, { page, brains, testInfo }) {
|
|
|
28
28
|
const baseAction = await getBaseAction(page, brains, step);
|
|
29
29
|
switch (baseAction.kind) {
|
|
30
30
|
case 'navigation':
|
|
31
|
-
|
|
31
|
+
// Navigation actions will log their own plain English annotations
|
|
32
32
|
const navigationAction = await getNavigationAction(page, brains, step);
|
|
33
|
-
await executeNavigationAction(page, navigationAction);
|
|
33
|
+
await executeNavigationAction(page, navigationAction, testInfo || undefined, step);
|
|
34
34
|
break;
|
|
35
35
|
case 'click':
|
|
36
|
-
|
|
36
|
+
// Click actions will log their own plain English annotations
|
|
37
37
|
const targetElements = await captureTargets(page, { interactableOnly: true });
|
|
38
38
|
const clickActionResult = await getClickAction(page, brains, step, targetElements);
|
|
39
39
|
// TODO: better way to work out if the top priority candidate is a clickable element
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const selectedCandidate = clickActionResult.candidates.find(Boolean);
|
|
41
|
+
if (!selectedCandidate) {
|
|
42
|
+
throw new Error(`No candidate element found for click action: ${step}`);
|
|
43
|
+
}
|
|
44
|
+
const clickable = await buildSelectorForTarget(page, targetElements[selectedCandidate.index]);
|
|
45
|
+
await executeClickAction(clickable, clickActionResult, selectedCandidate, testInfo || undefined, step);
|
|
42
46
|
break;
|
|
43
47
|
case 'form update':
|
|
48
|
+
// Form actions will log their own plain English annotations
|
|
44
49
|
const formElements = await captureTargets(page, { interactableOnly: true });
|
|
45
|
-
console.log(
|
|
50
|
+
console.log(`→ Processing form update: Found ${formElements.length} interactable form elements on the page`);
|
|
46
51
|
break;
|
|
47
52
|
default:
|
|
48
53
|
throw new Error(`Unknown base action type: ${baseAction.kind}`);
|
|
@@ -62,10 +67,14 @@ function trimTemplate(strings, ...values) {
|
|
|
62
67
|
.filter(line => line.length > 0)
|
|
63
68
|
.join('\n');
|
|
64
69
|
}
|
|
65
|
-
export const
|
|
70
|
+
export const createMimic = (config) => {
|
|
66
71
|
return async (prompt, ...args) => {
|
|
67
72
|
const lines = trimTemplate(prompt, ...args);
|
|
68
|
-
return await
|
|
73
|
+
return await mimic(lines, {
|
|
74
|
+
page: config.page,
|
|
75
|
+
brains: config.brains,
|
|
76
|
+
testInfo: config.testInfo,
|
|
77
|
+
});
|
|
69
78
|
};
|
|
70
79
|
};
|
|
71
80
|
//# sourceMappingURL=mimicry.js.map
|
package/dist/mimicry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mimicry.js","sourceRoot":"","sources":["../src/mimicry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAkB,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"mimicry.js","sourceRoot":"","sources":["../src/mimicry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright-mimic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Playwright Mimic allows AI to connect LLM to help in maintaining test code based off of logical steps in the test file in English",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"build": "tsc",
|
|
20
20
|
"test": "playwright test",
|
|
21
21
|
"test:ui": "playwright test --ui",
|
|
22
|
-
"test:debug": "playwright test --debug"
|
|
22
|
+
"test:debug": "playwright test --debug",
|
|
23
|
+
"serve": "http-server test-site -p 3000 -c-1"
|
|
23
24
|
},
|
|
24
25
|
"keywords": [],
|
|
25
26
|
"author": "",
|
|
@@ -31,6 +32,8 @@
|
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"ai": "^6.0.3",
|
|
33
34
|
"dotenv": "^17.2.3",
|
|
35
|
+
"http-server": "^14.1.1",
|
|
36
|
+
"sharp": "^0.33.5",
|
|
34
37
|
"typescript": "^5.9.3",
|
|
35
38
|
"zod": "^4.2.1"
|
|
36
39
|
},
|