@toolstackhq/cdpwright 1.1.0 → 1.3.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.
@@ -71,12 +71,40 @@ declare class AutomationEvents {
71
71
  emit<K extends keyof AutomationEventMap>(event: K, payload: AutomationEventMap[K]): void;
72
72
  }
73
73
 
74
- type LocatorOptions = {};
74
+ type SelectorLocatorOptions = {
75
+ pierceShadowDom?: boolean;
76
+ timeoutMs?: number;
77
+ };
78
+ type TextLocatorOptions$1 = {
79
+ exact?: boolean;
80
+ timeoutMs?: number;
81
+ };
82
+ type RoleLocatorOptions$1 = {
83
+ name?: string | RegExp;
84
+ exact?: boolean;
85
+ includeHidden?: boolean;
86
+ timeoutMs?: number;
87
+ };
88
+ type LocatorQuery = {
89
+ kind: "selector";
90
+ selector: string;
91
+ options?: SelectorLocatorOptions;
92
+ } | {
93
+ kind: "text";
94
+ text: string | RegExp;
95
+ options?: TextLocatorOptions$1;
96
+ } | {
97
+ kind: "role";
98
+ role: string;
99
+ options?: RoleLocatorOptions$1;
100
+ };
75
101
  declare class Locator {
76
102
  private frame;
77
- private selector;
78
- private options;
79
- constructor(frame: Frame, selector: string, options?: LocatorOptions);
103
+ private query;
104
+ constructor(frame: Frame, query: LocatorQuery);
105
+ getEvents(): AutomationEvents;
106
+ getFrameId(): string;
107
+ describe(): string;
80
108
  click(options?: {
81
109
  timeoutMs?: number;
82
110
  }): Promise<void>;
@@ -87,13 +115,35 @@ declare class Locator {
87
115
  timeoutMs?: number;
88
116
  }): Promise<void>;
89
117
  exists(): Promise<boolean>;
118
+ isVisible(): Promise<boolean | null>;
119
+ isEnabled(): Promise<boolean | null>;
120
+ isChecked(): Promise<boolean | null>;
90
121
  text(): Promise<string | null>;
122
+ value(): Promise<string | null>;
123
+ attribute(name: string): Promise<string | null>;
124
+ classes(): Promise<string[] | null>;
125
+ css(property: string): Promise<string | null>;
126
+ hasFocus(): Promise<boolean | null>;
127
+ isInViewport(fully?: boolean): Promise<boolean | null>;
128
+ isEditable(): Promise<boolean | null>;
129
+ count(): Promise<number>;
130
+ private queryTimeoutOptions;
91
131
  }
92
132
 
93
133
  type FrameSelectorOptions = {
94
134
  pierceShadowDom?: boolean;
95
135
  timeoutMs?: number;
96
136
  };
137
+ type TextLocatorOptions = {
138
+ exact?: boolean;
139
+ timeoutMs?: number;
140
+ };
141
+ type RoleLocatorOptions = {
142
+ name?: string | RegExp;
143
+ exact?: boolean;
144
+ includeHidden?: boolean;
145
+ timeoutMs?: number;
146
+ };
97
147
  type ClickOptions = {
98
148
  timeoutMs?: number;
99
149
  };
@@ -123,12 +173,15 @@ declare class Frame {
123
173
  url?: string;
124
174
  parentId?: string;
125
175
  }): void;
176
+ getEvents(): AutomationEvents;
126
177
  evaluate<T = unknown>(fnOrString: string | ((...args: any[]) => any), ...args: any[]): Promise<T>;
127
178
  query(selector: string, options?: FrameSelectorOptions): Promise<QueryResult | null>;
128
179
  queryAll(selector: string, options?: FrameSelectorOptions): Promise<QueryResult[]>;
129
180
  queryXPath(selector: string, options?: FrameSelectorOptions): Promise<QueryResult | null>;
130
181
  queryAllXPath(selector: string, options?: FrameSelectorOptions): Promise<QueryResult[]>;
131
182
  locator(selector: string, options?: FrameSelectorOptions): Locator;
183
+ getByText(text: string | RegExp, options?: TextLocatorOptions): Locator;
184
+ getByRole(role: string, options?: RoleLocatorOptions): Locator;
132
185
  click(selector: string, options?: ClickOptions): Promise<void>;
133
186
  dblclick(selector: string, options?: ClickOptions): Promise<void>;
134
187
  type(selector: string, text: string, options?: TypeOptions): Promise<void>;
@@ -145,6 +198,22 @@ declare class Frame {
145
198
  private writeLocatorHtml;
146
199
  exists(selector: string, options?: FrameSelectorOptions): Promise<boolean>;
147
200
  isVisible(selector: string, options?: FrameSelectorOptions): Promise<boolean>;
201
+ clickLocator(query: LocatorQuery, options?: ClickOptions): Promise<void>;
202
+ dblclickLocator(query: LocatorQuery, options?: ClickOptions): Promise<void>;
203
+ typeLocator(query: LocatorQuery, text: string, options?: TypeOptions): Promise<void>;
204
+ existsLocator(query: LocatorQuery): Promise<boolean>;
205
+ isVisibleLocator(query: LocatorQuery): Promise<boolean | null>;
206
+ isEnabledLocator(query: LocatorQuery): Promise<boolean | null>;
207
+ isCheckedLocator(query: LocatorQuery): Promise<boolean | null>;
208
+ textLocator(query: LocatorQuery): Promise<string | null>;
209
+ valueLocator(query: LocatorQuery): Promise<string | null>;
210
+ attributeLocator(query: LocatorQuery, name: string): Promise<string | null>;
211
+ classesLocator(query: LocatorQuery): Promise<string[] | null>;
212
+ cssLocator(query: LocatorQuery, property: string): Promise<string | null>;
213
+ hasFocusLocator(query: LocatorQuery): Promise<boolean | null>;
214
+ isInViewportLocator(query: LocatorQuery, fully?: boolean): Promise<boolean | null>;
215
+ isEditableLocator(query: LocatorQuery): Promise<boolean | null>;
216
+ countLocator(query: LocatorQuery): Promise<number>;
148
217
  text(selector: string, options?: FrameSelectorOptions): Promise<string | null>;
149
218
  textSecure(selector: string, options?: FrameSelectorOptions): Promise<string | null>;
150
219
  selectOption(selector: string, value: string): Promise<void>;
@@ -162,6 +231,13 @@ declare class Frame {
162
231
  hasFocus(selector: string, options?: FrameSelectorOptions): Promise<boolean | null>;
163
232
  isInViewport(selector: string, options?: FrameSelectorOptions, fully?: boolean): Promise<boolean | null>;
164
233
  isEditable(selector: string, options?: FrameSelectorOptions): Promise<boolean | null>;
234
+ private performClickLocator;
235
+ private locatorDescription;
236
+ private resolveLocatorElementBox;
237
+ private evalOnLocator;
238
+ private buildLocatorExpression;
239
+ private serializeLocatorQuery;
240
+ private serializeTextQuery;
165
241
  private performClick;
166
242
  private resolveElementBox;
167
243
  private querySelectorInternal;
@@ -215,6 +291,16 @@ declare class Page {
215
291
  predicate?: (frame: Frame) => boolean;
216
292
  }): Frame | null;
217
293
  locator(selector: string): Locator;
294
+ getByText(text: string | RegExp, options?: {
295
+ exact?: boolean;
296
+ timeoutMs?: number;
297
+ }): Locator;
298
+ getByRole(role: string, options?: {
299
+ name?: string | RegExp;
300
+ exact?: boolean;
301
+ includeHidden?: boolean;
302
+ timeoutMs?: number;
303
+ }): Locator;
218
304
  goto(url: string, options?: GotoOptions): Promise<void>;
219
305
  query(selector: string): Promise<QueryResult | null>;
220
306
  queryAll(selector: string): Promise<QueryResult[]>;
@@ -242,11 +328,13 @@ declare class Page {
242
328
  setFileInput(selector: string, name: string, contents: string, options?: {
243
329
  mimeType?: string;
244
330
  }): Promise<void>;
331
+ content(): Promise<string>;
245
332
  screenshot(options?: ScreenshotOptions): Promise<Buffer<ArrayBuffer>>;
246
333
  screenshotBase64(options?: Omit<ScreenshotOptions, "path">): Promise<string>;
247
334
  pdf(options?: PdfOptions): Promise<Buffer>;
248
335
  getEvents(): AutomationEvents;
249
336
  getDefaultTimeout(): number;
337
+ waitForLoad(timeoutMs?: number): Promise<void>;
250
338
  private buildFrameTree;
251
339
  private ensureFrame;
252
340
  private onFrameAttached;
@@ -262,13 +350,29 @@ declare class Page {
262
350
  type ExpectSelectorOptions = {
263
351
  timeoutMs?: number;
264
352
  };
353
+ type ExpectTarget = {
354
+ label: string;
355
+ frameId: string;
356
+ exists(): Promise<boolean>;
357
+ isVisible(): Promise<boolean | null>;
358
+ isEnabled(): Promise<boolean | null>;
359
+ isChecked(): Promise<boolean | null>;
360
+ text(): Promise<string | null>;
361
+ value(): Promise<string | null>;
362
+ attribute(name: string): Promise<string | null>;
363
+ count(): Promise<number>;
364
+ classes(): Promise<string[] | null>;
365
+ css(property: string): Promise<string | null>;
366
+ hasFocus(): Promise<boolean | null>;
367
+ isInViewport(fully?: boolean): Promise<boolean | null>;
368
+ isEditable(): Promise<boolean | null>;
369
+ };
265
370
  declare class ElementExpectation {
266
- private frame;
267
- private selector;
371
+ private target;
268
372
  private options;
269
373
  private negate;
270
374
  private events;
271
- constructor(frame: Frame, selector: string, options: ExpectSelectorOptions, negate: boolean, events: AutomationEvents);
375
+ constructor(target: ExpectTarget, options: ExpectSelectorOptions, negate: boolean, events: AutomationEvents);
272
376
  get not(): ElementExpectation;
273
377
  toExist(): Promise<void>;
274
378
  toBeVisible(): Promise<void>;
@@ -309,11 +413,13 @@ declare function expect(page: Page): {
309
413
  predicate?: (frame: Frame) => boolean;
310
414
  }) => ExpectFrame;
311
415
  };
416
+ declare function expect(locator: Locator): ElementExpectation;
312
417
 
313
418
  declare module "../core/Page.js" {
314
419
  interface Page {
315
420
  expect(): ReturnType<typeof expect>;
316
421
  expect(selector: string, options?: ExpectSelectorOptions): ElementExpectation;
422
+ expect(locator: Locator): ElementExpectation;
317
423
  find: {
318
424
  locators: (options?: {
319
425
  highlight?: boolean;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Connection, L as Logger, A as AutomationEvents, P as Page, a as LogLevel } from './expect-BY8vnFfi.js';
2
- export { F as Frame, b as Locator, e as expect } from './expect-BY8vnFfi.js';
1
+ import { C as Connection, L as Logger, A as AutomationEvents, P as Page, a as LogLevel } from './expect-Cd5SNFuF.js';
2
+ export { F as Frame, b as Locator, e as expect } from './expect-Cd5SNFuF.js';
3
3
  import { ChildProcess } from 'child_process';
4
4
 
5
5
  declare class BrowserContext {
@@ -17,12 +17,24 @@ declare class Browser {
17
17
  private events;
18
18
  private cleanupTasks;
19
19
  private contexts;
20
- constructor(connection: Connection, child: ChildProcess, logger: Logger, events: AutomationEvents, cleanupTasks?: Array<() => void>);
20
+ readonly wsEndpoint: string;
21
+ readonly pid: number;
22
+ constructor(connection: Connection, child: ChildProcess | null, logger: Logger, events: AutomationEvents, cleanupTasks?: Array<() => void>, wsEndpoint?: string);
21
23
  on(event: "action:start" | "action:end" | "assertion:start" | "assertion:end", handler: (payload: any) => void): void;
22
24
  newContext(): Promise<BrowserContext>;
23
25
  newPage(options?: {
24
26
  browserContextId?: string;
25
27
  }): Promise<Page>;
28
+ /** Attach to an existing page by target ID. */
29
+ attachPage(targetId: string): Promise<Page>;
30
+ /** List open page targets. */
31
+ pages(): Promise<Array<{
32
+ targetId: string;
33
+ url: string;
34
+ title: string;
35
+ }>>;
36
+ /** Disconnect without killing the browser process. */
37
+ disconnect(): Promise<void>;
26
38
  disposeContext(contextId: string): Promise<void>;
27
39
  close(): Promise<void>;
28
40
  }
@@ -54,11 +66,20 @@ declare class AssertionError extends Error {
54
66
  type AutomatonLaunchOptions = LaunchOptions & {
55
67
  logger?: Logger;
56
68
  };
69
+ type ConnectOptions = {
70
+ logLevel?: LogLevel;
71
+ logger?: Logger;
72
+ logEvents?: boolean;
73
+ logActions?: boolean;
74
+ logAssertions?: boolean;
75
+ };
57
76
  declare const automaton: {
58
77
  launch(options?: AutomatonLaunchOptions): Promise<Browser>;
78
+ connect(wsEndpoint: string, options?: ConnectOptions): Promise<Browser>;
59
79
  };
60
80
  declare const chromium: {
61
81
  launch(options?: AutomatonLaunchOptions): Promise<Browser>;
82
+ connect(wsEndpoint: string, options?: ConnectOptions): Promise<Browser>;
62
83
  };
63
84
 
64
- export { AssertionError, AutomationEvents, type AutomatonLaunchOptions, Browser, BrowserContext, LogLevel, Logger, Page, automaton, chromium };
85
+ export { AssertionError, AutomationEvents, type AutomatonLaunchOptions, Browser, BrowserContext, type ConnectOptions, LogLevel, Logger, Page, automaton, chromium };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  Locator,
5
5
  Page,
6
6
  expect
7
- } from "./chunk-M5G6EMAS.js";
7
+ } from "./chunk-EIAXMGD5.js";
8
8
 
9
9
  // src/browser/ChromiumManager.ts
10
10
  import fs2 from "fs";
@@ -292,12 +292,16 @@ var Browser = class {
292
292
  events;
293
293
  cleanupTasks;
294
294
  contexts = /* @__PURE__ */ new Set();
295
- constructor(connection, child, logger, events, cleanupTasks = []) {
295
+ wsEndpoint;
296
+ pid;
297
+ constructor(connection, child, logger, events, cleanupTasks = [], wsEndpoint = "") {
296
298
  this.connection = connection;
297
299
  this.process = child;
298
300
  this.logger = logger;
299
301
  this.events = events;
300
302
  this.cleanupTasks = cleanupTasks;
303
+ this.wsEndpoint = wsEndpoint;
304
+ this.pid = child?.pid ?? 0;
301
305
  }
302
306
  on(event, handler) {
303
307
  this.events.on(event, handler);
@@ -319,6 +323,23 @@ var Browser = class {
319
323
  await page.initialize();
320
324
  return page;
321
325
  }
326
+ /** Attach to an existing page by target ID. */
327
+ async attachPage(targetId) {
328
+ const { sessionId } = await this.connection.send("Target.attachToTarget", { targetId, flatten: true });
329
+ const session = this.connection.createSession(sessionId);
330
+ const page = new Page(session, this.logger, this.events);
331
+ await page.initialize();
332
+ return page;
333
+ }
334
+ /** List open page targets. */
335
+ async pages() {
336
+ const result = await this.connection.send("Target.getTargets");
337
+ return result.targetInfos.filter((t) => t.type === "page").map((t) => ({ targetId: t.targetId, url: t.url, title: t.title }));
338
+ }
339
+ /** Disconnect without killing the browser process. */
340
+ async disconnect() {
341
+ await this.connection.close();
342
+ }
322
343
  async disposeContext(contextId) {
323
344
  if (!contextId) return;
324
345
  try {
@@ -338,7 +359,7 @@ var Browser = class {
338
359
  } catch {
339
360
  }
340
361
  await this.connection.close();
341
- if (!this.process.killed) {
362
+ if (this.process && !this.process.killed) {
342
363
  this.process.kill();
343
364
  }
344
365
  for (const task of this.cleanupTasks) {
@@ -680,6 +701,7 @@ var ChromiumManager = class {
680
701
  }
681
702
  if (options.maximize) {
682
703
  args.push("--start-maximized");
704
+ args.push("--window-size=1920,1080");
683
705
  }
684
706
  if (options.args) {
685
707
  args.push(...options.args);
@@ -708,7 +730,7 @@ var ChromiumManager = class {
708
730
  logger.info(`Assertion ${payload.name}`, ...args2);
709
731
  });
710
732
  }
711
- const browser = new Browser(connection, child, logger, events, cleanupTasks);
733
+ const browser = new Browser(connection, child, logger, events, cleanupTasks, wsEndpoint);
712
734
  return browser;
713
735
  }
714
736
  resolveCacheRoot(platform) {
@@ -873,6 +895,33 @@ var automaton = {
873
895
  async launch(options = {}) {
874
896
  const manager = new ChromiumManager(options.logger);
875
897
  return manager.launch(options);
898
+ },
899
+ async connect(wsEndpoint, options = {}) {
900
+ const logger = options.logger ?? new Logger(options.logLevel ?? "warn");
901
+ const connection = new Connection(wsEndpoint, logger);
902
+ await connection.waitForOpen();
903
+ const events = new AutomationEvents();
904
+ const logEvents = options.logEvents ?? true;
905
+ const logActions = options.logActions ?? true;
906
+ const logAssertions = options.logAssertions ?? true;
907
+ if (logEvents && logActions) {
908
+ events.on("action:end", (payload) => {
909
+ const selector = payload.sensitive ? void 0 : payload.selector;
910
+ const args = [];
911
+ if (selector) args.push(selector);
912
+ if (typeof payload.durationMs === "number") args.push(`${payload.durationMs}ms`);
913
+ logger.info(`Action ${payload.name}`, ...args);
914
+ });
915
+ }
916
+ if (logEvents && logAssertions) {
917
+ events.on("assertion:end", (payload) => {
918
+ const args = [];
919
+ if (payload.selector) args.push(payload.selector);
920
+ if (typeof payload.durationMs === "number") args.push(`${payload.durationMs}ms`);
921
+ logger.info(`Assertion ${payload.name}`, ...args);
922
+ });
923
+ }
924
+ return new Browser(connection, null, logger, events, [], wsEndpoint);
876
925
  }
877
926
  };
878
927
  var chromium = automaton;