@humanjs/playwright 0.8.0 → 0.10.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/dist/index.cjs CHANGED
@@ -1,96 +1,108 @@
1
1
  'use strict';
2
2
 
3
- var chunkRCMSDC3N_cjs = require('./chunk-RCMSDC3N.cjs');
3
+ var chunk665R4N7R_cjs = require('./chunk-665R4N7R.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "Recording", {
8
8
  enumerable: true,
9
- get: function () { return chunkRCMSDC3N_cjs.Recording; }
9
+ get: function () { return chunk665R4N7R_cjs.Recording; }
10
10
  });
11
11
  Object.defineProperty(exports, "applyMicroJitter", {
12
12
  enumerable: true,
13
- get: function () { return chunkRCMSDC3N_cjs.applyMicroJitter; }
13
+ get: function () { return chunk665R4N7R_cjs.applyMicroJitter; }
14
14
  });
15
15
  Object.defineProperty(exports, "applyVelocityProfile", {
16
16
  enumerable: true,
17
- get: function () { return chunkRCMSDC3N_cjs.applyVelocityProfile; }
17
+ get: function () { return chunk665R4N7R_cjs.applyVelocityProfile; }
18
18
  });
19
19
  Object.defineProperty(exports, "bezierPath", {
20
20
  enumerable: true,
21
- get: function () { return chunkRCMSDC3N_cjs.bezierPath; }
21
+ get: function () { return chunk665R4N7R_cjs.bezierPath; }
22
22
  });
23
23
  Object.defineProperty(exports, "blend", {
24
24
  enumerable: true,
25
- get: function () { return chunkRCMSDC3N_cjs.blend; }
25
+ get: function () { return chunk665R4N7R_cjs.blend; }
26
26
  });
27
27
  Object.defineProperty(exports, "careful", {
28
28
  enumerable: true,
29
- get: function () { return chunkRCMSDC3N_cjs.careful; }
29
+ get: function () { return chunk665R4N7R_cjs.careful; }
30
30
  });
31
31
  Object.defineProperty(exports, "chromium", {
32
32
  enumerable: true,
33
- get: function () { return chunkRCMSDC3N_cjs.chromium; }
33
+ get: function () { return chunk665R4N7R_cjs.chromium; }
34
34
  });
35
35
  Object.defineProperty(exports, "computeReadingDwellMs", {
36
36
  enumerable: true,
37
- get: function () { return chunkRCMSDC3N_cjs.computeReadingDwellMs; }
37
+ get: function () { return chunk665R4N7R_cjs.computeReadingDwellMs; }
38
38
  });
39
39
  Object.defineProperty(exports, "countWords", {
40
40
  enumerable: true,
41
- get: function () { return chunkRCMSDC3N_cjs.countWords; }
41
+ get: function () { return chunk665R4N7R_cjs.countWords; }
42
42
  });
43
43
  Object.defineProperty(exports, "createHuman", {
44
44
  enumerable: true,
45
- get: function () { return chunkRCMSDC3N_cjs.createHuman; }
45
+ get: function () { return chunk665R4N7R_cjs.createHuman; }
46
46
  });
47
47
  Object.defineProperty(exports, "createRng", {
48
48
  enumerable: true,
49
- get: function () { return chunkRCMSDC3N_cjs.createRng; }
49
+ get: function () { return chunk665R4N7R_cjs.createRng; }
50
50
  });
51
51
  Object.defineProperty(exports, "distracted", {
52
52
  enumerable: true,
53
- get: function () { return chunkRCMSDC3N_cjs.distracted; }
53
+ get: function () { return chunk665R4N7R_cjs.distracted; }
54
54
  });
55
55
  Object.defineProperty(exports, "fast", {
56
56
  enumerable: true,
57
- get: function () { return chunkRCMSDC3N_cjs.fast; }
57
+ get: function () { return chunk665R4N7R_cjs.fast; }
58
58
  });
59
59
  Object.defineProperty(exports, "firefox", {
60
60
  enumerable: true,
61
- get: function () { return chunkRCMSDC3N_cjs.firefox; }
61
+ get: function () { return chunk665R4N7R_cjs.firefox; }
62
+ });
63
+ Object.defineProperty(exports, "generateHumanJS", {
64
+ enumerable: true,
65
+ get: function () { return chunk665R4N7R_cjs.generateHumanJS; }
66
+ });
67
+ Object.defineProperty(exports, "generatePlaywrightTest", {
68
+ enumerable: true,
69
+ get: function () { return chunk665R4N7R_cjs.generatePlaywrightTest; }
62
70
  });
63
71
  Object.defineProperty(exports, "humanizePath", {
64
72
  enumerable: true,
65
- get: function () { return chunkRCMSDC3N_cjs.humanizePath; }
73
+ get: function () { return chunk665R4N7R_cjs.humanizePath; }
66
74
  });
67
75
  Object.defineProperty(exports, "installMouseHelper", {
68
76
  enumerable: true,
69
- get: function () { return chunkRCMSDC3N_cjs.installMouseHelper; }
77
+ get: function () { return chunk665R4N7R_cjs.installMouseHelper; }
70
78
  });
71
79
  Object.defineProperty(exports, "planScroll", {
72
80
  enumerable: true,
73
- get: function () { return chunkRCMSDC3N_cjs.planScroll; }
81
+ get: function () { return chunk665R4N7R_cjs.planScroll; }
74
82
  });
75
83
  Object.defineProperty(exports, "planTypeKeystrokes", {
76
84
  enumerable: true,
77
- get: function () { return chunkRCMSDC3N_cjs.planTypeKeystrokes; }
85
+ get: function () { return chunk665R4N7R_cjs.planTypeKeystrokes; }
78
86
  });
79
87
  Object.defineProperty(exports, "precise", {
80
88
  enumerable: true,
81
- get: function () { return chunkRCMSDC3N_cjs.precise; }
89
+ get: function () { return chunk665R4N7R_cjs.precise; }
90
+ });
91
+ Object.defineProperty(exports, "replayTimeline", {
92
+ enumerable: true,
93
+ get: function () { return chunk665R4N7R_cjs.replayTimeline; }
82
94
  });
83
95
  Object.defineProperty(exports, "resolvePersonality", {
84
96
  enumerable: true,
85
- get: function () { return chunkRCMSDC3N_cjs.resolvePersonality; }
97
+ get: function () { return chunk665R4N7R_cjs.resolvePersonality; }
86
98
  });
87
99
  Object.defineProperty(exports, "sleep", {
88
100
  enumerable: true,
89
- get: function () { return chunkRCMSDC3N_cjs.sleep; }
101
+ get: function () { return chunk665R4N7R_cjs.sleep; }
90
102
  });
91
103
  Object.defineProperty(exports, "webkit", {
92
104
  enumerable: true,
93
- get: function () { return chunkRCMSDC3N_cjs.webkit; }
105
+ get: function () { return chunk665R4N7R_cjs.webkit; }
94
106
  });
95
107
  //# sourceMappingURL=index.cjs.map
96
108
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -81,6 +81,22 @@ interface PressResult {
81
81
  readonly dispatched: string;
82
82
  }
83
83
 
84
+ /** Options for {@link installMouseHelper}. */
85
+ interface InstallMouseHelperOptions {
86
+ /** Cursor fill color. Defaults to the HumanJS amber `#f5a55c`. */
87
+ readonly color?: string;
88
+ /** Cursor visual size in pixels. Defaults to 22. */
89
+ readonly size?: number;
90
+ /**
91
+ * Render a ripple at each `mousedown` position so clicks read on video.
92
+ * Defaults to `true`.
93
+ */
94
+ readonly showClicks?: boolean;
95
+ /** Halo opacity behind the cursor. Defaults to `0.18`. */
96
+ readonly haloOpacity?: number;
97
+ }
98
+ declare function installMouseHelper(target: BrowserContext | Page, options?: InstallMouseHelperOptions): Promise<void>;
99
+
84
100
  /**
85
101
  * What to read:
86
102
  * - `string`: a Playwright-compatible selector (matches `click()` / `type()`).
@@ -168,6 +184,12 @@ interface CaptureResult {
168
184
  cleanup(): Promise<void>;
169
185
  }
170
186
 
187
+ /**
188
+ * Generates a standalone, runnable HumanJS script that replays the recorded
189
+ * session. String selectors round-trip verbatim; raw coordinates and
190
+ * un-captured inputs are emitted with a flag so they're easy to fix up.
191
+ */
192
+ declare function generateHumanJS(timeline: Timeline): string;
171
193
  /** Options for {@link generatePlaywrightTest} / `Recording.toPlaywright`. */
172
194
  interface PlaywrightTestOptions {
173
195
  /**
@@ -189,6 +211,66 @@ interface PlaywrightTestOptions {
189
211
  */
190
212
  readonly baseUrl?: boolean;
191
213
  }
214
+ /**
215
+ * Generates a `@playwright/test` spec that replays the session through
216
+ * HumanJS — a humanized test, not raw Playwright, since the humanization is
217
+ * the point. Uses the `@humanjs/playwright/test` fixture for the `human`
218
+ * (recorded personality / seed / speed applied via `test.use({ humanOptions })`),
219
+ * runs instant in CI / recorded speed locally, drops timing `sleep()`s by
220
+ * default, and derives the assertions it safely can.
221
+ */
222
+ declare function generatePlaywrightTest(timeline: Timeline, options?: PlaywrightTestOptions): string;
223
+
224
+ /** Progress callback payload, fired as each step starts and settles. */
225
+ interface ReplayStepUpdate {
226
+ readonly index: number;
227
+ readonly type: string;
228
+ readonly status: 'running' | 'pass' | 'fail';
229
+ readonly error?: string;
230
+ }
231
+ /** Outcome of a single replayed step. */
232
+ interface ReplayStepResult {
233
+ readonly index: number;
234
+ readonly type: string;
235
+ readonly status: 'pass' | 'fail';
236
+ readonly error?: string;
237
+ }
238
+ /** Outcome of a {@link replayTimeline} run. */
239
+ interface ReplayResult {
240
+ readonly status: 'pass' | 'fail';
241
+ readonly steps: readonly ReplayStepResult[];
242
+ /** Index of the failing step, when `status` is `'fail'`. */
243
+ readonly failedIndex?: number;
244
+ readonly durationMs: number;
245
+ }
246
+ /** Options for {@link replayTimeline}. */
247
+ interface ReplayOptions {
248
+ /** Personality for the replay session. Defaults to `'careful'`. */
249
+ readonly personality?: PersonalityConfig;
250
+ /** Speed mode. Defaults to `'human'` so the replay is watchable. */
251
+ readonly speed?: Speed;
252
+ /** Seed for deterministic motion. */
253
+ readonly seed?: number | string;
254
+ /** Cursor overlay, forwarded to `createHuman` (on by default). */
255
+ readonly cursor?: boolean | InstallMouseHelperOptions;
256
+ /** Called as each step starts (`running`) and settles (`pass` / `fail`). */
257
+ readonly onStep?: (update: ReplayStepUpdate) => void;
258
+ /** Abort an in-flight replay (checked between steps); rejects with an `AbortError`. */
259
+ readonly signal?: AbortSignal;
260
+ }
261
+ /**
262
+ * Replay a recorded {@link Timeline} against a live `page`, driving it through
263
+ * the same humanized primitives the exported test uses. Runs each event in
264
+ * order and reports per-step pass/fail; **stops at the first failure** (like a
265
+ * real test). `assert` events are checked with plain Playwright APIs — there's
266
+ * no `@playwright/test` dependency — so they approximate `expect` without its
267
+ * auto-retry on text/url.
268
+ *
269
+ * Always resolves with a {@link ReplayResult}; a thrown error means the run
270
+ * itself broke (page closed, or the `signal` aborted → `AbortError`), not a
271
+ * step failure. The caller owns `page`'s lifecycle.
272
+ */
273
+ declare function replayTimeline(page: Page, timeline: Timeline | readonly TimelineEvent[], options?: ReplayOptions): Promise<ReplayResult>;
192
274
 
193
275
  /**
194
276
  * Encoding quality preset. Picks the per-frame capture quality + the
@@ -463,22 +545,15 @@ interface ScrollResult {
463
545
  readonly durationMs: number;
464
546
  }
465
547
 
466
- /** Options for {@link installMouseHelper}. */
467
- interface InstallMouseHelperOptions {
468
- /** Cursor fill color. Defaults to the HumanJS amber `#f5a55c`. */
469
- readonly color?: string;
470
- /** Cursor visual size in pixels. Defaults to 22. */
471
- readonly size?: number;
548
+ /** Options for {@link Human.selectText}. */
549
+ interface SelectTextOptions {
472
550
  /**
473
- * Render a ripple at each `mousedown` position so clicks read on video.
474
- * Defaults to `true`.
551
+ * Select only this substring of the element's text instead of all of it.
552
+ * Located inside the element whitespace-tolerantly (first match); falls back
553
+ * to selecting the whole element when not found.
475
554
  */
476
- readonly showClicks?: boolean;
477
- /** Halo opacity behind the cursor. Defaults to `0.18`. */
478
- readonly haloOpacity?: number;
555
+ text?: string;
479
556
  }
480
- declare function installMouseHelper(target: BrowserContext | Page, options?: InstallMouseHelperOptions): Promise<void>;
481
-
482
557
  /**
483
558
  * How fast the humanized session runs.
484
559
  * - `'human'` — full humanization (default)
@@ -496,6 +571,14 @@ interface CreateHumanOptions {
496
571
  readonly speed?: Speed;
497
572
  /** Plugins installed on this session, invoked in registration order. */
498
573
  readonly plugins?: readonly HumanPlugin[];
574
+ /**
575
+ * Visual cursor overlay ({@link installMouseHelper}) so humanized motion is
576
+ * visible in headed runs and recordings. **On by default.** Pass `false` to
577
+ * opt out — do this for `speed: 'instant'` / CI, where there's no motion to
578
+ * show and the injected cursor would land in test DOM and screenshots. Pass
579
+ * an options object to style it (color, size, …).
580
+ */
581
+ readonly cursor?: boolean | InstallMouseHelperOptions;
499
582
  /**
500
583
  * Starting cursor position used as the origin of the first humanized path.
501
584
  * Defaults to `{ x: 0, y: 0 }`. Set this if you've already moved the cursor
@@ -666,6 +749,23 @@ interface Human {
666
749
  * In `speed: 'instant'`, sets the value with no cursor motion.
667
750
  */
668
751
  selectOption(target: Locator | string, values: SelectOptionValues): Promise<string[]>;
752
+ /**
753
+ * Select text inside `target` (a paragraph, heading, input, …). The cursor
754
+ * moves to the element (humanized), then the text is highlighted — the
755
+ * "select this" gesture before copying, replacing, or triggering a highlight
756
+ * menu.
757
+ *
758
+ * By default the element's whole text is selected. Pass `{ text }` to select
759
+ * just that substring: HumanJS finds it inside the element (whitespace-
760
+ * tolerant, mapped to exact offsets, first match) and selects only that
761
+ * range — so a recorded partial highlight reproduces as itself, not the whole
762
+ * element. If the text can't be located, it falls back to selecting all of
763
+ * the element.
764
+ *
765
+ * `target` is element-bound (selector or `Locator`). In `speed: 'instant'`
766
+ * the cursor motion is skipped; the selection is still applied.
767
+ */
768
+ selectText(target: Locator | string, options?: SelectTextOptions): Promise<void>;
669
769
  /**
670
770
  * Attach file(s) to a file-input `target`. The cursor moves to the control
671
771
  * (visible in recordings / the overlay), then the files are attached via
@@ -982,4 +1082,4 @@ interface HumanRecordOptions {
982
1082
  */
983
1083
  declare function createHuman(page: Page, options?: CreateHumanOptions): Promise<Human>;
984
1084
 
985
- export { type CreateHumanOptions, type FfmpegPreset, type FfmpegTune, type Human, type HumanRecordOptions, type InstallMouseHelperOptions, type KeyModifier, type KeyName, type KeyOrChord, type MouseTarget, type PlaywrightTestOptions, type PressResult, type ReadOptions, type ReadResult, type ReadTarget, Recording, type RecordingQuality, type ScrollOptions, type ScrollResult, type ScrollTarget, type SelectOptionValues, type Speed, type Timeline, type TimelineEvent, type ToGifOptions, type ToVideoOptions, type UploadFiles, createHuman, installMouseHelper };
1085
+ export { type CreateHumanOptions, type FfmpegPreset, type FfmpegTune, type Human, type HumanRecordOptions, type InstallMouseHelperOptions, type KeyModifier, type KeyName, type KeyOrChord, type MouseTarget, type PlaywrightTestOptions, type PressResult, type ReadOptions, type ReadResult, type ReadTarget, Recording, type RecordingQuality, type ReplayOptions, type ReplayResult, type ReplayStepResult, type ReplayStepUpdate, type ScrollOptions, type ScrollResult, type ScrollTarget, type SelectOptionValues, type SelectTextOptions, type Speed, type Timeline, type TimelineEvent, type ToGifOptions, type ToVideoOptions, type UploadFiles, createHuman, generateHumanJS, generatePlaywrightTest, installMouseHelper, replayTimeline };
package/dist/index.d.ts CHANGED
@@ -81,6 +81,22 @@ interface PressResult {
81
81
  readonly dispatched: string;
82
82
  }
83
83
 
84
+ /** Options for {@link installMouseHelper}. */
85
+ interface InstallMouseHelperOptions {
86
+ /** Cursor fill color. Defaults to the HumanJS amber `#f5a55c`. */
87
+ readonly color?: string;
88
+ /** Cursor visual size in pixels. Defaults to 22. */
89
+ readonly size?: number;
90
+ /**
91
+ * Render a ripple at each `mousedown` position so clicks read on video.
92
+ * Defaults to `true`.
93
+ */
94
+ readonly showClicks?: boolean;
95
+ /** Halo opacity behind the cursor. Defaults to `0.18`. */
96
+ readonly haloOpacity?: number;
97
+ }
98
+ declare function installMouseHelper(target: BrowserContext | Page, options?: InstallMouseHelperOptions): Promise<void>;
99
+
84
100
  /**
85
101
  * What to read:
86
102
  * - `string`: a Playwright-compatible selector (matches `click()` / `type()`).
@@ -168,6 +184,12 @@ interface CaptureResult {
168
184
  cleanup(): Promise<void>;
169
185
  }
170
186
 
187
+ /**
188
+ * Generates a standalone, runnable HumanJS script that replays the recorded
189
+ * session. String selectors round-trip verbatim; raw coordinates and
190
+ * un-captured inputs are emitted with a flag so they're easy to fix up.
191
+ */
192
+ declare function generateHumanJS(timeline: Timeline): string;
171
193
  /** Options for {@link generatePlaywrightTest} / `Recording.toPlaywright`. */
172
194
  interface PlaywrightTestOptions {
173
195
  /**
@@ -189,6 +211,66 @@ interface PlaywrightTestOptions {
189
211
  */
190
212
  readonly baseUrl?: boolean;
191
213
  }
214
+ /**
215
+ * Generates a `@playwright/test` spec that replays the session through
216
+ * HumanJS — a humanized test, not raw Playwright, since the humanization is
217
+ * the point. Uses the `@humanjs/playwright/test` fixture for the `human`
218
+ * (recorded personality / seed / speed applied via `test.use({ humanOptions })`),
219
+ * runs instant in CI / recorded speed locally, drops timing `sleep()`s by
220
+ * default, and derives the assertions it safely can.
221
+ */
222
+ declare function generatePlaywrightTest(timeline: Timeline, options?: PlaywrightTestOptions): string;
223
+
224
+ /** Progress callback payload, fired as each step starts and settles. */
225
+ interface ReplayStepUpdate {
226
+ readonly index: number;
227
+ readonly type: string;
228
+ readonly status: 'running' | 'pass' | 'fail';
229
+ readonly error?: string;
230
+ }
231
+ /** Outcome of a single replayed step. */
232
+ interface ReplayStepResult {
233
+ readonly index: number;
234
+ readonly type: string;
235
+ readonly status: 'pass' | 'fail';
236
+ readonly error?: string;
237
+ }
238
+ /** Outcome of a {@link replayTimeline} run. */
239
+ interface ReplayResult {
240
+ readonly status: 'pass' | 'fail';
241
+ readonly steps: readonly ReplayStepResult[];
242
+ /** Index of the failing step, when `status` is `'fail'`. */
243
+ readonly failedIndex?: number;
244
+ readonly durationMs: number;
245
+ }
246
+ /** Options for {@link replayTimeline}. */
247
+ interface ReplayOptions {
248
+ /** Personality for the replay session. Defaults to `'careful'`. */
249
+ readonly personality?: PersonalityConfig;
250
+ /** Speed mode. Defaults to `'human'` so the replay is watchable. */
251
+ readonly speed?: Speed;
252
+ /** Seed for deterministic motion. */
253
+ readonly seed?: number | string;
254
+ /** Cursor overlay, forwarded to `createHuman` (on by default). */
255
+ readonly cursor?: boolean | InstallMouseHelperOptions;
256
+ /** Called as each step starts (`running`) and settles (`pass` / `fail`). */
257
+ readonly onStep?: (update: ReplayStepUpdate) => void;
258
+ /** Abort an in-flight replay (checked between steps); rejects with an `AbortError`. */
259
+ readonly signal?: AbortSignal;
260
+ }
261
+ /**
262
+ * Replay a recorded {@link Timeline} against a live `page`, driving it through
263
+ * the same humanized primitives the exported test uses. Runs each event in
264
+ * order and reports per-step pass/fail; **stops at the first failure** (like a
265
+ * real test). `assert` events are checked with plain Playwright APIs — there's
266
+ * no `@playwright/test` dependency — so they approximate `expect` without its
267
+ * auto-retry on text/url.
268
+ *
269
+ * Always resolves with a {@link ReplayResult}; a thrown error means the run
270
+ * itself broke (page closed, or the `signal` aborted → `AbortError`), not a
271
+ * step failure. The caller owns `page`'s lifecycle.
272
+ */
273
+ declare function replayTimeline(page: Page, timeline: Timeline | readonly TimelineEvent[], options?: ReplayOptions): Promise<ReplayResult>;
192
274
 
193
275
  /**
194
276
  * Encoding quality preset. Picks the per-frame capture quality + the
@@ -463,22 +545,15 @@ interface ScrollResult {
463
545
  readonly durationMs: number;
464
546
  }
465
547
 
466
- /** Options for {@link installMouseHelper}. */
467
- interface InstallMouseHelperOptions {
468
- /** Cursor fill color. Defaults to the HumanJS amber `#f5a55c`. */
469
- readonly color?: string;
470
- /** Cursor visual size in pixels. Defaults to 22. */
471
- readonly size?: number;
548
+ /** Options for {@link Human.selectText}. */
549
+ interface SelectTextOptions {
472
550
  /**
473
- * Render a ripple at each `mousedown` position so clicks read on video.
474
- * Defaults to `true`.
551
+ * Select only this substring of the element's text instead of all of it.
552
+ * Located inside the element whitespace-tolerantly (first match); falls back
553
+ * to selecting the whole element when not found.
475
554
  */
476
- readonly showClicks?: boolean;
477
- /** Halo opacity behind the cursor. Defaults to `0.18`. */
478
- readonly haloOpacity?: number;
555
+ text?: string;
479
556
  }
480
- declare function installMouseHelper(target: BrowserContext | Page, options?: InstallMouseHelperOptions): Promise<void>;
481
-
482
557
  /**
483
558
  * How fast the humanized session runs.
484
559
  * - `'human'` — full humanization (default)
@@ -496,6 +571,14 @@ interface CreateHumanOptions {
496
571
  readonly speed?: Speed;
497
572
  /** Plugins installed on this session, invoked in registration order. */
498
573
  readonly plugins?: readonly HumanPlugin[];
574
+ /**
575
+ * Visual cursor overlay ({@link installMouseHelper}) so humanized motion is
576
+ * visible in headed runs and recordings. **On by default.** Pass `false` to
577
+ * opt out — do this for `speed: 'instant'` / CI, where there's no motion to
578
+ * show and the injected cursor would land in test DOM and screenshots. Pass
579
+ * an options object to style it (color, size, …).
580
+ */
581
+ readonly cursor?: boolean | InstallMouseHelperOptions;
499
582
  /**
500
583
  * Starting cursor position used as the origin of the first humanized path.
501
584
  * Defaults to `{ x: 0, y: 0 }`. Set this if you've already moved the cursor
@@ -666,6 +749,23 @@ interface Human {
666
749
  * In `speed: 'instant'`, sets the value with no cursor motion.
667
750
  */
668
751
  selectOption(target: Locator | string, values: SelectOptionValues): Promise<string[]>;
752
+ /**
753
+ * Select text inside `target` (a paragraph, heading, input, …). The cursor
754
+ * moves to the element (humanized), then the text is highlighted — the
755
+ * "select this" gesture before copying, replacing, or triggering a highlight
756
+ * menu.
757
+ *
758
+ * By default the element's whole text is selected. Pass `{ text }` to select
759
+ * just that substring: HumanJS finds it inside the element (whitespace-
760
+ * tolerant, mapped to exact offsets, first match) and selects only that
761
+ * range — so a recorded partial highlight reproduces as itself, not the whole
762
+ * element. If the text can't be located, it falls back to selecting all of
763
+ * the element.
764
+ *
765
+ * `target` is element-bound (selector or `Locator`). In `speed: 'instant'`
766
+ * the cursor motion is skipped; the selection is still applied.
767
+ */
768
+ selectText(target: Locator | string, options?: SelectTextOptions): Promise<void>;
669
769
  /**
670
770
  * Attach file(s) to a file-input `target`. The cursor moves to the control
671
771
  * (visible in recordings / the overlay), then the files are attached via
@@ -982,4 +1082,4 @@ interface HumanRecordOptions {
982
1082
  */
983
1083
  declare function createHuman(page: Page, options?: CreateHumanOptions): Promise<Human>;
984
1084
 
985
- export { type CreateHumanOptions, type FfmpegPreset, type FfmpegTune, type Human, type HumanRecordOptions, type InstallMouseHelperOptions, type KeyModifier, type KeyName, type KeyOrChord, type MouseTarget, type PlaywrightTestOptions, type PressResult, type ReadOptions, type ReadResult, type ReadTarget, Recording, type RecordingQuality, type ScrollOptions, type ScrollResult, type ScrollTarget, type SelectOptionValues, type Speed, type Timeline, type TimelineEvent, type ToGifOptions, type ToVideoOptions, type UploadFiles, createHuman, installMouseHelper };
1085
+ export { type CreateHumanOptions, type FfmpegPreset, type FfmpegTune, type Human, type HumanRecordOptions, type InstallMouseHelperOptions, type KeyModifier, type KeyName, type KeyOrChord, type MouseTarget, type PlaywrightTestOptions, type PressResult, type ReadOptions, type ReadResult, type ReadTarget, Recording, type RecordingQuality, type ReplayOptions, type ReplayResult, type ReplayStepResult, type ReplayStepUpdate, type ScrollOptions, type ScrollResult, type ScrollTarget, type SelectOptionValues, type SelectTextOptions, type Speed, type Timeline, type TimelineEvent, type ToGifOptions, type ToVideoOptions, type UploadFiles, createHuman, generateHumanJS, generatePlaywrightTest, installMouseHelper, replayTimeline };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Recording, applyMicroJitter, applyVelocityProfile, bezierPath, blend, careful, chromium, computeReadingDwellMs, countWords, createHuman, createRng, distracted, fast, firefox, humanizePath, installMouseHelper, planScroll, planTypeKeystrokes, precise, resolvePersonality, sleep, webkit } from './chunk-CCZEDNOF.js';
1
+ export { Recording, applyMicroJitter, applyVelocityProfile, bezierPath, blend, careful, chromium, computeReadingDwellMs, countWords, createHuman, createRng, distracted, fast, firefox, generateHumanJS, generatePlaywrightTest, humanizePath, installMouseHelper, planScroll, planTypeKeystrokes, precise, replayTimeline, resolvePersonality, sleep, webkit } from './chunk-I2PQGZU7.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/test.cjs CHANGED
@@ -1,16 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var chunkRCMSDC3N_cjs = require('./chunk-RCMSDC3N.cjs');
3
+ var chunk665R4N7R_cjs = require('./chunk-665R4N7R.cjs');
4
4
  var test$1 = require('@playwright/test');
5
5
 
6
6
  var test = test$1.test.extend({
7
7
  humanOptions: [{}, { option: true }],
8
8
  human: async ({ page, humanOptions }, use, testInfo) => {
9
- const human = await chunkRCMSDC3N_cjs.createHuman(page, {
9
+ const human = await chunk665R4N7R_cjs.createHuman(page, {
10
10
  // Deterministic per test, CI-fast by default — both overridable since
11
11
  // the spread comes last.
12
12
  seed: testInfo.title,
13
13
  speed: process.env.CI ? "instant" : "human",
14
+ // No cursor overlay in CI (instant) so it never lands in test DOM or
15
+ // screenshots; shown locally where you actually watch the run.
16
+ cursor: !process.env.CI,
14
17
  ...humanOptions
15
18
  });
16
19
  await use(human);
package/dist/test.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/test/index.ts"],"names":["base","createHuman"],"mappings":";;;;;AAyDO,IAAM,IAAA,GAAOA,YAAK,MAAA,CAAqC;AAAA,EAC5D,cAAc,CAAC,IAAI,EAAE,MAAA,EAAQ,MAAM,CAAA;AAAA,EACnC,OAAO,OAAO,EAAE,MAAM,YAAA,EAAa,EAAG,KAAK,QAAA,KAAa;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAMC,6BAAA,CAAY,IAAA,EAAM;AAAA;AAAA;AAAA,MAGpC,MAAM,QAAA,CAAS,KAAA;AAAA,MACf,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,EAAA,GAAK,SAAA,GAAY,OAAA;AAAA,MACpC,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,IAAI,KAAK,CAAA;AAAA,EACjB;AACF,CAAC","file":"test.cjs","sourcesContent":["/**\n * Playwright Test integration — opt-in via the `@humanjs/playwright/test`\n * subpath. Re-exports `test` / `expect` from `@playwright/test` with a\n * pre-wired `human` fixture, so a spec never hand-rolls `createHuman`.\n *\n * Each test gets a {@link Human} bound to its `page`, **seeded from the test\n * title** (deterministic per test, so snapshots stay stable) and **instant in\n * CI / humanized locally** (fast pipelines, real-pace runs at your desk).\n * Override any of that per-file or per-project with the `humanOptions` option.\n *\n * `@playwright/test` is an optional peer — it's how you run Playwright tests,\n * so the host already provides it. Keeping the fixture on a subpath means the\n * package root never pulls in the test runner.\n *\n * @example\n * ```ts\n * import { test, expect } from '@humanjs/playwright/test';\n *\n * test('checkout', async ({ human, page }) => {\n * await human.goto('/cart');\n * await human.click('Checkout');\n * await expect(page).toHaveURL(/success/);\n * });\n *\n * // Customize for a file (or a whole project via playwright.config.ts):\n * test.use({ humanOptions: { personality: 'distracted', speed: 'human' } });\n * ```\n */\n\nimport { test as base } from '@playwright/test';\nimport { type CreateHumanOptions, createHuman, type Human } from '../index';\n\n/** Test-scoped fixtures added by `@humanjs/playwright/test`. */\nexport interface HumanFixtures {\n /**\n * A {@link Human} bound to the test's `page`. Created fresh per test; by\n * default seeded from the test title and run instant in CI, humanized\n * locally. Tune via the `humanOptions` option.\n */\n human: Human;\n}\n\n/** Option fixture to customize the per-test {@link Human}. */\nexport interface HumanOptions {\n /**\n * Options forwarded to `createHuman` for the `human` fixture. Set with\n * `test.use({ humanOptions: { … } })` (per file) or in `playwright.config.ts`\n * `use` (per project). Defaults: `seed` = the test title, `speed` =\n * `'instant'` in CI else `'human'`. Anything you set here overrides those.\n */\n humanOptions: CreateHumanOptions;\n}\n\n/**\n * Playwright `test` extended with the `human` fixture. Drop-in replacement\n * for `@playwright/test`'s `test`.\n */\nexport const test = base.extend<HumanFixtures & HumanOptions>({\n humanOptions: [{}, { option: true }],\n human: async ({ page, humanOptions }, use, testInfo) => {\n const human = await createHuman(page, {\n // Deterministic per test, CI-fast by default — both overridable since\n // the spread comes last.\n seed: testInfo.title,\n speed: process.env.CI ? 'instant' : 'human',\n ...humanOptions,\n });\n await use(human);\n },\n});\n\nexport { expect } from '@playwright/test';\n"]}
1
+ {"version":3,"sources":["../src/test/index.ts"],"names":["base","createHuman"],"mappings":";;;;;AAyDO,IAAM,IAAA,GAAOA,YAAK,MAAA,CAAqC;AAAA,EAC5D,cAAc,CAAC,IAAI,EAAE,MAAA,EAAQ,MAAM,CAAA;AAAA,EACnC,OAAO,OAAO,EAAE,MAAM,YAAA,EAAa,EAAG,KAAK,QAAA,KAAa;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAMC,6BAAA,CAAY,IAAA,EAAM;AAAA;AAAA;AAAA,MAGpC,MAAM,QAAA,CAAS,KAAA;AAAA,MACf,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,EAAA,GAAK,SAAA,GAAY,OAAA;AAAA;AAAA;AAAA,MAGpC,MAAA,EAAQ,CAAC,OAAA,CAAQ,GAAA,CAAI,EAAA;AAAA,MACrB,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,IAAI,KAAK,CAAA;AAAA,EACjB;AACF,CAAC","file":"test.cjs","sourcesContent":["/**\n * Playwright Test integration — opt-in via the `@humanjs/playwright/test`\n * subpath. Re-exports `test` / `expect` from `@playwright/test` with a\n * pre-wired `human` fixture, so a spec never hand-rolls `createHuman`.\n *\n * Each test gets a {@link Human} bound to its `page`, **seeded from the test\n * title** (deterministic per test, so snapshots stay stable) and **instant in\n * CI / humanized locally** (fast pipelines, real-pace runs at your desk).\n * Override any of that per-file or per-project with the `humanOptions` option.\n *\n * `@playwright/test` is an optional peer — it's how you run Playwright tests,\n * so the host already provides it. Keeping the fixture on a subpath means the\n * package root never pulls in the test runner.\n *\n * @example\n * ```ts\n * import { test, expect } from '@humanjs/playwright/test';\n *\n * test('checkout', async ({ human, page }) => {\n * await human.goto('/cart');\n * await human.click('Checkout');\n * await expect(page).toHaveURL(/success/);\n * });\n *\n * // Customize for a file (or a whole project via playwright.config.ts):\n * test.use({ humanOptions: { personality: 'distracted', speed: 'human' } });\n * ```\n */\n\nimport { test as base } from '@playwright/test';\nimport { type CreateHumanOptions, createHuman, type Human } from '../index';\n\n/** Test-scoped fixtures added by `@humanjs/playwright/test`. */\nexport interface HumanFixtures {\n /**\n * A {@link Human} bound to the test's `page`. Created fresh per test; by\n * default seeded from the test title and run instant in CI, humanized\n * locally. Tune via the `humanOptions` option.\n */\n human: Human;\n}\n\n/** Option fixture to customize the per-test {@link Human}. */\nexport interface HumanOptions {\n /**\n * Options forwarded to `createHuman` for the `human` fixture. Set with\n * `test.use({ humanOptions: { … } })` (per file) or in `playwright.config.ts`\n * `use` (per project). Defaults: `seed` = the test title, `speed` =\n * `'instant'` in CI else `'human'`. Anything you set here overrides those.\n */\n humanOptions: CreateHumanOptions;\n}\n\n/**\n * Playwright `test` extended with the `human` fixture. Drop-in replacement\n * for `@playwright/test`'s `test`.\n */\nexport const test = base.extend<HumanFixtures & HumanOptions>({\n humanOptions: [{}, { option: true }],\n human: async ({ page, humanOptions }, use, testInfo) => {\n const human = await createHuman(page, {\n // Deterministic per test, CI-fast by default — both overridable since\n // the spread comes last.\n seed: testInfo.title,\n speed: process.env.CI ? 'instant' : 'human',\n // No cursor overlay in CI (instant) so it never lands in test DOM or\n // screenshots; shown locally where you actually watch the run.\n cursor: !process.env.CI,\n ...humanOptions,\n });\n await use(human);\n },\n});\n\nexport { expect } from '@playwright/test';\n"]}
package/dist/test.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createHuman } from './chunk-CCZEDNOF.js';
1
+ import { createHuman } from './chunk-I2PQGZU7.js';
2
2
  import { test as test$1 } from '@playwright/test';
3
3
  export { expect } from '@playwright/test';
4
4
 
@@ -10,6 +10,9 @@ var test = test$1.extend({
10
10
  // the spread comes last.
11
11
  seed: testInfo.title,
12
12
  speed: process.env.CI ? "instant" : "human",
13
+ // No cursor overlay in CI (instant) so it never lands in test DOM or
14
+ // screenshots; shown locally where you actually watch the run.
15
+ cursor: !process.env.CI,
13
16
  ...humanOptions
14
17
  });
15
18
  await use(human);
package/dist/test.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/test/index.ts"],"names":["base"],"mappings":";;;;AAyDO,IAAM,IAAA,GAAOA,OAAK,MAAA,CAAqC;AAAA,EAC5D,cAAc,CAAC,IAAI,EAAE,MAAA,EAAQ,MAAM,CAAA;AAAA,EACnC,OAAO,OAAO,EAAE,MAAM,YAAA,EAAa,EAAG,KAAK,QAAA,KAAa;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,IAAA,EAAM;AAAA;AAAA;AAAA,MAGpC,MAAM,QAAA,CAAS,KAAA;AAAA,MACf,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,EAAA,GAAK,SAAA,GAAY,OAAA;AAAA,MACpC,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,IAAI,KAAK,CAAA;AAAA,EACjB;AACF,CAAC","file":"test.js","sourcesContent":["/**\n * Playwright Test integration — opt-in via the `@humanjs/playwright/test`\n * subpath. Re-exports `test` / `expect` from `@playwright/test` with a\n * pre-wired `human` fixture, so a spec never hand-rolls `createHuman`.\n *\n * Each test gets a {@link Human} bound to its `page`, **seeded from the test\n * title** (deterministic per test, so snapshots stay stable) and **instant in\n * CI / humanized locally** (fast pipelines, real-pace runs at your desk).\n * Override any of that per-file or per-project with the `humanOptions` option.\n *\n * `@playwright/test` is an optional peer — it's how you run Playwright tests,\n * so the host already provides it. Keeping the fixture on a subpath means the\n * package root never pulls in the test runner.\n *\n * @example\n * ```ts\n * import { test, expect } from '@humanjs/playwright/test';\n *\n * test('checkout', async ({ human, page }) => {\n * await human.goto('/cart');\n * await human.click('Checkout');\n * await expect(page).toHaveURL(/success/);\n * });\n *\n * // Customize for a file (or a whole project via playwright.config.ts):\n * test.use({ humanOptions: { personality: 'distracted', speed: 'human' } });\n * ```\n */\n\nimport { test as base } from '@playwright/test';\nimport { type CreateHumanOptions, createHuman, type Human } from '../index';\n\n/** Test-scoped fixtures added by `@humanjs/playwright/test`. */\nexport interface HumanFixtures {\n /**\n * A {@link Human} bound to the test's `page`. Created fresh per test; by\n * default seeded from the test title and run instant in CI, humanized\n * locally. Tune via the `humanOptions` option.\n */\n human: Human;\n}\n\n/** Option fixture to customize the per-test {@link Human}. */\nexport interface HumanOptions {\n /**\n * Options forwarded to `createHuman` for the `human` fixture. Set with\n * `test.use({ humanOptions: { … } })` (per file) or in `playwright.config.ts`\n * `use` (per project). Defaults: `seed` = the test title, `speed` =\n * `'instant'` in CI else `'human'`. Anything you set here overrides those.\n */\n humanOptions: CreateHumanOptions;\n}\n\n/**\n * Playwright `test` extended with the `human` fixture. Drop-in replacement\n * for `@playwright/test`'s `test`.\n */\nexport const test = base.extend<HumanFixtures & HumanOptions>({\n humanOptions: [{}, { option: true }],\n human: async ({ page, humanOptions }, use, testInfo) => {\n const human = await createHuman(page, {\n // Deterministic per test, CI-fast by default — both overridable since\n // the spread comes last.\n seed: testInfo.title,\n speed: process.env.CI ? 'instant' : 'human',\n ...humanOptions,\n });\n await use(human);\n },\n});\n\nexport { expect } from '@playwright/test';\n"]}
1
+ {"version":3,"sources":["../src/test/index.ts"],"names":["base"],"mappings":";;;;AAyDO,IAAM,IAAA,GAAOA,OAAK,MAAA,CAAqC;AAAA,EAC5D,cAAc,CAAC,IAAI,EAAE,MAAA,EAAQ,MAAM,CAAA;AAAA,EACnC,OAAO,OAAO,EAAE,MAAM,YAAA,EAAa,EAAG,KAAK,QAAA,KAAa;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY,IAAA,EAAM;AAAA;AAAA;AAAA,MAGpC,MAAM,QAAA,CAAS,KAAA;AAAA,MACf,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,EAAA,GAAK,SAAA,GAAY,OAAA;AAAA;AAAA;AAAA,MAGpC,MAAA,EAAQ,CAAC,OAAA,CAAQ,GAAA,CAAI,EAAA;AAAA,MACrB,GAAG;AAAA,KACJ,CAAA;AACD,IAAA,MAAM,IAAI,KAAK,CAAA;AAAA,EACjB;AACF,CAAC","file":"test.js","sourcesContent":["/**\n * Playwright Test integration — opt-in via the `@humanjs/playwright/test`\n * subpath. Re-exports `test` / `expect` from `@playwright/test` with a\n * pre-wired `human` fixture, so a spec never hand-rolls `createHuman`.\n *\n * Each test gets a {@link Human} bound to its `page`, **seeded from the test\n * title** (deterministic per test, so snapshots stay stable) and **instant in\n * CI / humanized locally** (fast pipelines, real-pace runs at your desk).\n * Override any of that per-file or per-project with the `humanOptions` option.\n *\n * `@playwright/test` is an optional peer — it's how you run Playwright tests,\n * so the host already provides it. Keeping the fixture on a subpath means the\n * package root never pulls in the test runner.\n *\n * @example\n * ```ts\n * import { test, expect } from '@humanjs/playwright/test';\n *\n * test('checkout', async ({ human, page }) => {\n * await human.goto('/cart');\n * await human.click('Checkout');\n * await expect(page).toHaveURL(/success/);\n * });\n *\n * // Customize for a file (or a whole project via playwright.config.ts):\n * test.use({ humanOptions: { personality: 'distracted', speed: 'human' } });\n * ```\n */\n\nimport { test as base } from '@playwright/test';\nimport { type CreateHumanOptions, createHuman, type Human } from '../index';\n\n/** Test-scoped fixtures added by `@humanjs/playwright/test`. */\nexport interface HumanFixtures {\n /**\n * A {@link Human} bound to the test's `page`. Created fresh per test; by\n * default seeded from the test title and run instant in CI, humanized\n * locally. Tune via the `humanOptions` option.\n */\n human: Human;\n}\n\n/** Option fixture to customize the per-test {@link Human}. */\nexport interface HumanOptions {\n /**\n * Options forwarded to `createHuman` for the `human` fixture. Set with\n * `test.use({ humanOptions: { … } })` (per file) or in `playwright.config.ts`\n * `use` (per project). Defaults: `seed` = the test title, `speed` =\n * `'instant'` in CI else `'human'`. Anything you set here overrides those.\n */\n humanOptions: CreateHumanOptions;\n}\n\n/**\n * Playwright `test` extended with the `human` fixture. Drop-in replacement\n * for `@playwright/test`'s `test`.\n */\nexport const test = base.extend<HumanFixtures & HumanOptions>({\n humanOptions: [{}, { option: true }],\n human: async ({ page, humanOptions }, use, testInfo) => {\n const human = await createHuman(page, {\n // Deterministic per test, CI-fast by default — both overridable since\n // the spread comes last.\n seed: testInfo.title,\n speed: process.env.CI ? 'instant' : 'human',\n // No cursor overlay in CI (instant) so it never lands in test DOM or\n // screenshots; shown locally where you actually watch the run.\n cursor: !process.env.CI,\n ...humanOptions,\n });\n await use(human);\n },\n});\n\nexport { expect } from '@playwright/test';\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humanjs/playwright",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Humanize Playwright sessions for AI agents, QA tests, and demos.",
5
5
  "keywords": [
6
6
  "humanjs",
@@ -63,7 +63,7 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "ffmpeg-static": "^5.2.0",
66
- "@humanjs/core": "0.7.0"
66
+ "@humanjs/core": "0.8.0"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "playwright": ">=1.49.0",