@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.
- package/README.md +25 -7
- package/dist/assert/expect.d.ts +1 -1
- package/dist/assert/expect.js +1 -1
- package/dist/{chunk-M5G6EMAS.js → chunk-EIAXMGD5.js} +639 -69
- package/dist/chunk-EIAXMGD5.js.map +1 -0
- package/dist/cli.js +964 -120
- package/dist/cli.js.map +1 -1
- package/dist/{expect-BY8vnFfi.d.ts → expect-Cd5SNFuF.d.ts} +113 -7
- package/dist/index.d.ts +25 -4
- package/dist/index.js +53 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-M5G6EMAS.js.map +0 -1
|
@@ -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
|
|
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
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
267
|
-
private selector;
|
|
371
|
+
private target;
|
|
268
372
|
private options;
|
|
269
373
|
private negate;
|
|
270
374
|
private events;
|
|
271
|
-
constructor(
|
|
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-
|
|
2
|
-
export { F as Frame, b as Locator, e as expect } from './expect-
|
|
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
|
-
|
|
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-
|
|
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
|
-
|
|
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;
|