@unotest/web 0.43.2 → 0.44.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.
@@ -1,6 +1,6 @@
1
1
  import { InjectedDomHelpers } from '@unotest/grounder-client/dom-walker';
2
2
  import { PickerMode } from '@unotest/protocol';
3
- import { E as ElementHint } from '../interfaces-ClW2IRgY.js';
3
+ import { E as ElementHint } from '../interfaces-DEmGI704.js';
4
4
  import '../config/schema.js';
5
5
  import 'zod';
6
6
 
@@ -91,13 +91,27 @@ interface LaunchOptions {
91
91
  /** Extra browser command-line arguments (`config.launch.args`). */
92
92
  args?: string[];
93
93
  }
94
- interface Viewport {
94
+ interface ViewportSize {
95
95
  width: number;
96
96
  height: number;
97
97
  }
98
+ /** What a context is asked to look like. Each field left out comes from
99
+ * the device preset, or from DEFAULT_VIEWPORT when there is none. */
100
+ interface Viewport extends Partial<ViewportSize> {
101
+ /** Device pixels per CSS pixel. Fixed for the life of a context. */
102
+ deviceScaleFactor?: number;
103
+ }
98
104
  interface ContextOptions {
99
105
  baseUrl?: string;
106
+ /** A device preset by name — the driver owns the list and refuses a
107
+ * name it does not know. Applied before `viewport`, which overrides the
108
+ * preset's size and scale field by field. */
109
+ device?: string;
100
110
  viewport?: Viewport;
111
+ /** Put a fake clock on the context before its first page loads, so that
112
+ * every timer the pages set is under `DriverContext.clock()`. Off by
113
+ * default: time on the page is the real one. */
114
+ clock?: boolean;
101
115
  /** Path to storageState JSON (D-23 caching, optional). */
102
116
  storageState?: string;
103
117
  /** Per-context override for dialog policy. Defaults to config.dialogPolicy. */
@@ -231,11 +245,34 @@ interface ScreenshotOptions {
231
245
  * as `png`. `webp` needs Playwright 1.62+, which is why the package
232
246
  * pins that floor. */
233
247
  type?: "png" | "jpeg" | "webp";
248
+ /** `"disabled"` — CSS animations and transitions are finished first, so
249
+ * two captures of the same page are the same picture (the visual
250
+ * assert). Default: as Playwright, animations run. */
251
+ animations?: "disabled" | "allow";
252
+ /** `"hide"` — the text caret is not drawn (it blinks). Default `"initial"`. */
253
+ caret?: "hide" | "initial";
234
254
  }
235
255
  /** Encoding options for an element capture — `ScreenshotOptions` minus
236
256
  * the page-geometry fields (`fullPage`, `clip`) that have no meaning for a
237
257
  * single element. */
238
- type ElementScreenshotOptions = Pick<ScreenshotOptions, "type" | "quality">;
258
+ type ElementScreenshotOptions = Pick<ScreenshotOptions, "type" | "quality" | "animations" | "caret">;
259
+ /** A rectangle in the PIXELS of a capture (device pixels, the capture's own
260
+ * origin) — where an element lies in a screenshot. */
261
+ interface CaptureRect {
262
+ x: number;
263
+ y: number;
264
+ width: number;
265
+ height: number;
266
+ }
267
+ /** Which capture a `CaptureRect` is measured in. */
268
+ type CaptureFrame = {
269
+ kind: "viewport";
270
+ } | {
271
+ kind: "fullPage";
272
+ } | {
273
+ kind: "element";
274
+ loc: LocatorValue;
275
+ };
239
276
  interface CookieOptions {
240
277
  domain?: string;
241
278
  path?: string;
@@ -250,7 +287,12 @@ interface CookieOptions {
250
287
  * dismisses every dialog on behalf of the client that has none — and a
251
288
  * second client watching the run's page would answer `confirm()` with
252
289
  * "no" before the run's own accept lands. */
253
- type AttachOptions = Pick<ContextOptions, "dialogPolicy">;
290
+ interface AttachOptions extends Pick<ContextOptions, "dialogPolicy"> {
291
+ /** The browser's id of the context to attach to (CDP `browserContextId`,
292
+ * as the run publishes it). Unset, or not found → the first context
293
+ * with an open page, as before. */
294
+ contextId?: string;
295
+ }
254
296
 
255
297
  interface WebDriver {
256
298
  /**
@@ -280,7 +322,7 @@ interface WebDriver {
280
322
  */
281
323
  wsEndpoint(): string | undefined;
282
324
  connectShared(wsEndpoint: string, browser: LaunchOptions["browser"]): Promise<void>;
283
- attachExisting(opts?: AttachOptions): DriverContext;
325
+ attachExisting(opts?: AttachOptions): Promise<DriverContext>;
284
326
  }
285
327
  /** One captured network request/response, recorded only under
286
328
  * `UNOTEST_NETWORK`. `status`/`ok` come from the response; `failureText`
@@ -299,6 +341,21 @@ interface NetworkEntry {
299
341
  durationMs?: number;
300
342
  timestamp: string;
301
343
  }
344
+ /** A fake clock shared by every page of a context. Time runs by itself
345
+ * until `freeze`, and again after `run`. */
346
+ interface DriverClock {
347
+ /** Stop time at `at`: `Date` reads it, and no timer fires until `tick`
348
+ * or `run`. Any instant, past or future — no timer fires on the way. */
349
+ freeze(at: Date): Promise<void>;
350
+ /** Advance frozen time by `ms`, firing every timer due in it. */
351
+ tick(ms: number): Promise<void>;
352
+ /** Let time run again from where it stands. */
353
+ run(): Promise<void>;
354
+ /** Whether time stands still now (after `freeze`, before `run`). While
355
+ * it does, `requestAnimationFrame` does not fire either — a wait for a
356
+ * painted frame would wait for nothing. */
357
+ frozen(): boolean;
358
+ }
302
359
  interface DriverContext {
303
360
  /** Currently-open tabs/windows in this context. Index 0 = first opened. */
304
361
  pages(): ReadonlyArray<DriverPage>;
@@ -334,6 +391,22 @@ interface DriverContext {
334
391
  * before auto-switching to a popup (frame scope does not survive tab
335
392
  * changes). */
336
393
  frameDepth(): number;
394
+ /**
395
+ * Resize every open page of this context, and every page it opens after
396
+ * this call. Width and height only: the device scale factor is fixed when
397
+ * the context is created — changing it would mean a new context and the
398
+ * loss of the page, which a resize must never cost.
399
+ */
400
+ setViewport(size: ViewportSize): Promise<void>;
401
+ /** The browser's own id of this context (CDP `browserContextId`), the
402
+ * same in every process connected to the browser — or null where the
403
+ * engine has no such id to give (Firefox, WebKit) or no page is open. */
404
+ browserContextId(): Promise<string | null>;
405
+ /** The page clock. Works only on a context opened with `clock: true`
406
+ * (the fake clock must be in place before the first page loads, or the
407
+ * page's own timers stay real) — otherwise every call throws
408
+ * ClockNotInstalledError. */
409
+ clock(): DriverClock;
337
410
  /** Typed storage shortcuts (D-6). */
338
411
  setLocalStorage(key: string, value: string): Promise<void>;
339
412
  getLocalStorage(key: string): Promise<string | null>;
@@ -443,6 +516,13 @@ interface DriverPage {
443
516
  * viewport — the evidence shot of a card / row / dialog. Same encoding
444
517
  * options as `screenshot`; `fullPage` / `clip` don't apply. */
445
518
  screenshotElement(loc: LocatorValue, opts?: ElementScreenshotOptions): Promise<Buffer>;
519
+ /** Where each element lies in a capture of `frame`, in that capture's
520
+ * pixels (device pixel ratio, page scroll and the element's own box
521
+ * applied) — the masks of the visual assert. Each locator must match
522
+ * exactly one element (a locator that matches none is an error, not a
523
+ * skipped mask); an element that is not rendered has no box and is
524
+ * left out. */
525
+ boxesInCapture(locs: readonly LocatorValue[], frame: CaptureFrame): Promise<CaptureRect[]>;
446
526
  inspectElement(loc: LocatorValue, opts?: InspectElementOptions): Promise<ElementHint | null>;
447
527
  /** HTML of the element the locator matches (first match), redacted like
448
528
  * page.html — secret and hidden field values and script content become
@@ -565,4 +645,4 @@ interface AncestorHint {
565
645
  className?: string;
566
646
  }
567
647
 
568
- export { type AttachOptions as A, type ContextOptions as C, type DriverContext as D, type ElementHint as E, type FillOptions as F, type GotoOptions as G, type HoverOptions as H, type LaunchOptions as L, type NetworkEntry as N, type PressOptions as P, type ReloadOptions as R, type ScreenshotOptions as S, type Viewport as V, type WebDriver as W, type ActionTimeout as a, type CheckOptions as b, type ClickOptions as c, type CookieOptions as d, type DriverPage as e, type NavigationOptions as f, type SelectOptions as g, type WaitOptions as h, type WaitState as i, type LocatorValue as j, type LocatorStep as k, appendStep as l, describeLocator as m, isLocatorValue as n, rootedAt as r };
648
+ export { type AttachOptions as A, type CaptureFrame as C, type DriverContext as D, type ElementHint as E, type FillOptions as F, type GotoOptions as G, type HoverOptions as H, type LocatorValue as L, type NetworkEntry as N, type PressOptions as P, type ReloadOptions as R, type ScreenshotOptions as S, type Viewport as V, type WebDriver as W, type CaptureRect as a, type LaunchOptions as b, type ContextOptions as c, type ActionTimeout as d, type CheckOptions as e, type ClickOptions as f, type CookieOptions as g, type DriverPage as h, type NavigationOptions as i, type SelectOptions as j, type ViewportSize as k, type WaitOptions as l, type WaitState as m, type LocatorStep as n, appendStep as o, describeLocator as p, isLocatorValue as q, rootedAt as r };