@humanjs/playwright 0.6.0 → 0.8.0

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 CHANGED
@@ -54,6 +54,28 @@ await human.type('input[name="email"]', 'gonzalo@example.com');
54
54
 
55
55
  Pass a `seed` and every random decision (path curvature, typo placement, keystroke jitter) becomes reproducible. Same seed + same personality + same value = same keystrokes.
56
56
 
57
+ ### Playwright Test fixture
58
+
59
+ Writing `@playwright/test` specs? Import from the `@humanjs/playwright/test` subpath instead of constructing a `Human` in every test. It extends Playwright's `test` with a `human` fixture — seeded from the test title (deterministic per test) and instant in CI / humanized locally:
60
+
61
+ ```ts
62
+ import { test, expect } from '@humanjs/playwright/test';
63
+
64
+ test('checkout flow', async ({ human, page }) => {
65
+ await human.goto('/');
66
+ await human.click('Buy now');
67
+ await expect(page).toHaveURL(/checkout/);
68
+ });
69
+ ```
70
+
71
+ Customize per file (or per project via `playwright.config.ts` `use`) with the `humanOptions` option:
72
+
73
+ ```ts
74
+ test.use({ humanOptions: { personality: 'distracted', speed: 'human' } });
75
+ ```
76
+
77
+ Requires `@playwright/test` (an optional peer — you already have it to run the tests).
78
+
57
79
  ### Primitives
58
80
 
59
81
  The full `Human` surface, at a glance. Each one fires real DOM events through Playwright; the humanization wraps the timing and the path, not the dispatch.
@@ -341,7 +363,32 @@ await rec.toTimeline('session.json'); // → JSON on disk
341
363
  const timeline = rec.timeline; // → in-memory object
342
364
  ```
343
365
 
344
- The shape (`Timeline` with `personality`, `seed`, `speed`, `durationMs`, and an `events` array of `{ type, params, tMs, durationMs }`) is intended for observability pipelines, replay infrastructure, analytics, and debugger UIs. `toTimeline()` doesn't touch the browser context — call it before or after `toVideo()`, multiple times, in any order.
366
+ The shape (`Timeline` with `personality`, `seed`, `speed`, `durationMs`, and an `events` array of `{ type, params, tMs, durationMs }`, plus `inputValue` on captured `type`/`paste` events) is intended for observability pipelines, replay infrastructure, analytics, and debugger UIs. `toTimeline()` doesn't touch the browser context — call it before or after `toVideo()`, multiple times, in any order.
367
+
368
+ **Code export** — turn the same recording into runnable code:
369
+
370
+ ```ts
371
+ await rec.toHumanJS('session.ts'); // standalone HumanJS script
372
+ await rec.toPlaywright('session.spec.ts'); // @playwright/test spec (humanized)
373
+ ```
374
+
375
+ `toHumanJS()` emits a standalone script (`createHuman` + `human.*`); `toPlaywright()` emits a `@playwright/test` spec that drives the page through HumanJS, so the generated test runs humanized too. String selectors round-trip verbatim. Both work on timeline-only recordings and are unaffected by `dispose()`.
376
+
377
+ `toPlaywright()` also derives the assertions it safely can from the recording — a `read` implies its target was visible (`toBeVisible`), a captured input implies its value (`toHaveValue`) — and leaves a `TODO` for outcome assertions (URL changed, text appeared) that can't be inferred from actions alone. It never fabricates assertions that might fail on a correct run.
378
+
379
+ Generated tests are built to *be tests*: they run `speed: process.env.CI ? 'instant' : '<recorded>'` (instant in CI, recorded feel locally) and drop recorded `sleep()` pauses (timing fidelity belongs in a demo, not a test — pass `toPlaywright(path, { keepSleeps: true })` to keep them). The test title comes from the recording's name (`human.record({ name })`) and is overridable with `{ title }`.
380
+
381
+ Two more options: `{ steps: true }` groups the actions into `test.step(...)` blocks (a new step per navigation) for collapsible sections in the HTML report and trace; `{ baseUrl: true }` rewrites same-origin `goto`s to relative paths and adds a note to set `use.baseURL` in your `playwright.config.ts` — so the same test runs against local / staging / prod.
382
+
383
+ By default the actual typed/pasted text is captured into the timeline (and the exported code). Values typed into `input[type="password"]` are always masked; set `captureInputs: false` to record none — exports then emit empty-string placeholders:
384
+
385
+ ```ts
386
+ await human.record({ captureInputs: false }, fn);
387
+ ```
388
+
389
+ > Captured input values land in the timeline JSON and any exported code — treat those artifacts with the same care as the values themselves.
390
+
391
+ Two limits, by design: a target passed as a `Locator` or a raw `point(x, y)` doesn't round-trip to a clean selector (points are emitted verbatim with a flag comment — locator/point → selector synthesis is a planned follow-up), and reads driven by word-count or raw text emit a note instead of code.
345
392
 
346
393
  **Quality presets** trade off file size, encoding time, and visual fidelity. Defaults to `'high'`:
347
394