@browserflow-ai/generator 0.0.6

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 (41) hide show
  1. package/dist/config-emit.d.ts +41 -0
  2. package/dist/config-emit.d.ts.map +1 -0
  3. package/dist/config-emit.js +191 -0
  4. package/dist/config-emit.js.map +1 -0
  5. package/dist/index.d.ts +16 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +15 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/locator-emit.d.ts +76 -0
  10. package/dist/locator-emit.d.ts.map +1 -0
  11. package/dist/locator-emit.js +239 -0
  12. package/dist/locator-emit.js.map +1 -0
  13. package/dist/locator-emit.test.d.ts +6 -0
  14. package/dist/locator-emit.test.d.ts.map +1 -0
  15. package/dist/locator-emit.test.js +425 -0
  16. package/dist/locator-emit.test.js.map +1 -0
  17. package/dist/playwright-ts.d.ts +97 -0
  18. package/dist/playwright-ts.d.ts.map +1 -0
  19. package/dist/playwright-ts.js +373 -0
  20. package/dist/playwright-ts.js.map +1 -0
  21. package/dist/playwright-ts.test.d.ts +6 -0
  22. package/dist/playwright-ts.test.d.ts.map +1 -0
  23. package/dist/playwright-ts.test.js +548 -0
  24. package/dist/playwright-ts.test.js.map +1 -0
  25. package/dist/visual-checks.d.ts +76 -0
  26. package/dist/visual-checks.d.ts.map +1 -0
  27. package/dist/visual-checks.js +195 -0
  28. package/dist/visual-checks.js.map +1 -0
  29. package/dist/visual-checks.test.d.ts +6 -0
  30. package/dist/visual-checks.test.d.ts.map +1 -0
  31. package/dist/visual-checks.test.js +188 -0
  32. package/dist/visual-checks.test.js.map +1 -0
  33. package/package.json +34 -0
  34. package/src/config-emit.ts +253 -0
  35. package/src/index.ts +57 -0
  36. package/src/locator-emit.test.ts +533 -0
  37. package/src/locator-emit.ts +310 -0
  38. package/src/playwright-ts.test.ts +704 -0
  39. package/src/playwright-ts.ts +519 -0
  40. package/src/visual-checks.test.ts +232 -0
  41. package/src/visual-checks.ts +294 -0
@@ -0,0 +1,548 @@
1
+ /**
2
+ * playwright-ts.test.ts
3
+ * Tests for the Playwright test generator.
4
+ */
5
+ import { describe, it, expect } from 'bun:test';
6
+ import { PlaywrightGenerator, generateTest } from './playwright-ts.js';
7
+ /**
8
+ * Creates a minimal ExplorationLockfile for testing.
9
+ */
10
+ function createMockLockfile(overrides = {}) {
11
+ return {
12
+ spec: 'test-spec',
13
+ spec_path: 'specs/test-spec.yaml',
14
+ exploration_id: 'exp-123',
15
+ timestamp: '2026-01-15T10:00:00Z',
16
+ duration_ms: 5000,
17
+ browser: 'chromium',
18
+ viewport: { width: 1280, height: 720 },
19
+ base_url: 'http://localhost:3000',
20
+ steps: [],
21
+ outcome_checks: [],
22
+ overall_status: 'completed',
23
+ errors: [],
24
+ ...overrides,
25
+ };
26
+ }
27
+ /**
28
+ * Creates a minimal ExplorationStep for testing.
29
+ */
30
+ function createMockStep(action, execution = {}) {
31
+ return {
32
+ step_index: 0,
33
+ spec_action: action,
34
+ execution: {
35
+ status: 'completed',
36
+ duration_ms: 100,
37
+ ...execution,
38
+ },
39
+ screenshots: {},
40
+ };
41
+ }
42
+ /**
43
+ * Creates a minimal ReviewData for testing.
44
+ */
45
+ function createMockReview(overrides = {}) {
46
+ return {
47
+ exploration_id: 'exp-123',
48
+ started_at: '2026-01-15T10:00:00Z',
49
+ updated_at: '2026-01-15T12:00:00Z',
50
+ steps: [],
51
+ verdict: 'approved',
52
+ ...overrides,
53
+ };
54
+ }
55
+ describe('PlaywrightGenerator', () => {
56
+ describe('generate()', () => {
57
+ it('generates valid TypeScript test structure', () => {
58
+ const lockfile = createMockLockfile();
59
+ const generator = new PlaywrightGenerator();
60
+ const result = generator.generate(lockfile);
61
+ expect(result.content).toContain("import { test, expect } from '@playwright/test'");
62
+ expect(result.content).toContain("test.describe('test-spec'");
63
+ expect(result.content).toContain("test('Test Spec'");
64
+ expect(result.content).toContain('async ({ page })');
65
+ });
66
+ it('includes generation metadata in header', () => {
67
+ const lockfile = createMockLockfile({
68
+ exploration_id: 'exp-abc123',
69
+ spec: 'checkout-cart',
70
+ spec_path: 'specs/checkout-cart.yaml',
71
+ });
72
+ const generator = new PlaywrightGenerator();
73
+ const result = generator.generate(lockfile);
74
+ expect(result.content).toContain('BrowserFlow Generated Test: checkout-cart');
75
+ expect(result.content).toContain('Spec: specs/checkout-cart.yaml');
76
+ expect(result.content).toContain('Exploration: exp-abc123');
77
+ expect(result.content).toContain('Generated:');
78
+ });
79
+ it('includes reviewer info when provided', () => {
80
+ const lockfile = createMockLockfile();
81
+ const generator = new PlaywrightGenerator();
82
+ const result = generator.generate(lockfile, createMockReview({
83
+ reviewer: 'john.doe',
84
+ submitted_at: '2026-01-15T12:00:00Z',
85
+ }));
86
+ expect(result.content).toContain('Approved by: john.doe @ 2026-01-15T12:00:00Z');
87
+ });
88
+ });
89
+ describe('test.step() wrapping', () => {
90
+ it('wraps click action in test.step()', () => {
91
+ const lockfile = createMockLockfile({
92
+ steps: [
93
+ createMockStep({ action: 'click', query: 'Add to Cart button' }, {
94
+ locator: { method: 'getByTestId', args: { testId: 'add-to-cart' } },
95
+ }),
96
+ ],
97
+ });
98
+ const generator = new PlaywrightGenerator();
99
+ const result = generator.generate(lockfile);
100
+ expect(result.content).toContain("await test.step('step_0'");
101
+ expect(result.content).toContain("await page.getByTestId('add-to-cart').click()");
102
+ });
103
+ it('wraps fill action in test.step()', () => {
104
+ const lockfile = createMockLockfile({
105
+ steps: [
106
+ createMockStep({ action: 'fill', query: 'Email input', value: 'test@example.com' }, {
107
+ locator: { method: 'getByLabel', args: { text: 'Email' } },
108
+ value_used: 'test@example.com',
109
+ }),
110
+ ],
111
+ });
112
+ const generator = new PlaywrightGenerator();
113
+ const result = generator.generate(lockfile);
114
+ expect(result.content).toContain("await test.step('step_0'");
115
+ expect(result.content).toContain("await page.getByLabel('Email').fill('test@example.com')");
116
+ });
117
+ it('wraps navigate action in test.step()', () => {
118
+ const lockfile = createMockLockfile({
119
+ steps: [createMockStep({ action: 'navigate', to: '/products' })],
120
+ });
121
+ const generator = new PlaywrightGenerator();
122
+ const result = generator.generate(lockfile);
123
+ expect(result.content).toContain("await test.step('step_0'");
124
+ expect(result.content).toContain("await page.goto('/products')");
125
+ });
126
+ it('wraps wait action in test.step()', () => {
127
+ const lockfile = createMockLockfile({
128
+ steps: [createMockStep({ action: 'wait', for: 'text', text: 'Success' })],
129
+ });
130
+ const generator = new PlaywrightGenerator();
131
+ const result = generator.generate(lockfile);
132
+ expect(result.content).toContain("await test.step('step_0'");
133
+ expect(result.content).toContain("page.getByText('Success').waitFor");
134
+ });
135
+ it('uses step description as test.step name when available', () => {
136
+ const lockfile = createMockLockfile({
137
+ steps: [
138
+ createMockStep({ action: 'click', query: 'Submit', description: 'submit_form' }, { locator: { selector: 'button[type=submit]' } }),
139
+ ],
140
+ });
141
+ const generator = new PlaywrightGenerator();
142
+ const result = generator.generate(lockfile);
143
+ expect(result.content).toContain("await test.step('submit_form'");
144
+ });
145
+ it('generates multiple test.step() calls for multiple steps', () => {
146
+ const lockfile = createMockLockfile({
147
+ steps: [
148
+ createMockStep({ action: 'navigate', to: '/' }, {}),
149
+ createMockStep({ action: 'click', query: 'Login button' }, { locator: { selector: 'button.login' } }),
150
+ createMockStep({ action: 'fill', query: 'Username', value: 'user' }, {
151
+ locator: { method: 'getByLabel', args: { text: 'Username' } },
152
+ value_used: 'user',
153
+ }),
154
+ ],
155
+ });
156
+ lockfile.steps[1].step_index = 1;
157
+ lockfile.steps[2].step_index = 2;
158
+ const generator = new PlaywrightGenerator();
159
+ const result = generator.generate(lockfile);
160
+ expect(result.content).toContain("await test.step('step_0'");
161
+ expect(result.content).toContain("await test.step('step_1'");
162
+ expect(result.content).toContain("await test.step('step_2'");
163
+ });
164
+ it('includes comments inside test.step()', () => {
165
+ const lockfile = createMockLockfile({
166
+ steps: [
167
+ createMockStep({ action: 'click', query: 'Add to Cart button on first product' }, { locator: { selector: 'button.add-to-cart' }, method: 'css' }),
168
+ ],
169
+ });
170
+ const generator = new PlaywrightGenerator({ includeComments: true });
171
+ const result = generator.generate(lockfile);
172
+ expect(result.content).toContain('// Step 0: Click');
173
+ });
174
+ it('respects includeComments: false option', () => {
175
+ const lockfile = createMockLockfile({
176
+ steps: [
177
+ createMockStep({ action: 'click', query: 'Button' }, { locator: { selector: 'button' } }),
178
+ ],
179
+ });
180
+ const generator = new PlaywrightGenerator({ includeComments: false });
181
+ const result = generator.generate(lockfile);
182
+ expect(result.content).not.toContain('// Step 0');
183
+ });
184
+ });
185
+ describe('action types', () => {
186
+ it('generates click action code', () => {
187
+ const lockfile = createMockLockfile({
188
+ steps: [
189
+ createMockStep({ action: 'click' }, { locator: { method: 'getByRole', args: { role: 'button', name: 'Submit' } } }),
190
+ ],
191
+ });
192
+ const generator = new PlaywrightGenerator();
193
+ const result = generator.generate(lockfile);
194
+ expect(result.content).toContain("page.getByRole('button', { name: 'Submit' }).click()");
195
+ });
196
+ it('generates navigate action code', () => {
197
+ const lockfile = createMockLockfile({
198
+ steps: [createMockStep({ action: 'navigate', to: '/dashboard' })],
199
+ });
200
+ const generator = new PlaywrightGenerator();
201
+ const result = generator.generate(lockfile);
202
+ expect(result.content).toContain("await page.goto('/dashboard')");
203
+ });
204
+ it('generates fill action code', () => {
205
+ const lockfile = createMockLockfile({
206
+ steps: [
207
+ createMockStep({ action: 'fill', value: 'test@email.com' }, {
208
+ locator: { method: 'getByPlaceholder', args: { text: 'Email' } },
209
+ value_used: 'test@email.com',
210
+ }),
211
+ ],
212
+ });
213
+ const generator = new PlaywrightGenerator();
214
+ const result = generator.generate(lockfile);
215
+ expect(result.content).toContain("page.getByPlaceholder('Email').fill('test@email.com')");
216
+ });
217
+ it('generates type action code with pressSequentially', () => {
218
+ const lockfile = createMockLockfile({
219
+ steps: [
220
+ createMockStep({ action: 'type', value: 'search term' }, {
221
+ locator: { selector: 'input.search' },
222
+ value_used: 'search term',
223
+ }),
224
+ ],
225
+ });
226
+ const generator = new PlaywrightGenerator();
227
+ const result = generator.generate(lockfile);
228
+ expect(result.content).toContain("pressSequentially('search term')");
229
+ });
230
+ it('generates type action with pressEnter', () => {
231
+ const lockfile = createMockLockfile({
232
+ steps: [
233
+ createMockStep({ action: 'type', value: 'query', pressEnter: true }, { locator: { selector: 'input' }, value_used: 'query' }),
234
+ ],
235
+ });
236
+ const generator = new PlaywrightGenerator();
237
+ const result = generator.generate(lockfile);
238
+ expect(result.content).toContain("pressSequentially('query')");
239
+ expect(result.content).toContain("press('Enter')");
240
+ });
241
+ it('generates wait for element code', () => {
242
+ const lockfile = createMockLockfile({
243
+ steps: [createMockStep({ action: 'wait', for: 'element', selector: '.modal' })],
244
+ });
245
+ const generator = new PlaywrightGenerator();
246
+ const result = generator.generate(lockfile);
247
+ expect(result.content).toContain("page.locator('.modal').waitFor");
248
+ });
249
+ it('generates wait for text code', () => {
250
+ const lockfile = createMockLockfile({
251
+ steps: [createMockStep({ action: 'wait', for: 'text', text: 'Loading complete' })],
252
+ });
253
+ const generator = new PlaywrightGenerator();
254
+ const result = generator.generate(lockfile);
255
+ expect(result.content).toContain("page.getByText('Loading complete').waitFor");
256
+ });
257
+ it('generates wait for URL code', () => {
258
+ const lockfile = createMockLockfile({
259
+ steps: [createMockStep({ action: 'wait', for: 'url', contains: '/success' })],
260
+ });
261
+ const generator = new PlaywrightGenerator();
262
+ const result = generator.generate(lockfile);
263
+ expect(result.content).toContain("page.waitForURL(url => url.href.includes('/success')");
264
+ });
265
+ it('generates wait for time code', () => {
266
+ const lockfile = createMockLockfile({
267
+ steps: [createMockStep({ action: 'wait', for: 'time', duration: 2000 })],
268
+ });
269
+ const generator = new PlaywrightGenerator();
270
+ const result = generator.generate(lockfile);
271
+ expect(result.content).toContain('page.waitForTimeout(2000)');
272
+ });
273
+ it('generates select action code', () => {
274
+ const lockfile = createMockLockfile({
275
+ steps: [
276
+ createMockStep({ action: 'select', option: 'us' }, { locator: { selector: 'select#country' } }),
277
+ ],
278
+ });
279
+ const generator = new PlaywrightGenerator();
280
+ const result = generator.generate(lockfile);
281
+ expect(result.content).toContain("selectOption('us')");
282
+ });
283
+ it('generates check action code', () => {
284
+ const lockfile = createMockLockfile({
285
+ steps: [
286
+ createMockStep({ action: 'check', checked: true }, { locator: { selector: 'input[type=checkbox]' } }),
287
+ ],
288
+ });
289
+ const generator = new PlaywrightGenerator();
290
+ const result = generator.generate(lockfile);
291
+ expect(result.content).toContain('.check()');
292
+ });
293
+ it('generates uncheck action code', () => {
294
+ const lockfile = createMockLockfile({
295
+ steps: [
296
+ createMockStep({ action: 'check', checked: false }, { locator: { selector: 'input[type=checkbox]' } }),
297
+ ],
298
+ });
299
+ const generator = new PlaywrightGenerator();
300
+ const result = generator.generate(lockfile);
301
+ expect(result.content).toContain('.uncheck()');
302
+ });
303
+ it('generates back action code', () => {
304
+ const lockfile = createMockLockfile({
305
+ steps: [createMockStep({ action: 'back' })],
306
+ });
307
+ const generator = new PlaywrightGenerator();
308
+ const result = generator.generate(lockfile);
309
+ expect(result.content).toContain('await page.goBack()');
310
+ });
311
+ it('generates forward action code', () => {
312
+ const lockfile = createMockLockfile({
313
+ steps: [createMockStep({ action: 'forward' })],
314
+ });
315
+ const generator = new PlaywrightGenerator();
316
+ const result = generator.generate(lockfile);
317
+ expect(result.content).toContain('await page.goForward()');
318
+ });
319
+ it('generates refresh action code', () => {
320
+ const lockfile = createMockLockfile({
321
+ steps: [createMockStep({ action: 'refresh' })],
322
+ });
323
+ const generator = new PlaywrightGenerator();
324
+ const result = generator.generate(lockfile);
325
+ expect(result.content).toContain('await page.reload()');
326
+ });
327
+ it('generates verify_state action code', () => {
328
+ const lockfile = createMockLockfile({
329
+ steps: [
330
+ createMockStep({
331
+ action: 'verify_state',
332
+ checks: [
333
+ { element_visible: '.success-message' },
334
+ { text_contains: 'Order confirmed' },
335
+ ],
336
+ }),
337
+ ],
338
+ });
339
+ const generator = new PlaywrightGenerator();
340
+ const result = generator.generate(lockfile);
341
+ expect(result.content).toContain("expect(page.locator('.success-message')).toBeVisible()");
342
+ expect(result.content).toContain("expect(page.getByText('Order confirmed')).toBeVisible()");
343
+ });
344
+ it('generates screenshot action code', () => {
345
+ const lockfile = createMockLockfile({
346
+ steps: [createMockStep({ action: 'screenshot', name: 'checkout-page' })],
347
+ });
348
+ const generator = new PlaywrightGenerator();
349
+ const result = generator.generate(lockfile);
350
+ expect(result.content).toContain('toHaveScreenshot');
351
+ expect(result.content).toContain('checkout-page.png');
352
+ });
353
+ it('generates screenshot with selector-based mask', () => {
354
+ const lockfile = createMockLockfile({
355
+ steps: [
356
+ createMockStep({
357
+ action: 'screenshot',
358
+ name: 'dashboard',
359
+ mask: [
360
+ { selector: '.timestamp' },
361
+ { selector: '.user-avatar' },
362
+ ],
363
+ }),
364
+ ],
365
+ });
366
+ const generator = new PlaywrightGenerator();
367
+ const result = generator.generate(lockfile);
368
+ expect(result.content).toContain('toHaveScreenshot');
369
+ expect(result.content).toContain("mask: [page.locator('.timestamp'), page.locator('.user-avatar')]");
370
+ });
371
+ it('generates screenshot with region-based mask and setup code', () => {
372
+ const lockfile = createMockLockfile({
373
+ steps: [
374
+ createMockStep({
375
+ action: 'screenshot',
376
+ name: 'homepage',
377
+ mask: [
378
+ { region: { x: 10, y: 20, width: 100, height: 50 } },
379
+ ],
380
+ }),
381
+ ],
382
+ });
383
+ const generator = new PlaywrightGenerator();
384
+ const result = generator.generate(lockfile);
385
+ // Should include mask setup code before screenshot
386
+ expect(result.content).toContain('await page.evaluate');
387
+ expect(result.content).toContain('data-bf-mask');
388
+ expect(result.content).toContain('left:10%');
389
+ expect(result.content).toContain('top:20%');
390
+ expect(result.content).toContain('width:100%');
391
+ expect(result.content).toContain('height:50%');
392
+ // Should include screenshot with mask reference
393
+ expect(result.content).toContain('toHaveScreenshot');
394
+ expect(result.content).toContain("mask: [page.locator('[data-bf-mask=\"0\"]')]");
395
+ });
396
+ it('generates screenshot with mixed selector and region masks', () => {
397
+ const lockfile = createMockLockfile({
398
+ steps: [
399
+ createMockStep({
400
+ action: 'screenshot',
401
+ name: 'complex-page',
402
+ mask: [
403
+ { selector: '.header' },
404
+ { region: { x: 0, y: 90, width: 100, height: 10 } },
405
+ { selector: '.footer' },
406
+ { region: { x: 80, y: 5, width: 15, height: 10 } },
407
+ ],
408
+ }),
409
+ ],
410
+ });
411
+ const generator = new PlaywrightGenerator();
412
+ const result = generator.generate(lockfile);
413
+ // Should include setup code for both region masks
414
+ expect(result.content).toContain('await page.evaluate');
415
+ expect(result.content).toContain('left:0%');
416
+ expect(result.content).toContain('top:90%');
417
+ expect(result.content).toContain('left:80%');
418
+ expect(result.content).toContain('top:5%');
419
+ // Should include all masks in proper order
420
+ expect(result.content).toContain("page.locator('.header')");
421
+ expect(result.content).toContain("page.locator('[data-bf-mask=\"0\"]')");
422
+ expect(result.content).toContain("page.locator('.footer')");
423
+ expect(result.content).toContain("page.locator('[data-bf-mask=\"1\"]')");
424
+ });
425
+ it('generates screenshot without mask setup when only selector masks', () => {
426
+ const lockfile = createMockLockfile({
427
+ steps: [
428
+ createMockStep({
429
+ action: 'screenshot',
430
+ name: 'page',
431
+ mask: [
432
+ { selector: '.timestamp' },
433
+ { selector: '.avatar' },
434
+ ],
435
+ }),
436
+ ],
437
+ });
438
+ const generator = new PlaywrightGenerator();
439
+ const result = generator.generate(lockfile);
440
+ // Should NOT include page.evaluate for mask setup
441
+ expect(result.content).not.toContain('await page.evaluate');
442
+ expect(result.content).not.toContain('data-bf-mask');
443
+ // Should still include selector masks
444
+ expect(result.content).toContain("page.locator('.timestamp')");
445
+ expect(result.content).toContain("page.locator('.avatar')");
446
+ });
447
+ it('handles identify_element action as comment', () => {
448
+ const lockfile = createMockLockfile({
449
+ steps: [
450
+ createMockStep({ action: 'identify_element', query: 'Main navigation menu', save_as: 'nav' }, {}),
451
+ ],
452
+ });
453
+ const generator = new PlaywrightGenerator();
454
+ const result = generator.generate(lockfile);
455
+ // identify_element is exploratory and shouldn't generate runtime code
456
+ expect(result.content).toContain('identify_element');
457
+ });
458
+ it('handles ai_verify action as comment', () => {
459
+ const lockfile = createMockLockfile({
460
+ steps: [
461
+ createMockStep({ action: 'ai_verify', question: 'Is the cart empty?', expected: true }, {}),
462
+ ],
463
+ });
464
+ const generator = new PlaywrightGenerator();
465
+ const result = generator.generate(lockfile);
466
+ // ai_verify is AI-powered and shouldn't generate deterministic test code
467
+ expect(result.content).toContain('ai_verify');
468
+ });
469
+ it('handles custom action as comment', () => {
470
+ const lockfile = createMockLockfile({
471
+ steps: [createMockStep({ action: 'custom' })],
472
+ });
473
+ const generator = new PlaywrightGenerator();
474
+ const result = generator.generate(lockfile);
475
+ expect(result.content).toContain('custom');
476
+ });
477
+ });
478
+ describe('locator resolution', () => {
479
+ it('uses lockfile locator over exploration refs', () => {
480
+ const lockfile = createMockLockfile({
481
+ steps: [
482
+ createMockStep({ action: 'click', ref: '@e23' }, { locator: { method: 'getByTestId', args: { testId: 'submit' } } }),
483
+ ],
484
+ });
485
+ const generator = new PlaywrightGenerator();
486
+ const result = generator.generate(lockfile);
487
+ // Should use the resolved locator, not the ref
488
+ expect(result.content).toContain("page.getByTestId('submit')");
489
+ expect(result.content).not.toContain('@e23');
490
+ });
491
+ it('falls back to selector_used when locator is not available', () => {
492
+ const lockfile = createMockLockfile({
493
+ steps: [
494
+ createMockStep({ action: 'click' }, { selector_used: 'button.fallback' }),
495
+ ],
496
+ });
497
+ const generator = new PlaywrightGenerator();
498
+ const result = generator.generate(lockfile);
499
+ expect(result.content).toContain("page.locator('button.fallback')");
500
+ });
501
+ });
502
+ describe('outcome checks', () => {
503
+ it('generates outcome verification code for passed checks', () => {
504
+ const lockfile = createMockLockfile({
505
+ outcome_checks: [
506
+ { check: 'cart_total', expected: 99.99, actual: 99.99, passed: true },
507
+ { check: 'item_count', expected: 3, actual: 3, passed: true },
508
+ ],
509
+ });
510
+ const generator = new PlaywrightGenerator();
511
+ const result = generator.generate(lockfile);
512
+ expect(result.content).toContain('Outcome: cart_total');
513
+ expect(result.content).toContain('Outcome: item_count');
514
+ });
515
+ it('does not generate code for failed outcome checks', () => {
516
+ const lockfile = createMockLockfile({
517
+ outcome_checks: [
518
+ { check: 'cart_total', expected: 99.99, actual: 50.00, passed: false },
519
+ ],
520
+ });
521
+ const generator = new PlaywrightGenerator();
522
+ const result = generator.generate(lockfile);
523
+ expect(result.content).not.toContain('cart_total');
524
+ });
525
+ });
526
+ describe('generateTest convenience function', () => {
527
+ it('generates test using default options', () => {
528
+ const lockfile = createMockLockfile();
529
+ const result = generateTest(lockfile);
530
+ expect(result.content).toContain("import { test, expect }");
531
+ expect(result.path).toBe('e2e/tests/test-spec.spec.ts');
532
+ });
533
+ it('passes options to generator', () => {
534
+ const lockfile = createMockLockfile();
535
+ const result = generateTest(lockfile, { includeComments: false });
536
+ expect(result.content).not.toContain('//');
537
+ });
538
+ it('passes review data to generator', () => {
539
+ const lockfile = createMockLockfile();
540
+ const result = generateTest(lockfile, {}, createMockReview({
541
+ reviewer: 'alice',
542
+ submitted_at: '2026-01-15T14:00:00Z',
543
+ }));
544
+ expect(result.content).toContain('Approved by: alice');
545
+ });
546
+ });
547
+ });
548
+ //# sourceMappingURL=playwright-ts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright-ts.test.js","sourceRoot":"","sources":["../src/playwright-ts.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * visual-checks.ts
3
+ * Generates Playwright screenshot assertion code.
4
+ */
5
+ import type { MaskRegion } from '@browserflow-ai/core';
6
+ /**
7
+ * Options for screenshot assertion generation.
8
+ */
9
+ export interface ScreenshotOptions {
10
+ /** Name for the screenshot (used in baseline path) */
11
+ name: string;
12
+ /** Regions to mask during comparison */
13
+ mask?: MaskRegion[];
14
+ /** Maximum allowed pixel difference (0-1) */
15
+ maxDiffPixelRatio?: number;
16
+ /** Threshold for pixel color difference (0-1) */
17
+ threshold?: number;
18
+ /** Animation handling: "disabled" waits for animations to finish */
19
+ animations?: 'disabled' | 'allow';
20
+ /** Whether to capture full page */
21
+ fullPage?: boolean;
22
+ /** Timeout for screenshot capture */
23
+ timeout?: number;
24
+ }
25
+ /**
26
+ * Options for visual check code generation.
27
+ */
28
+ export interface VisualCheckEmitOptions {
29
+ /** Variable name for the page object (default: "page") */
30
+ pageVar?: string;
31
+ /** Base path for baseline screenshots */
32
+ baselinesPath?: string;
33
+ /** Include comments explaining the assertion */
34
+ includeComments?: boolean;
35
+ }
36
+ /**
37
+ * Generates code for a Playwright toHaveScreenshot assertion.
38
+ *
39
+ * @example
40
+ * generateScreenshotAssertion({ name: 'homepage' })
41
+ * // Returns: "await expect(page).toHaveScreenshot('homepage.png');"
42
+ */
43
+ export declare function generateScreenshotAssertion(options: ScreenshotOptions, emitOptions?: VisualCheckEmitOptions): string;
44
+ /**
45
+ * Generates code for an element-specific screenshot assertion.
46
+ *
47
+ * @example
48
+ * generateElementScreenshotAssertion("page.locator('.card')", { name: 'card' })
49
+ * // Returns: "await expect(page.locator('.card')).toHaveScreenshot('card.png');"
50
+ */
51
+ export declare function generateElementScreenshotAssertion(locatorCode: string, options: ScreenshotOptions, emitOptions?: VisualCheckEmitOptions): string;
52
+ /**
53
+ * Generates a screenshot capture statement (not an assertion).
54
+ */
55
+ export declare function generateScreenshotCapture(options: ScreenshotOptions, emitOptions?: VisualCheckEmitOptions): string;
56
+ /**
57
+ * Generates code for comparing two screenshot paths.
58
+ * This is useful for custom comparison logic outside of Playwright's built-in assertions.
59
+ */
60
+ export declare function generateScreenshotCompare(actualPath: string, expectedPath: string, options?: {
61
+ threshold?: number;
62
+ }): string;
63
+ /**
64
+ * Generates a helper import statement for visual comparisons.
65
+ */
66
+ export declare function generateVisualImports(): string;
67
+ /**
68
+ * Generates wait-for-animations code before taking a screenshot.
69
+ */
70
+ export declare function generateWaitForAnimations(pageVar?: string): string;
71
+ /**
72
+ * Generates code to inject overlay elements for region-based masks.
73
+ * Returns empty string if no region masks are present.
74
+ */
75
+ export declare function generateMaskSetupCode(masks: MaskRegion[], pageVar?: string): string;
76
+ //# sourceMappingURL=visual-checks.d.ts.map