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/README.md
CHANGED
|
@@ -1,446 +1,633 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
##
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
await
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
###
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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
|
+
|