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
package/README.md CHANGED
@@ -1,446 +1,633 @@
1
- # Playwright Mimic
2
-
3
- **Playwright Mimic** is an AI-powered browser testing framework that takes natural language instructions and reasons through them to operate the browser and run tests. It's designed to work seamlessly with Playwright, allowing you to write tests in plain English (Gherkin-style) that are automatically executed by AI.
4
-
5
- ## Features
6
-
7
- - 🤖 **AI-Powered**: Uses language models to understand and execute natural language test instructions
8
- - 🎯 **Smart Element Selection**: Automatically finds and interacts with elements based on semantic understanding
9
- - 📝 **Gherkin-Style Syntax**: Write tests in natural language, one instruction per line
10
- - 🔄 **Multiple Action Types**: Supports navigation, clicks, form updates, and more
11
- - 🎭 **Playwright Integration**: Built on top of Playwright for reliable browser automation
12
- - 📊 **Token Tracking**: Built-in token usage tracking for AI model calls
13
-
14
- ## Installation
15
-
16
- ```bash
17
- npm install playwright-mimic
18
- # or
19
- pnpm install playwright-mimic
20
- # or
21
- yarn add playwright-mimic
22
- ```
23
-
24
- ## Prerequisites
25
-
26
- - Node.js 18+
27
- - Playwright installed in your project
28
- - An AI model provider (OpenAI, Ollama, or compatible provider from the `ai` SDK)
29
-
30
- ## Quick Start
31
-
32
- ### 1. Install Dependencies
33
-
34
- ```bash
35
- npm install @playwright/test playwright-mimic @ai-sdk/openai ai
36
- # or for Ollama
37
- npm install @playwright/test playwright-mimic ollama-ai-provider-v2 ai
38
- ```
39
-
40
- ### 2. Set Up Environment Variables
41
-
42
- Create a `.env` file in your project root:
43
-
44
- ```env
45
- OPENAI_API_KEY=your_openai_api_key_here
46
- # or for Ollama (if using local models)
47
- OLLAMA_BASE_URL=http://localhost:11434
48
- ```
49
-
50
- ### 3. Configure Playwright Fixtures
51
-
52
- Create a test utilities file (e.g., `test-utils.ts`):
53
-
54
- ```typescript
55
- import "dotenv/config";
56
- import { test as base } from '@playwright/test';
57
- import { createMimicry, type Mimicry } from 'playwright-mimic';
58
- import { openai } from '@ai-sdk/openai';
59
- // or for Ollama: import { ollama } from 'ollama-ai-provider-v2';
60
-
61
- // Configure your AI model
62
- const brains = openai('gpt-4o-mini');
63
- // or for Ollama: const brains = ollama('llama3.2') as LanguageModel;
64
-
65
- export * from '@playwright/test';
66
-
67
- // Extend Playwright's test with mimicry fixture
68
- export const test = base.extend<{
69
- mimicry: Mimicry
70
- }>({
71
- mimicry: async ({ page }, use, testInfo) => {
72
- const mimicry = createMimicry({
73
- page,
74
- brains,
75
- eyes: brains, // Can use a different model for visual analysis
76
- testInfo,
77
- });
78
- await use(mimicry);
79
- }
80
- });
81
- ```
82
-
83
- ### 4. Write Your First Test
84
-
85
- Create a test file (e.g., `example.spec.ts`):
86
-
87
- ```typescript
88
- import { test, expect } from './test-utils';
89
-
90
- test('navigate and interact with Playwright docs', async ({ page, mimicry }) => {
91
- await mimicry`
92
- navigate to https://playwright.dev/
93
- click on "get started"
94
- and click on "trace viewer"
95
- `;
96
-
97
- expect(page.url()).toBe('https://playwright.dev/docs/trace-viewer-intro');
98
-
99
- await mimicry`go back`;
100
-
101
- expect(page.url()).toBe('https://playwright.dev/docs/intro');
102
- });
103
- ```
104
-
105
- ### 5. Run Your Tests
106
-
107
- ```bash
108
- npx playwright test
109
- ```
110
-
111
- ## Usage
112
-
113
- ### Basic Syntax
114
-
115
- Mimicry uses a simple line-by-line syntax where each line represents a test step:
116
-
117
- ```typescript
118
- await mimicry`
119
- navigate to https://example.com
120
- click on "Sign In"
121
- type "username" into the email field
122
- type "password123" into the password field
123
- click on the submit button
124
- `;
125
- ```
126
-
127
- ### Supported Actions
128
-
129
- #### Navigation
130
-
131
- ```typescript
132
- await mimicry`
133
- navigate to https://example.com
134
- go back
135
- go forward
136
- refresh the page
137
- close the page
138
- `;
139
- ```
140
-
141
- #### Clicking Elements
142
-
143
- Mimicry can find elements by:
144
- - Visible text: `click on "Sign In"`
145
- - Button labels: `click on the submit button`
146
- - Link text: `click on "About Us"`
147
- - Semantic descriptions: `click on the login button in the header`
148
-
149
- ```typescript
150
- await mimicry`
151
- click on "Get Started"
152
- click on the search icon
153
- click on the menu button
154
- `;
155
- ```
156
-
157
- #### Form Interactions
158
-
159
- ```typescript
160
- await mimicry`
161
- type "john@example.com" into the email field
162
- fill the password field with "secret123"
163
- select "United States" from the country dropdown
164
- check the terms and conditions checkbox
165
- uncheck the newsletter checkbox
166
- `;
167
- ```
168
-
169
- ### Using Variables
170
-
171
- You can use template literals to inject variables:
172
-
173
- ```typescript
174
- const username = 'testuser';
175
- const password = 'testpass';
176
-
177
- await mimicry`
178
- type "${username}" into the username field
179
- type "${password}" into the password field
180
- click on "Login"
181
- `;
182
- ```
183
-
184
- ### Combining with Playwright Assertions
185
-
186
- Mimicry works seamlessly with Playwright's built-in assertions:
187
-
188
- ```typescript
189
- test('complete user registration', async ({ page, mimicry }) => {
190
- await mimicry`
191
- navigate to https://example.com/register
192
- type "John Doe" into the name field
193
- type "john@example.com" into the email field
194
- type "SecurePass123!" into the password field
195
- click on "Create Account"
196
- `;
197
-
198
- // Use Playwright assertions
199
- await expect(page.locator('text=Welcome')).toBeVisible();
200
- expect(page.url()).toContain('/dashboard');
201
- });
202
- ```
203
-
204
- ### Advanced: Direct API Usage
205
-
206
- If you need more control, you can use the `mimicry` function directly:
207
-
208
- ```typescript
209
- import { mimicry } from 'playwright-mimic';
210
- import { openai } from '@ai-sdk/openai';
211
- import { test } from '@playwright/test';
212
-
213
- test('custom usage', async ({ page, testInfo }) => {
214
- const brains = openai('gpt-4o-mini');
215
-
216
- await mimicry(
217
- 'navigate to https://example.com\nclick on "Get Started"',
218
- {
219
- page,
220
- brains,
221
- eyes: brains,
222
- testInfo,
223
- }
224
- );
225
- });
226
- ```
227
-
228
- ## API Reference
229
-
230
- ### `createMimicry(config)`
231
-
232
- Creates a mimicry function that can be used as a template literal tag.
233
-
234
- **Parameters:**
235
- - `config.page` (required): Playwright `Page` object
236
- - `config.brains` (required): Language model for reasoning (from `ai` SDK)
237
- - `config.eyes` (required): Language model for visual analysis (can be same as brains)
238
- - `config.testInfo` (optional): Playwright `TestInfo` object for test tracking
239
-
240
- **Returns:** A function that accepts template literals
241
-
242
- ### `mimicry(input, config)`
243
-
244
- Direct function call version.
245
-
246
- **Parameters:**
247
- - `input` (string): Newline-separated test steps
248
- - `config`: Same as `createMimicry`
249
-
250
- ### Exported Utilities
251
-
252
- You can also import individual utilities for custom implementations:
253
-
254
- ```typescript
255
- import {
256
- getBaseAction,
257
- getClickAction,
258
- executeClickAction,
259
- getNavigationAction,
260
- executeNavigationAction,
261
- getFormAction,
262
- executeFormAction,
263
- captureTargets,
264
- buildSelectorForTarget,
265
- } from 'playwright-mimic';
266
- ```
267
-
268
- ## Configuration
269
-
270
- ### AI Model Selection
271
-
272
- **OpenAI:**
273
- ```typescript
274
- import { openai } from '@ai-sdk/openai';
275
- const brains = openai('gpt-4o-mini'); // or 'gpt-4', 'gpt-4-turbo', etc.
276
- ```
277
-
278
- **Ollama (Local Models):**
279
- ```typescript
280
- import { ollama } from 'ollama-ai-provider-v2';
281
- const brains = ollama('llama3.2') as LanguageModel;
282
- ```
283
-
284
- **Different Models for Different Tasks:**
285
- ```typescript
286
- const brains = openai('gpt-4o-mini'); // For reasoning
287
- const eyes = openai('gpt-4-vision-preview'); // For visual analysis (if needed)
288
- ```
289
-
290
- ### Playwright Configuration
291
-
292
- Ensure your `playwright.config.ts` is set up correctly:
293
-
294
- ```typescript
295
- import { defineConfig } from '@playwright/test';
296
-
297
- export default defineConfig({
298
- testDir: './tests', // or wherever your tests are
299
- use: {
300
- trace: 'on-first-retry',
301
- },
302
- // ... other config
303
- });
304
- ```
305
-
306
- ## Best Practices
307
-
308
- ### 1. Use Descriptive Steps
309
-
310
- Be specific in your instructions:
311
-
312
- ```typescript
313
- // ✅ Good
314
- await mimicry`
315
- click on the "Sign In" button in the header
316
- type "admin@example.com" into the email input field
317
- `;
318
-
319
- // Less clear
320
- await mimicry`
321
- click button
322
- type email
323
- `;
324
- ```
325
-
326
- ### 2. Combine with Assertions
327
-
328
- Always verify the results:
329
-
330
- ```typescript
331
- await mimicry`
332
- navigate to /dashboard
333
- click on "Create Project"
334
- type "My Project" into the project name field
335
- click on "Save"
336
- `;
337
-
338
- await expect(page.locator('text=My Project')).toBeVisible();
339
- ```
340
-
341
- ### 3. Use Test Steps for Debugging
342
-
343
- Mimicry automatically creates Playwright test steps, making it easy to debug:
344
-
345
- ```typescript
346
- // Each line becomes a test step in Playwright's trace viewer
347
- await mimicry`
348
- navigate to https://example.com
349
- click on "Products"
350
- click on "View Details"
351
- `;
352
- ```
353
-
354
- ### 4. Handle Dynamic Content
355
-
356
- For dynamic content, combine mimicry with Playwright waits:
357
-
358
- ```typescript
359
- await mimicry`click on "Load More"`;
360
- await page.waitForSelector('text=New Content');
361
- await mimicry`click on "New Content"`;
362
- ```
363
-
364
- ### 5. Token Usage
365
-
366
- Mimicry tracks token usage automatically. Monitor your AI provider's usage to optimize costs:
367
-
368
- - Use smaller models (like `gpt-4o-mini`) for faster, cheaper tests
369
- - Use larger models only when needed for complex reasoning
370
-
371
- ## Troubleshooting
372
-
373
- ### Element Not Found
374
-
375
- If mimicry can't find an element, try:
376
- 1. Be more specific: `click on "Submit" button` instead of `click on "Submit"`
377
- 2. Use unique identifiers: `click on the login button with id "submit-btn"`
378
- 3. Check if the element is visible: Add a wait before the action
379
-
380
- ### Slow Execution
381
-
382
- AI model calls take time. To speed up:
383
- 1. Use faster models (e.g., `gpt-4o-mini` instead of `gpt-4`)
384
- 2. Batch related actions when possible
385
- 3. Use Playwright's native selectors for simple, stable elements
386
-
387
- ### API Key Issues
388
-
389
- Ensure your `.env` file is loaded:
390
- ```typescript
391
- import "dotenv/config"; // At the top of your test-utils.ts
392
- ```
393
-
394
- ## Examples
395
-
396
- ### E-commerce Checkout Flow
397
-
398
- ```typescript
399
- test('complete checkout process', async ({ page, mimicry }) => {
400
- await mimicry`
401
- navigate to https://store.example.com
402
- click on "Add to Cart" for "Product Name"
403
- click on the shopping cart icon
404
- click on "Proceed to Checkout"
405
- type "john@example.com" into the email field
406
- type "123 Main St" into the address field
407
- type "New York" into the city field
408
- select "United States" from the country dropdown
409
- type "10001" into the zip code field
410
- click on "Continue to Payment"
411
- type "4242 4242 4242 4242" into the card number field
412
- type "12/25" into the expiration field
413
- type "123" into the CVV field
414
- click on "Place Order"
415
- `;
416
-
417
- await expect(page.locator('text=Order Confirmed')).toBeVisible();
418
- });
419
- ```
420
-
421
- ### Form Validation Testing
422
-
423
- ```typescript
424
- test('validate required fields', async ({ page, mimicry }) => {
425
- await mimicry`
426
- navigate to https://example.com/contact
427
- click on "Submit" without filling fields
428
- `;
429
-
430
- await expect(page.locator('text=Email is required')).toBeVisible();
431
- await expect(page.locator('text=Name is required')).toBeVisible();
432
- });
433
- ```
434
-
435
- ## Contributing
436
-
437
- Contributions are welcome! Please feel free to submit a Pull Request.
438
-
439
- ## License
440
-
441
- ISC
442
-
443
- ## Support
444
-
445
- For issues, questions, or contributions, please open an issue on the GitHub repository.
446
-
1
+ # Mimic
2
+
3
+ **Mimic** is an AI-powered browser testing framework that converts Gherkin or plain language tests into executable code, with self-repair capabilities when tests break due to code changes.
4
+
5
+ > Mimic learns how your app works, remembers what succeeds, repeats it reliably — and only thinks again when something breaks.
6
+
7
+ ## Features
8
+
9
+ - 🤖 **AI-Powered Conversion**: Uses language models to understand and execute natural language test instructions
10
+ - 🎯 **Smart Element Selection**: Automatically finds and interacts with elements based on semantic understanding
11
+ - 📝 **Gherkin-Style Syntax**: Write tests in natural language, one instruction per line
12
+ - 🔄 **Self-Repair Capability**: Automatically repairs broken tests when application code changes
13
+ - 🎭 **Playwright Integration**: Built on top of Playwright for reliable browser automation
14
+ - 📊 **Token Tracking**: Built-in token usage tracking for AI model calls
15
+ - 💾 **Snapshot Storage**: Automatically saves and replays successful test executions
16
+ - 🎯 **Best Selector System**: Stores optimal selectors (role, label, testid) with fallback to stable marker IDs
17
+
18
+ ## How It Works
19
+
20
+ Mimic follows a simple, human-readable lifecycle:
21
+
22
+ **Learn → Remember → Repeat → Troubleshoot & Fix**
23
+
24
+ AI is used to learn and adapt — not to waste tokens repeating work it has already done.
25
+
26
+ ### 1. Learn — Understand the Intent
27
+
28
+ You write your test in plain English or Gherkin-style steps:
29
+
30
+ ```typescript
31
+ await mimic`
32
+ navigate to https://playwright.dev/
33
+ click on "get started"
34
+ and click on "trace viewer"
35
+ `;
36
+ ```
37
+
38
+ During **Learn**, Mimic:
39
+
40
+ - **Dynamically injects marker code** into the page to assign `data-mimic-id` attributes to elements, making identification much easier
41
+ - Uses an AI model to:
42
+ - Interpret your intent
43
+ - Reason about the structure and semantics of the page
44
+ - Identify the most likely elements to interact with
45
+ - Generate executable Playwright steps
46
+
47
+ This is the most flexible phase — it's where Mimic figures out what you meant, not just what to click. The marker injection happens automatically and transparently — no changes to your application code are needed.
48
+
49
+ ### 2. Remember — Capture a Verified Recording
50
+
51
+ Once the test runs successfully, Mimic remembers what worked.
52
+
53
+ It stores a verified recording (snapshot) of the execution, including:
54
+
55
+ - The resolved interaction steps with full action details
56
+ - **Best selector descriptors** for each element (role, label, testid, etc.) — not just marker IDs
57
+ - Element identification data and positioning information
58
+ - Context needed to reliably repeat the behavior
59
+ - Timestamps and execution metadata
60
+
61
+ The storage system automatically saves snapshots to `<testfile-name>.mimic.json` files alongside your test files. These snapshots contain:
62
+ - **SelectorDescriptor objects**: The best available selector for each element (e.g., `getByRole('button', { name: 'Submit' })`)
63
+ - **Mimic IDs**: Fallback identifiers using dynamically injected `data-mimic-id` attributes (these are automatically added to page elements at runtime)
64
+ - **Action results**: Complete details of what action was performed and how
65
+
66
+ You can review the execution (for example, via Playwright's video output) to confirm it behaves exactly as expected. Once verified, this recording becomes the trusted reference for future runs.
67
+
68
+ > **Note**: The storage system is actively being refined to improve selector stability and snapshot reliability.
69
+
70
+ ### 3. Repeat — Fast, Deterministic Execution
71
+
72
+ On subsequent runs, Mimic simply repeats the recorded behavior using stored snapshots.
73
+
74
+ In this phase:
75
+
76
+ - No AI calls are made
77
+ - Token usage drops to near zero
78
+ - Tests run faster and more deterministically
79
+ - Behavior is repeatable because it's based on a known-good run
80
+ - **Selector reconstruction**: Uses stored `SelectorDescriptor` objects to rebuild locators, falling back to mimic IDs if needed
81
+
82
+ The replay system:
83
+ 1. Loads the snapshot from the `.mimic.json` file
84
+ 2. Dynamically injects marker code to assign `data-mimic-id` attributes to page elements
85
+ 3. Reconstructs locators from stored selector descriptors (e.g., `getByRole('button', { name: 'Submit' })`)
86
+ 4. Executes actions directly without AI analysis
87
+ 5. Falls back to dynamically injected `data-mimic-id` markers if selectors become stale
88
+
89
+ As long as the application hasn't changed in a way that breaks the test, Mimic stays in Repeat mode.
90
+
91
+ ### 4. Troubleshoot & Fix — Adapt When Things Change
92
+
93
+ When a test can no longer repeat successfully — due to UI or structural changes — Mimic detects the failure and switches back into reasoning mode.
94
+
95
+ During **Troubleshoot & Fix**, Mimic:
96
+
97
+ - Analyzes what failed and why
98
+ - Re-learns the updated application structure
99
+ - Repairs or regenerates the broken steps
100
+ - Saves a new verified recording
101
+
102
+ Once repaired and validated, the test returns to Repeat mode — stable, fast, and low-cost again.
103
+
104
+ ### The Full Loop
105
+
106
+ **Learn → Remember → Repeat → Troubleshoot & Fix → Repeat**
107
+
108
+ AI is invoked only when something is new or broken.
109
+ Everything else runs on verified knowledge.
110
+
111
+ ## Architecture
112
+
113
+ Built on top of Playwright with AI model integration for natural language processing and test repair. Converts plain language or Gherkin syntax into executable Playwright test code, then monitors test execution to detect failures and automatically repair broken tests when application code changes.
114
+
115
+ ### Element Identification System
116
+
117
+ Mimic uses a sophisticated element identification system:
118
+
119
+ - **Dynamic Marker Injection**: Automatically injects `data-mimic-id` attributes into page elements at runtime. These stable identifiers are added dynamically to help identify elements more reliably, without requiring any manual changes to your application code.
120
+ - **Best Selector Generation**: Generates optimal selectors using Playwright's semantic locators:
121
+ - `getByRole()` for ARIA roles
122
+ - `getByLabel()` for form labels
123
+ - `getByTestId()` for test IDs
124
+ - `getByText()` for visible text
125
+ - CSS selectors as fallback
126
+ - **Snapshot Storage**: Stores `SelectorDescriptor` objects (JSON-serializable) in snapshots for fast replay
127
+ - **Dual Fallback**: Uses best selector first, falls back to marker ID if selector becomes stale
128
+
129
+ The marker system works entirely behind the scenes — Mimic dynamically loads marker code into the page to assign stable `data-mimic-id` attributes to interactive, display, and structural elements. This makes element identification much easier overall, without requiring any modifications to your application.
130
+
131
+ This ensures tests remain stable even when DOM structure changes, while preferring semantic selectors over brittle CSS paths.
132
+
133
+ ### Technology Stack
134
+
135
+ - **TypeScript**
136
+ - **Node.js**
137
+ - **Playwright**
138
+
139
+ ## Installation
140
+
141
+ ```bash
142
+ npm install playwright-mimic
143
+ # or
144
+ pnpm install playwright-mimic
145
+ # or
146
+ yarn add playwright-mimic
147
+ ```
148
+
149
+ ## Prerequisites
150
+
151
+ - Node.js 18+
152
+ - Playwright installed in your project
153
+ - An AI model provider (OpenAI, Ollama, or compatible provider from the `ai` SDK)
154
+
155
+ ## Quick Start
156
+
157
+ ### 1. Install Dependencies
158
+
159
+ ```bash
160
+ npm install @playwright/test playwright-mimic @ai-sdk/openai ai
161
+ # or for Ollama
162
+ npm install @playwright/test playwright-mimic ollama-ai-provider-v2 ai
163
+ ```
164
+
165
+ ### 2. Set Up Environment Variables
166
+
167
+ Create a `.env` file in your project root:
168
+
169
+ ```env
170
+ OPENAI_API_KEY=your_openai_api_key_here
171
+ # or for Ollama (if using local models)
172
+ OLLAMA_BASE_URL=http://localhost:11434
173
+ ```
174
+
175
+ ### 3. Configure Playwright Fixtures
176
+
177
+ Create a test utilities file (e.g., `test-utils.ts`):
178
+
179
+ ```typescript
180
+ import "dotenv/config";
181
+ import { test as base } from '@playwright/test';
182
+ import { createMimic, type Mimic } from 'playwright-mimic';
183
+ import { openai } from '@ai-sdk/openai';
184
+ // or for Ollama: import { ollama } from 'ollama-ai-provider-v2';
185
+
186
+ // Configure your AI model
187
+ const brains = openai('gpt-4o-mini');
188
+ // or for Ollama: const brains = ollama('llama3.2') as LanguageModel;
189
+
190
+ export * from '@playwright/test';
191
+
192
+ // Extend Playwright's test with mimic fixture
193
+ export const test = base.extend<{
194
+ mimic: Mimic
195
+ }>({
196
+ mimic: async ({ page }, use, testInfo) => {
197
+ const mimic = createMimic({
198
+ page,
199
+ brains,
200
+ eyes: brains, // Can use a different model for visual analysis
201
+ testInfo,
202
+ });
203
+ await use(mimic);
204
+ }
205
+ });
206
+ ```
207
+
208
+ ### 4. Write Your First Test
209
+
210
+ Create a test file (e.g., `example.spec.ts`):
211
+
212
+ ```typescript
213
+ import { test, expect } from './test-utils';
214
+
215
+ test('navigate and interact with Playwright docs', async ({ page, mimic }) => {
216
+ await mimic`
217
+ navigate to https://playwright.dev/
218
+ click on "get started"
219
+ and click on "trace viewer"
220
+ `;
221
+
222
+ expect(page.url()).toBe('https://playwright.dev/docs/trace-viewer-intro');
223
+
224
+ await mimic`go back`;
225
+
226
+ expect(page.url()).toBe('https://playwright.dev/docs/intro');
227
+ });
228
+ ```
229
+
230
+ ### 5. Run Your Tests
231
+
232
+ ```bash
233
+ npx playwright test
234
+ ```
235
+
236
+ ## Usage
237
+
238
+ ### Basic Syntax
239
+
240
+ Mimic uses a simple line-by-line syntax where each line represents a test step:
241
+
242
+ ```typescript
243
+ await mimic`
244
+ navigate to https://example.com
245
+ click on "Sign In"
246
+ type "username" into the email field
247
+ type "password123" into the password field
248
+ click on the submit button
249
+ `;
250
+ ```
251
+
252
+ ### Supported Actions
253
+
254
+ #### Navigation
255
+
256
+ ```typescript
257
+ await mimic`
258
+ navigate to https://example.com
259
+ go back
260
+ go forward
261
+ refresh the page
262
+ close the page
263
+ `;
264
+ ```
265
+
266
+ #### Clicking Elements
267
+
268
+ Mimic can find elements by:
269
+ - Visible text: `click on "Sign In"`
270
+ - Button labels: `click on the submit button`
271
+ - Link text: `click on "About Us"`
272
+ - Semantic descriptions: `click on the login button in the header`
273
+
274
+ ```typescript
275
+ await mimic`
276
+ click on "Get Started"
277
+ click on the search icon
278
+ click on the menu button
279
+ `;
280
+ ```
281
+
282
+ #### Form Interactions
283
+
284
+ ```typescript
285
+ await mimic`
286
+ type "john@example.com" into the email field
287
+ fill the password field with "secret123"
288
+ select "United States" from the country dropdown
289
+ check the terms and conditions checkbox
290
+ uncheck the newsletter checkbox
291
+ `;
292
+ ```
293
+
294
+ ### Using Variables
295
+
296
+ You can use template literals to inject variables:
297
+
298
+ ```typescript
299
+ const username = 'testuser';
300
+ const password = 'testpass';
301
+
302
+ await mimic`
303
+ type "${username}" into the username field
304
+ type "${password}" into the password field
305
+ click on "Login"
306
+ `;
307
+ ```
308
+
309
+ ### Combining with Playwright Assertions
310
+
311
+ Mimic works seamlessly with Playwright's built-in assertions:
312
+
313
+ ```typescript
314
+ test('complete user registration', async ({ page, mimic }) => {
315
+ await mimic`
316
+ navigate to https://example.com/register
317
+ type "John Doe" into the name field
318
+ type "john@example.com" into the email field
319
+ type "SecurePass123!" into the password field
320
+ click on "Create Account"
321
+ `;
322
+
323
+ // Use Playwright assertions
324
+ await expect(page.locator('text=Welcome')).toBeVisible();
325
+ expect(page.url()).toContain('/dashboard');
326
+ });
327
+ ```
328
+
329
+ ### Advanced: Direct API Usage
330
+
331
+ If you need more control, you can use the `mimic` function directly:
332
+
333
+ ```typescript
334
+ import { mimic } from 'playwright-mimic';
335
+ import { openai } from '@ai-sdk/openai';
336
+ import { test } from '@playwright/test';
337
+
338
+ test('custom usage', async ({ page, testInfo }) => {
339
+ const brains = openai('gpt-4o-mini');
340
+
341
+ await mimic(
342
+ 'navigate to https://example.com\nclick on "Get Started"',
343
+ {
344
+ page,
345
+ brains,
346
+ eyes: brains,
347
+ testInfo,
348
+ }
349
+ );
350
+ });
351
+ ```
352
+
353
+ ## API Reference
354
+
355
+ ### `createMimic(config)`
356
+
357
+ Creates a mimic function that can be used as a template literal tag.
358
+
359
+ **Parameters:**
360
+ - `config.page` (required): Playwright `Page` object
361
+ - `config.brains` (required): Language model for reasoning (from `ai` SDK)
362
+ - `config.eyes` (required): Language model for visual analysis (can be same as brains)
363
+ - `config.testInfo` (optional): Playwright `TestInfo` object for test tracking
364
+
365
+ **Returns:** A function that accepts template literals
366
+
367
+ ### `mimic(input, config)`
368
+
369
+ Direct function call version.
370
+
371
+ **Parameters:**
372
+ - `input` (string): Newline-separated test steps
373
+ - `config`: Same as `createMimic`
374
+
375
+ ### Exported Utilities
376
+
377
+ You can also import individual utilities for custom implementations:
378
+
379
+ ```typescript
380
+ import {
381
+ getBaseAction,
382
+ getClickAction,
383
+ executeClickAction,
384
+ getNavigationAction,
385
+ executeNavigationAction,
386
+ getFormAction,
387
+ executeFormAction,
388
+ captureTargets,
389
+ buildSelectorForTarget,
390
+ } from 'playwright-mimic';
391
+ ```
392
+
393
+ ## Snapshot Files
394
+
395
+ Mimic automatically creates snapshot files (`.mimic.json`) in `__mimic__/` directories alongside your test files. These files contain:
396
+
397
+ - **Test hash**: Unique identifier for the test
398
+ - **Steps**: Array of executed steps with:
399
+ - Step text and hash
400
+ - Action details (navigation, click, form)
401
+ - **Target element**: Contains `SelectorDescriptor` (primary) and `mimicId` (fallback)
402
+ - Execution timestamp
403
+ - **Flags**: Metadata about the snapshot (needsRetry, hasErrors, etc.)
404
+
405
+ ### Example Snapshot Structure
406
+
407
+ ```json
408
+ {
409
+ "testHash": "abc123...",
410
+ "testText": "click on \"Submit\"\nfill the email field with \"test@example.com\"",
411
+ "steps": [
412
+ {
413
+ "stepHash": "def456...",
414
+ "stepIndex": 0,
415
+ "stepText": "click on \"Submit\"",
416
+ "actionKind": "click",
417
+ "actionDetails": { ... },
418
+ "targetElement": {
419
+ "selector": {
420
+ "type": "role",
421
+ "role": "button",
422
+ "name": "Submit"
423
+ },
424
+ "mimicId": 42
425
+ },
426
+ "executedAt": "2024-01-01T12:00:00.000Z"
427
+ }
428
+ ],
429
+ "flags": { ... }
430
+ }
431
+ ```
432
+
433
+ The snapshot system is actively being refined to improve selector stability and reliability.
434
+
435
+ **Note**: The `mimicId` values in snapshots reference `data-mimic-id` attributes that are dynamically injected into the page by Mimic at runtime. These markers are automatically assigned to elements to help with identification — you don't need to add them to your application code.
436
+
437
+ ## Configuration
438
+
439
+ ### AI Model Selection
440
+
441
+ **OpenAI:**
442
+ ```typescript
443
+ import { openai } from '@ai-sdk/openai';
444
+ const brains = openai('gpt-4o-mini'); // or 'gpt-4', 'gpt-4-turbo', etc.
445
+ ```
446
+
447
+ **Ollama (Local Models):**
448
+ ```typescript
449
+ import { ollama } from 'ollama-ai-provider-v2';
450
+ const brains = ollama('llama3.2') as LanguageModel;
451
+ ```
452
+
453
+ **Different Models for Different Tasks:**
454
+ ```typescript
455
+ const brains = openai('gpt-4o-mini'); // For reasoning
456
+ const eyes = openai('gpt-4-vision-preview'); // For visual analysis (if needed)
457
+ ```
458
+
459
+ ### Playwright Configuration
460
+
461
+ Ensure your `playwright.config.ts` is set up correctly:
462
+
463
+ ```typescript
464
+ import { defineConfig } from '@playwright/test';
465
+
466
+ export default defineConfig({
467
+ testDir: './tests', // or wherever your tests are
468
+ use: {
469
+ trace: 'on-first-retry',
470
+ },
471
+ // ... other config
472
+ });
473
+ ```
474
+
475
+ ## Best Practices
476
+
477
+ ### 1. Use Descriptive Steps
478
+
479
+ Be specific in your instructions:
480
+
481
+ ```typescript
482
+ // ✅ Good
483
+ await mimic`
484
+ click on the "Sign In" button in the header
485
+ type "admin@example.com" into the email input field
486
+ `;
487
+
488
+ // ❌ Less clear
489
+ await mimic`
490
+ click button
491
+ type email
492
+ `;
493
+ ```
494
+
495
+ ### 2. Combine with Assertions
496
+
497
+ Always verify the results:
498
+
499
+ ```typescript
500
+ await mimic`
501
+ navigate to /dashboard
502
+ click on "Create Project"
503
+ type "My Project" into the project name field
504
+ click on "Save"
505
+ `;
506
+
507
+ await expect(page.locator('text=My Project')).toBeVisible();
508
+ ```
509
+
510
+ ### 3. Use Test Steps for Debugging
511
+
512
+ Mimic automatically creates Playwright test steps, making it easy to debug:
513
+
514
+ ```typescript
515
+ // Each line becomes a test step in Playwright's trace viewer
516
+ await mimic`
517
+ navigate to https://example.com
518
+ click on "Products"
519
+ click on "View Details"
520
+ `;
521
+ ```
522
+
523
+ ### 4. Handle Dynamic Content
524
+
525
+ For dynamic content, combine mimic with Playwright waits:
526
+
527
+ ```typescript
528
+ await mimic`click on "Load More"`;
529
+ await page.waitForSelector('text=New Content');
530
+ await mimic`click on "New Content"`;
531
+ ```
532
+
533
+ ### 5. Token Usage
534
+
535
+ Mimic tracks token usage automatically. Monitor your AI provider's usage to optimize costs:
536
+
537
+ - Use smaller models (like `gpt-4o-mini`) for faster, cheaper tests
538
+ - Use larger models only when needed for complex reasoning
539
+
540
+ ## Troubleshooting
541
+
542
+ ### Element Not Found
543
+
544
+ If mimic can't find an element, try:
545
+ 1. Be more specific: `click on "Submit" button` instead of `click on "Submit"`
546
+ 2. Use unique identifiers: `click on the login button with id "submit-btn"`
547
+ 3. Check if the element is visible: Add a wait before the action
548
+ 4. **Check snapshots**: If a test was previously working, check the `.mimic.json` snapshot file to see what selector was used
549
+
550
+ ### Slow Execution
551
+
552
+ AI model calls take time. To speed up:
553
+ 1. Use faster models (e.g., `gpt-4o-mini` instead of `gpt-4`)
554
+ 2. Batch related actions when possible
555
+ 3. Use Playwright's native selectors for simple, stable elements
556
+ 4. **Leverage snapshots**: Once a test passes, subsequent runs use snapshots and skip AI calls entirely
557
+
558
+ ### Snapshot Issues
559
+
560
+ If snapshots aren't working as expected:
561
+ 1. Check that `.mimic.json` files are being created in `__mimic__/` directories
562
+ 2. Verify selector descriptors in snapshots are valid
563
+ 3. If selectors become stale, Mimic will automatically fall back to marker IDs
564
+ 4. Delete the snapshot file to force regeneration if needed
565
+
566
+ ### Storage System
567
+
568
+ The snapshot storage system is actively being refined. Current capabilities:
569
+ - ✅ Automatic snapshot creation on successful test runs
570
+ - ✅ Selector descriptor storage with fallback to marker IDs
571
+ - ✅ Fast replay without AI calls
572
+ - 🔄 Ongoing refinement for improved stability and reliability
573
+
574
+ ### API Key Issues
575
+
576
+ Ensure your `.env` file is loaded:
577
+ ```typescript
578
+ import "dotenv/config"; // At the top of your test-utils.ts
579
+ ```
580
+
581
+ ## Examples
582
+
583
+ ### E-commerce Checkout Flow
584
+
585
+ ```typescript
586
+ test('complete checkout process', async ({ page, mimic }) => {
587
+ await mimic`
588
+ navigate to https://store.example.com
589
+ click on "Add to Cart" for "Product Name"
590
+ click on the shopping cart icon
591
+ click on "Proceed to Checkout"
592
+ type "john@example.com" into the email field
593
+ type "123 Main St" into the address field
594
+ type "New York" into the city field
595
+ select "United States" from the country dropdown
596
+ type "10001" into the zip code field
597
+ click on "Continue to Payment"
598
+ type "4242 4242 4242 4242" into the card number field
599
+ type "12/25" into the expiration field
600
+ type "123" into the CVV field
601
+ click on "Place Order"
602
+ `;
603
+
604
+ await expect(page.locator('text=Order Confirmed')).toBeVisible();
605
+ });
606
+ ```
607
+
608
+ ### Form Validation Testing
609
+
610
+ ```typescript
611
+ test('validate required fields', async ({ page, mimic }) => {
612
+ await mimic`
613
+ navigate to https://example.com/contact
614
+ click on "Submit" without filling fields
615
+ `;
616
+
617
+ await expect(page.locator('text=Email is required')).toBeVisible();
618
+ await expect(page.locator('text=Name is required')).toBeVisible();
619
+ });
620
+ ```
621
+
622
+ ## Contributing
623
+
624
+ Contributions are welcome! Please feel free to submit a Pull Request.
625
+
626
+ ## License
627
+
628
+ ISC
629
+
630
+ ## Support
631
+
632
+ For issues, questions, or contributions, please open an issue on the GitHub repository.
633
+