@tstdl/base 0.87.1 → 0.87.3
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/browser/browser-context-controller.d.ts +12 -2
- package/browser/browser-context-controller.js +32 -1
- package/browser/document-controller.d.ts +15 -9
- package/browser/document-controller.js +37 -28
- package/browser/element-controller.d.ts +26 -8
- package/browser/element-controller.js +73 -38
- package/browser/frame-controller.d.ts +5 -9
- package/browser/frame-controller.js +6 -9
- package/browser/module.js +3 -0
- package/browser/page-controller.d.ts +14 -6
- package/browser/page-controller.js +68 -5
- package/browser/types.d.ts +5 -0
- package/browser/utils.d.ts +3 -0
- package/browser/utils.js +17 -1
- package/examples/browser/basic.d.ts +1 -1
- package/examples/browser/basic.js +1 -0
- package/function/log.d.ts +1 -1
- package/function/log.js +10 -4
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { BrowserContext } from 'playwright';
|
|
1
|
+
import type { BrowserContext, Page } from 'playwright';
|
|
2
2
|
import type { AsyncDisposable } from '../disposable/disposable.js';
|
|
3
3
|
import { disposeAsync } from '../disposable/disposable.js';
|
|
4
4
|
import type { Resolvable } from '../injector/interfaces.js';
|
|
5
|
-
import { resolveArgumentType } from '../injector/interfaces.js';
|
|
5
|
+
import { afterResolve, resolveArgumentType } from '../injector/interfaces.js';
|
|
6
6
|
import type { Logger } from '../logger/logger.js';
|
|
7
7
|
import type { Record } from '../types.js';
|
|
8
8
|
import type { Tagged } from 'type-fest';
|
|
@@ -19,12 +19,22 @@ export type NewPageOptions = {
|
|
|
19
19
|
export type BrowserContextState = Tagged<Record<string | number, unknown>, 'BrowserContextState'>;
|
|
20
20
|
export type BrowserContextControllerArgument = NewBrowserContextOptions;
|
|
21
21
|
export declare class BrowserContextController implements AsyncDisposable, Resolvable<BrowserContextControllerArgument> {
|
|
22
|
+
#private;
|
|
22
23
|
/** @deprecated should be avoided */
|
|
23
24
|
readonly context: BrowserContext;
|
|
24
25
|
readonly options: BrowserContextControllerOptions;
|
|
25
26
|
readonly [resolveArgumentType]: BrowserContextControllerArgument;
|
|
26
27
|
constructor(context: BrowserContext, options?: BrowserContextControllerOptions);
|
|
28
|
+
[afterResolve](): void;
|
|
29
|
+
initialize(): void;
|
|
27
30
|
[disposeAsync](): Promise<void>;
|
|
31
|
+
pages(): PageController[];
|
|
32
|
+
/**
|
|
33
|
+
* Get a controller for the page.
|
|
34
|
+
* @param page page to get controller for
|
|
35
|
+
* @param options options to use for the page controller *if* it is new. Ignored if there is already a controller associated.
|
|
36
|
+
*/
|
|
37
|
+
getControllerByPage(page: Page, options?: PageControllerOptions): PageController;
|
|
28
38
|
close(): Promise<void>;
|
|
29
39
|
getState(): Promise<BrowserContextState>;
|
|
30
40
|
setExtraHttpHeaders(headers: Record<string, string | undefined>): Promise<void>;
|
|
@@ -44,6 +44,7 @@ var __metadata = function(k, v) {
|
|
|
44
44
|
return Reflect.metadata(k, v);
|
|
45
45
|
};
|
|
46
46
|
let BrowserContextController = class BrowserContextController2 {
|
|
47
|
+
#pageControllers = /* @__PURE__ */ new WeakMap();
|
|
47
48
|
/** @deprecated should be avoided */
|
|
48
49
|
context;
|
|
49
50
|
options;
|
|
@@ -51,9 +52,38 @@ let BrowserContextController = class BrowserContextController2 {
|
|
|
51
52
|
this.context = context;
|
|
52
53
|
this.options = options;
|
|
53
54
|
}
|
|
55
|
+
[import_interfaces.afterResolve]() {
|
|
56
|
+
this.initialize();
|
|
57
|
+
}
|
|
58
|
+
initialize() {
|
|
59
|
+
this.context.on("page", (page) => {
|
|
60
|
+
page.once("close", () => this.#pageControllers.delete(page));
|
|
61
|
+
});
|
|
62
|
+
}
|
|
54
63
|
async [import_disposable.disposeAsync]() {
|
|
55
64
|
await this.close();
|
|
56
65
|
}
|
|
66
|
+
pages() {
|
|
67
|
+
const pages = this.context.pages();
|
|
68
|
+
return pages.map((page) => this.getControllerByPage(page));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get a controller for the page.
|
|
72
|
+
* @param page page to get controller for
|
|
73
|
+
* @param options options to use for the page controller *if* it is new. Ignored if there is already a controller associated.
|
|
74
|
+
*/
|
|
75
|
+
getControllerByPage(page, options) {
|
|
76
|
+
if (page.context() != this.context) {
|
|
77
|
+
throw new Error("Page is not from this context.");
|
|
78
|
+
}
|
|
79
|
+
const existingController = this.#pageControllers.get(page);
|
|
80
|
+
if ((0, import_type_guards.isDefined)(existingController)) {
|
|
81
|
+
return existingController;
|
|
82
|
+
}
|
|
83
|
+
const newController = new import_page_controller.PageController(page, this, { ...this.options.defaultNewPageOptions?.controllerOptions, ...options });
|
|
84
|
+
this.#pageControllers.set(page, newController);
|
|
85
|
+
return newController;
|
|
86
|
+
}
|
|
57
87
|
async close() {
|
|
58
88
|
await this.context.close();
|
|
59
89
|
}
|
|
@@ -68,7 +98,8 @@ let BrowserContextController = class BrowserContextController2 {
|
|
|
68
98
|
async newPage(options) {
|
|
69
99
|
const page = await this.context.newPage();
|
|
70
100
|
const mergedOptions = { ...this.options.defaultNewPageOptions, ...options };
|
|
71
|
-
const controller = new import_page_controller.PageController(page, mergedOptions.controllerOptions);
|
|
101
|
+
const controller = new import_page_controller.PageController(page, this, mergedOptions.controllerOptions);
|
|
102
|
+
this.#pageControllers.set(page, controller);
|
|
72
103
|
if ((0, import_type_guards.isDefined)(mergedOptions.extraHttpHeaders)) {
|
|
73
104
|
await controller.setExtraHttpHeaders(mergedOptions.extraHttpHeaders);
|
|
74
105
|
}
|
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import type { ElementHandle, Frame, FrameLocator, Page } from 'playwright';
|
|
2
|
-
import type {
|
|
2
|
+
import type { BrowserContextController } from './browser-context-controller.js';
|
|
3
3
|
import { ElementController } from './element-controller.js';
|
|
4
4
|
import type { FrameController, FrameControllerOptions } from './frame-controller.js';
|
|
5
5
|
import { LocatorController } from './locator-controller.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { Delay } from './types.js';
|
|
7
7
|
export type DocumentControllerOptions = {
|
|
8
8
|
defaultActionDelay?: Delay;
|
|
9
9
|
defaultTypeDelay?: Delay;
|
|
10
10
|
};
|
|
11
|
-
export
|
|
12
|
-
pageControllerOptions: PageControllerOptions;
|
|
13
|
-
frameControllerOptions: FrameControllerOptions;
|
|
14
|
-
};
|
|
11
|
+
export declare function setFrameControllerConstructor(constructor: typeof FrameController): void;
|
|
15
12
|
export declare class DocumentController<T extends Page | Frame = Page | Frame> extends LocatorController<T> {
|
|
16
|
-
|
|
13
|
+
#private;
|
|
17
14
|
/** @deprecated should be avoided */
|
|
18
15
|
readonly document: T;
|
|
19
|
-
|
|
16
|
+
readonly context: BrowserContextController;
|
|
17
|
+
readonly options: DocumentControllerOptions;
|
|
18
|
+
constructor(document: T, context: BrowserContextController, options: DocumentControllerOptions);
|
|
19
|
+
frames(): FrameController[];
|
|
20
|
+
/**
|
|
21
|
+
* Get a controller for the frame.
|
|
22
|
+
* @param frame frame to get controller for
|
|
23
|
+
* @param options options to use for the frame controller *if* it is new. Ignored if there is already a controller associated.
|
|
24
|
+
*/
|
|
25
|
+
getControllerByFrame(frame: Frame, options?: FrameControllerOptions): FrameController;
|
|
20
26
|
setContent(...args: Parameters<Page['setContent']>): Promise<void>;
|
|
21
27
|
navigate(...args: Parameters<Page['goto']>): Promise<void>;
|
|
22
28
|
waitForLoadState(...args: Parameters<Page['waitForLoadState']>): Promise<void>;
|
|
23
29
|
waitForUrl(...args: Parameters<Page['waitForURL']>): Promise<void>;
|
|
24
30
|
waitForElement(selector: string, options?: Parameters<Page['waitForSelector']>[1]): Promise<ElementController<ElementHandle<SVGElement | HTMLElement>>>;
|
|
25
31
|
locateInFrame(frameSelector: string): LocatorController<FrameLocator>;
|
|
26
|
-
waitForFrame(selector: string, options?: Parameters<Page['waitForSelector']>[1]): Promise<FrameController>;
|
|
32
|
+
waitForFrame(selector: string, options?: Parameters<Page['waitForSelector']>[1], controllerOptions?: FrameControllerOptions): Promise<FrameController>;
|
|
27
33
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,31 +15,54 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
var document_controller_exports = {};
|
|
30
20
|
__export(document_controller_exports, {
|
|
31
|
-
DocumentController: () => DocumentController
|
|
21
|
+
DocumentController: () => DocumentController,
|
|
22
|
+
setFrameControllerConstructor: () => setFrameControllerConstructor
|
|
32
23
|
});
|
|
33
24
|
module.exports = __toCommonJS(document_controller_exports);
|
|
34
25
|
var import_type_guards = require("../utils/type-guards.js");
|
|
35
26
|
var import_element_controller = require("./element-controller.js");
|
|
36
27
|
var import_locator_controller = require("./locator-controller.js");
|
|
28
|
+
var import_utils = require("./utils.js");
|
|
29
|
+
let frameControllerConstructor;
|
|
30
|
+
function setFrameControllerConstructor(constructor) {
|
|
31
|
+
frameControllerConstructor = constructor;
|
|
32
|
+
}
|
|
37
33
|
class DocumentController extends import_locator_controller.LocatorController {
|
|
38
|
-
|
|
34
|
+
#frameControllers = /* @__PURE__ */ new WeakMap();
|
|
39
35
|
/** @deprecated should be avoided */
|
|
40
36
|
document;
|
|
41
|
-
|
|
37
|
+
context;
|
|
38
|
+
options;
|
|
39
|
+
constructor(document, context, options) {
|
|
42
40
|
super(document, { actionDelay: options.defaultActionDelay, typeDelay: options.defaultTypeDelay });
|
|
43
41
|
this.document = document;
|
|
44
|
-
this.
|
|
42
|
+
this.context = context;
|
|
43
|
+
this.options = options;
|
|
44
|
+
}
|
|
45
|
+
frames() {
|
|
46
|
+
const frames = (0, import_utils.isPage)(this.document) ? this.document.frames() : this.document.childFrames();
|
|
47
|
+
return frames.map((page) => this.getControllerByFrame(page));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get a controller for the frame.
|
|
51
|
+
* @param frame frame to get controller for
|
|
52
|
+
* @param options options to use for the frame controller *if* it is new. Ignored if there is already a controller associated.
|
|
53
|
+
*/
|
|
54
|
+
getControllerByFrame(frame, options) {
|
|
55
|
+
const documentPage = (0, import_utils.isPage)(this.document) ? this.document : this.document.page();
|
|
56
|
+
if (frame.page() != documentPage) {
|
|
57
|
+
throw new Error("Frame is not from this page.");
|
|
58
|
+
}
|
|
59
|
+
const existingController = this.#frameControllers.get(frame);
|
|
60
|
+
if ((0, import_type_guards.isDefined)(existingController)) {
|
|
61
|
+
return existingController;
|
|
62
|
+
}
|
|
63
|
+
const newController = new frameControllerConstructor(frame, this.context, { ...this.options, ...options });
|
|
64
|
+
this.#frameControllers.set(frame, newController);
|
|
65
|
+
return newController;
|
|
45
66
|
}
|
|
46
67
|
async setContent(...args) {
|
|
47
68
|
await this.document.setContent(...args);
|
|
@@ -66,24 +87,12 @@ class DocumentController extends import_locator_controller.LocatorController {
|
|
|
66
87
|
const locator = this.document.frameLocator(frameSelector);
|
|
67
88
|
return new import_locator_controller.LocatorController(locator, this.elementControllerOptions);
|
|
68
89
|
}
|
|
69
|
-
async waitForFrame(selector, options) {
|
|
90
|
+
async waitForFrame(selector, options, controllerOptions) {
|
|
70
91
|
const element = await this.waitForElement(selector, options);
|
|
71
92
|
const frame = await element.locatorOrHandle.contentFrame();
|
|
72
93
|
if ((0, import_type_guards.isNull)(frame)) {
|
|
73
94
|
throw new Error("Element is not a frame.");
|
|
74
95
|
}
|
|
75
|
-
return
|
|
96
|
+
return this.getControllerByFrame(frame, controllerOptions);
|
|
76
97
|
}
|
|
77
98
|
}
|
|
78
|
-
let frameControllerConstructor;
|
|
79
|
-
async function newFrameController(...args) {
|
|
80
|
-
if ((0, import_type_guards.isUndefined)(frameControllerConstructor)) {
|
|
81
|
-
frameControllerConstructor = importFrameController();
|
|
82
|
-
void frameControllerConstructor.then((constructor) => frameControllerConstructor = constructor);
|
|
83
|
-
}
|
|
84
|
-
return new (await frameControllerConstructor)(...args);
|
|
85
|
-
}
|
|
86
|
-
async function importFrameController() {
|
|
87
|
-
const module2 = await import("./frame-controller.js");
|
|
88
|
-
return module2.FrameController;
|
|
89
|
-
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ElementHandle, Locator } from 'playwright';
|
|
2
2
|
import type { Merge, NonUndefinable, TypedOmit } from '../types.js';
|
|
3
|
-
import type {
|
|
4
|
-
export type Delay = ValueOrProvider<number>;
|
|
5
|
-
export type ActionDelayOptions = {
|
|
6
|
-
actionDelay?: Delay;
|
|
7
|
-
};
|
|
3
|
+
import type { ActionDelayOptions, Delay, TimeoutOptions } from './types.js';
|
|
8
4
|
export type TypeDelayOptions = {
|
|
9
5
|
typeDelay?: Delay;
|
|
10
6
|
};
|
|
@@ -23,6 +19,12 @@ export type Filter = {
|
|
|
23
19
|
hasText?: string | RegExp;
|
|
24
20
|
hasNotText?: string | RegExp;
|
|
25
21
|
};
|
|
22
|
+
export type BoundingBox = {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
26
28
|
export declare class ElementController<T extends Locator | ElementHandle = Locator | ElementHandle> implements Pick<Locator, Methods> {
|
|
27
29
|
readonly locatorOrHandle: T;
|
|
28
30
|
readonly options: ElementControllerOptions;
|
|
@@ -35,6 +37,12 @@ export declare class ElementController<T extends Locator | ElementHandle = Locat
|
|
|
35
37
|
* @param elementController
|
|
36
38
|
*/
|
|
37
39
|
and(elementController: ElementController): ElementController<Locator>;
|
|
40
|
+
/**
|
|
41
|
+
* Get an controller with elements contained in this and the provided controller.
|
|
42
|
+
* Requires locator based controller
|
|
43
|
+
* @param elementController
|
|
44
|
+
*/
|
|
45
|
+
or(elementController: ElementController): ElementController<Locator>;
|
|
38
46
|
/**
|
|
39
47
|
* Filter out elements with by provided filter.
|
|
40
48
|
* Requires locator based controller.
|
|
@@ -45,12 +53,23 @@ export declare class ElementController<T extends Locator | ElementHandle = Locat
|
|
|
45
53
|
* Requires locator based controller.
|
|
46
54
|
*/
|
|
47
55
|
locate(selectorOrController: string | ElementController, filter?: Filter): ElementController<Locator>;
|
|
56
|
+
first(): ElementController<Locator>;
|
|
57
|
+
last(): ElementController<Locator>;
|
|
58
|
+
nth(index: number): ElementController<Locator>;
|
|
59
|
+
evaluate<R, A>(fn: string | ((element: SVGElement | HTMLElement, argument: A) => R | Promise<R>), argument: A): Promise<R>;
|
|
60
|
+
evaluate<R, A>(fn: string | ((element: SVGElement | HTMLElement, argument?: A) => R | Promise<R>), argument?: A): Promise<R>;
|
|
48
61
|
/**
|
|
49
62
|
* Wait for element state
|
|
50
63
|
* @param state some states may only be usable for either locator or handle
|
|
51
64
|
* @param options options
|
|
52
65
|
*/
|
|
53
66
|
waitFor(state?: Parameters<ElementHandle['waitForElementState']>[0] | NonNullable<LocatorOptions<'waitFor', '0'>['state']>, options?: Parameters<ElementHandle['waitForElementState']>[1]): Promise<void>;
|
|
67
|
+
boundingBox(options?: TimeoutOptions): Promise<BoundingBox | null>;
|
|
68
|
+
scrollIntoViewIfNeeded(options?: TimeoutOptions): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Counts matching elements for locator based or returns 1 for handle based.
|
|
71
|
+
*/
|
|
72
|
+
count(): Promise<number>;
|
|
54
73
|
/**
|
|
55
74
|
* Check if element exists
|
|
56
75
|
* @param options.state which state is required in order to be deemed existing
|
|
@@ -58,14 +77,14 @@ export declare class ElementController<T extends Locator | ElementHandle = Locat
|
|
|
58
77
|
*/
|
|
59
78
|
exists(options?: {
|
|
60
79
|
state?: 'visible' | 'attached';
|
|
61
|
-
|
|
62
|
-
}): Promise<boolean>;
|
|
80
|
+
} & TimeoutOptions): Promise<boolean>;
|
|
63
81
|
isVisible(): Promise<boolean>;
|
|
64
82
|
isHidden(): Promise<boolean>;
|
|
65
83
|
isEnabled(): Promise<boolean>;
|
|
66
84
|
isDisabled(): Promise<boolean>;
|
|
67
85
|
isChecked(): Promise<boolean>;
|
|
68
86
|
isEditable(): Promise<boolean>;
|
|
87
|
+
clear(options?: Merge<LocatorOptions<'clear', 1>, ActionDelayOptions>): Promise<void>;
|
|
69
88
|
fill(text: string, options?: Merge<LocatorOptions<'fill', 1>, ActionDelayOptions>): Promise<void>;
|
|
70
89
|
type(text: string, options?: Merge<TypedOmit<LocatorOptions<'type', 1>, 'delay'>, ActionDelayOptions & TypeDelayOptions>): Promise<void>;
|
|
71
90
|
press(key: string, options?: Merge<LocatorOptions<'press', 1>, ActionDelayOptions>): Promise<void>;
|
|
@@ -81,6 +100,5 @@ export declare class ElementController<T extends Locator | ElementHandle = Locat
|
|
|
81
100
|
tap(options?: Merge<LocatorOptions<'tap', 1>, ActionDelayOptions>): Promise<void>;
|
|
82
101
|
selectText(options?: Merge<LocatorOptions<'selectText', 1>, ActionDelayOptions>): Promise<void>;
|
|
83
102
|
inputValue(options?: LocatorOptions<'inputValue', 0>): Promise<string>;
|
|
84
|
-
private prepareAction;
|
|
85
103
|
}
|
|
86
104
|
export {};
|
|
@@ -21,11 +21,10 @@ __export(element_controller_exports, {
|
|
|
21
21
|
ElementController: () => ElementController
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(element_controller_exports);
|
|
24
|
-
var import_timing = require("../utils/timing.js");
|
|
25
24
|
var import_type_guards = require("../utils/type-guards.js");
|
|
26
25
|
var import_value_or_provider = require("../utils/value-or-provider.js");
|
|
27
26
|
var import_utils = require("./utils.js");
|
|
28
|
-
const
|
|
27
|
+
const requiresLocatorBasedController = "Requires a locator based controller";
|
|
29
28
|
class ElementController {
|
|
30
29
|
locatorOrHandle;
|
|
31
30
|
options;
|
|
@@ -53,17 +52,28 @@ class ElementController {
|
|
|
53
52
|
* @param elementController
|
|
54
53
|
*/
|
|
55
54
|
and(elementController) {
|
|
56
|
-
(0, import_utils.assertLocator)(this.locatorOrHandle,
|
|
57
|
-
(0, import_utils.assertLocator)(elementController.locatorOrHandle,
|
|
55
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
56
|
+
(0, import_utils.assertLocator)(elementController.locatorOrHandle, requiresLocatorBasedController);
|
|
58
57
|
const locator = this.locatorOrHandle.and(elementController.locatorOrHandle);
|
|
59
58
|
return new ElementController(locator, this.options);
|
|
60
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Get an controller with elements contained in this and the provided controller.
|
|
62
|
+
* Requires locator based controller
|
|
63
|
+
* @param elementController
|
|
64
|
+
*/
|
|
65
|
+
or(elementController) {
|
|
66
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
67
|
+
(0, import_utils.assertLocator)(elementController.locatorOrHandle, requiresLocatorBasedController);
|
|
68
|
+
const locator = this.locatorOrHandle.or(elementController.locatorOrHandle);
|
|
69
|
+
return new ElementController(locator, this.options);
|
|
70
|
+
}
|
|
61
71
|
/**
|
|
62
72
|
* Filter out elements with by provided filter.
|
|
63
73
|
* Requires locator based controller.
|
|
64
74
|
*/
|
|
65
75
|
filter(filter) {
|
|
66
|
-
(0, import_utils.assertLocator)(this.locatorOrHandle,
|
|
76
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
67
77
|
const locator = this.locatorOrHandle.filter(convertFilter(filter));
|
|
68
78
|
return new ElementController(locator, this.options);
|
|
69
79
|
}
|
|
@@ -72,12 +82,33 @@ class ElementController {
|
|
|
72
82
|
* Requires locator based controller.
|
|
73
83
|
*/
|
|
74
84
|
locate(selectorOrController, filter) {
|
|
75
|
-
(0, import_utils.assertLocator)(this.locatorOrHandle,
|
|
76
|
-
const selector = (0, import_type_guards.isString)(selectorOrController) ? selectorOrController : (0, import_utils.assertLocatorPass)(selectorOrController.locatorOrHandle,
|
|
85
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
86
|
+
const selector = (0, import_type_guards.isString)(selectorOrController) ? selectorOrController : (0, import_utils.assertLocatorPass)(selectorOrController.locatorOrHandle, requiresLocatorBasedController);
|
|
77
87
|
const convertedFilter = (0, import_type_guards.isDefined)(filter) ? convertFilter(filter) : void 0;
|
|
78
88
|
const locator = this.locatorOrHandle.locator(selector, convertedFilter);
|
|
79
89
|
return new ElementController(locator, this.options);
|
|
80
90
|
}
|
|
91
|
+
first() {
|
|
92
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
93
|
+
const locator = this.locatorOrHandle.first();
|
|
94
|
+
return new ElementController(locator, this.options);
|
|
95
|
+
}
|
|
96
|
+
last() {
|
|
97
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
98
|
+
const locator = this.locatorOrHandle.last();
|
|
99
|
+
return new ElementController(locator, this.options);
|
|
100
|
+
}
|
|
101
|
+
nth(index) {
|
|
102
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
103
|
+
const locator = this.locatorOrHandle.nth(index);
|
|
104
|
+
return new ElementController(locator, this.options);
|
|
105
|
+
}
|
|
106
|
+
async evaluate(fn, argument) {
|
|
107
|
+
if ((0, import_utils.isLocator)(this.locatorOrHandle)) {
|
|
108
|
+
return this.locatorOrHandle.evaluate(fn, argument);
|
|
109
|
+
}
|
|
110
|
+
return this.locatorOrHandle.evaluate(fn, argument);
|
|
111
|
+
}
|
|
81
112
|
/**
|
|
82
113
|
* Wait for element state
|
|
83
114
|
* @param state some states may only be usable for either locator or handle
|
|
@@ -89,6 +120,18 @@ class ElementController {
|
|
|
89
120
|
}
|
|
90
121
|
return this.locatorOrHandle.waitForElementState(state, options);
|
|
91
122
|
}
|
|
123
|
+
async boundingBox(options) {
|
|
124
|
+
return this.locatorOrHandle.boundingBox({ timeout: options?.timeout ?? 1e3 });
|
|
125
|
+
}
|
|
126
|
+
async scrollIntoViewIfNeeded(options) {
|
|
127
|
+
await this.locatorOrHandle.scrollIntoViewIfNeeded({ timeout: options?.timeout ?? 1e3 });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Counts matching elements for locator based or returns 1 for handle based.
|
|
131
|
+
*/
|
|
132
|
+
async count() {
|
|
133
|
+
return (0, import_utils.isLocator)(this.locatorOrHandle) ? this.locatorOrHandle.count() : 1;
|
|
134
|
+
}
|
|
92
135
|
/**
|
|
93
136
|
* Check if element exists
|
|
94
137
|
* @param options.state which state is required in order to be deemed existing
|
|
@@ -96,7 +139,7 @@ class ElementController {
|
|
|
96
139
|
*/
|
|
97
140
|
async exists(options) {
|
|
98
141
|
try {
|
|
99
|
-
await this.waitFor(options?.state ?? "visible", { timeout: options?.timeout ??
|
|
142
|
+
await this.waitFor(options?.state ?? "visible", { timeout: options?.timeout ?? 1e3 });
|
|
100
143
|
return true;
|
|
101
144
|
} catch (error) {
|
|
102
145
|
if (error instanceof Error && error.message.includes("violation")) {
|
|
@@ -123,97 +166,89 @@ class ElementController {
|
|
|
123
166
|
async isEditable() {
|
|
124
167
|
return this.locatorOrHandle.isEditable();
|
|
125
168
|
}
|
|
169
|
+
async clear(options) {
|
|
170
|
+
(0, import_utils.assertLocator)(this.locatorOrHandle, requiresLocatorBasedController);
|
|
171
|
+
await (0, import_utils.prepareAction)(options);
|
|
172
|
+
await this.locatorOrHandle.clear(options);
|
|
173
|
+
}
|
|
126
174
|
async fill(text, options) {
|
|
127
|
-
await
|
|
175
|
+
await (0, import_utils.prepareAction)(options);
|
|
128
176
|
await this.locatorOrHandle.fill(text, options);
|
|
129
177
|
}
|
|
130
178
|
async type(text, options) {
|
|
131
|
-
await
|
|
179
|
+
await (0, import_utils.prepareAction)(options);
|
|
132
180
|
if ((0, import_type_guards.isUndefined)(this.options.typeDelay)) {
|
|
133
181
|
await this.locatorOrHandle.type(text, options);
|
|
134
182
|
} else {
|
|
135
183
|
for (const char of text) {
|
|
136
184
|
await this.locatorOrHandle.type(char, options);
|
|
137
|
-
await delay(options?.typeDelay ?? this.options.typeDelay);
|
|
185
|
+
await (0, import_utils.delay)(options?.typeDelay ?? this.options.typeDelay);
|
|
138
186
|
}
|
|
139
187
|
}
|
|
140
188
|
}
|
|
141
189
|
async press(key, options) {
|
|
142
|
-
await
|
|
190
|
+
await (0, import_utils.prepareAction)(options);
|
|
143
191
|
await this.locatorOrHandle.press(key, options);
|
|
144
192
|
}
|
|
145
193
|
async check(options) {
|
|
146
|
-
await
|
|
194
|
+
await (0, import_utils.prepareAction)(options);
|
|
147
195
|
await this.locatorOrHandle.check(options);
|
|
148
196
|
}
|
|
149
197
|
async uncheck(options) {
|
|
150
|
-
await
|
|
198
|
+
await (0, import_utils.prepareAction)(options);
|
|
151
199
|
await this.locatorOrHandle.uncheck(options);
|
|
152
200
|
}
|
|
153
201
|
async setChecked(checked, options) {
|
|
154
|
-
await
|
|
202
|
+
await (0, import_utils.prepareAction)(options);
|
|
155
203
|
await this.locatorOrHandle.setChecked(checked, options);
|
|
156
204
|
}
|
|
157
205
|
async selectOption(option, options) {
|
|
158
|
-
await
|
|
206
|
+
await (0, import_utils.prepareAction)(options);
|
|
159
207
|
const selectedOptions = await this.locatorOrHandle.selectOption(option, options);
|
|
160
208
|
return selectedOptions;
|
|
161
209
|
}
|
|
162
210
|
async setInputFiles(files, options) {
|
|
163
|
-
await
|
|
211
|
+
await (0, import_utils.prepareAction)(options);
|
|
164
212
|
await this.locatorOrHandle.setInputFiles(files, options);
|
|
165
213
|
}
|
|
166
214
|
async click(options) {
|
|
167
|
-
await
|
|
215
|
+
await (0, import_utils.prepareAction)(options);
|
|
168
216
|
await this.locatorOrHandle.click({
|
|
169
217
|
...options,
|
|
170
218
|
delay: (0, import_value_or_provider.resolveValueOrProvider)(options?.clickDelay)
|
|
171
219
|
});
|
|
172
220
|
}
|
|
173
221
|
async dblclick(options) {
|
|
174
|
-
await
|
|
222
|
+
await (0, import_utils.prepareAction)(options);
|
|
175
223
|
await this.locatorOrHandle.dblclick({
|
|
176
224
|
...options,
|
|
177
225
|
delay: (0, import_value_or_provider.resolveValueOrProvider)(options?.clickDelay)
|
|
178
226
|
});
|
|
179
227
|
}
|
|
180
228
|
async hover(options) {
|
|
181
|
-
await
|
|
229
|
+
await (0, import_utils.prepareAction)(options);
|
|
182
230
|
await this.locatorOrHandle.hover(options);
|
|
183
231
|
}
|
|
184
232
|
async focus(options) {
|
|
185
|
-
await
|
|
233
|
+
await (0, import_utils.prepareAction)(options);
|
|
186
234
|
await this.locatorOrHandle.focus(options);
|
|
187
235
|
}
|
|
188
236
|
async tap(options) {
|
|
189
|
-
await
|
|
237
|
+
await (0, import_utils.prepareAction)(options);
|
|
190
238
|
await this.locatorOrHandle.tap(options);
|
|
191
239
|
}
|
|
192
240
|
async selectText(options) {
|
|
193
|
-
await
|
|
241
|
+
await (0, import_utils.prepareAction)(options);
|
|
194
242
|
await this.locatorOrHandle.selectText(options);
|
|
195
243
|
}
|
|
196
244
|
async inputValue(options) {
|
|
197
245
|
return this.locatorOrHandle.inputValue(options);
|
|
198
246
|
}
|
|
199
|
-
async prepareAction(options) {
|
|
200
|
-
const actionDelay = options?.actionDelay ?? this.options.actionDelay;
|
|
201
|
-
if ((0, import_type_guards.isDefined)(actionDelay)) {
|
|
202
|
-
await this.waitFor("visible", { timeout: (0, import_value_or_provider.resolveValueOrProvider)(options?.timeout) });
|
|
203
|
-
await delay(actionDelay);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async function delay(milliseconds) {
|
|
208
|
-
if ((0, import_type_guards.isUndefined)(milliseconds)) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
await (0, import_timing.timeout)((0, import_value_or_provider.resolveValueOrProvider)(milliseconds));
|
|
212
247
|
}
|
|
213
248
|
function convertFilter(filter) {
|
|
214
249
|
return {
|
|
215
|
-
has: (0, import_type_guards.isDefined)(filter.has) ? (0, import_utils.assertLocatorPass)(filter.has.locatorOrHandle,
|
|
216
|
-
hasNot: (0, import_type_guards.isDefined)(filter.hasNot) ? (0, import_utils.assertLocatorPass)(filter.hasNot.locatorOrHandle,
|
|
250
|
+
has: (0, import_type_guards.isDefined)(filter.has) ? (0, import_utils.assertLocatorPass)(filter.has.locatorOrHandle, requiresLocatorBasedController) : void 0,
|
|
251
|
+
hasNot: (0, import_type_guards.isDefined)(filter.hasNot) ? (0, import_utils.assertLocatorPass)(filter.hasNot.locatorOrHandle, requiresLocatorBasedController) : void 0,
|
|
217
252
|
hasText: filter.hasText,
|
|
218
253
|
hasNotText: filter.hasNotText
|
|
219
254
|
};
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
import type { Frame, Page } from 'playwright';
|
|
2
|
+
import type { BrowserContextController } from './browser-context-controller.js';
|
|
2
3
|
import type { DocumentControllerOptions } from './document-controller.js';
|
|
3
4
|
import { DocumentController } from './document-controller.js';
|
|
4
|
-
import type { PageControllerOptions } from './page-controller.js';
|
|
5
|
-
import { PageController } from './page-controller.js';
|
|
5
|
+
import type { PageController, PageControllerOptions } from './page-controller.js';
|
|
6
6
|
export type FrameControllerOptions = DocumentControllerOptions;
|
|
7
|
-
export type FrameControllerForwardOptions = {
|
|
8
|
-
pageControllerOptions: PageControllerOptions;
|
|
9
|
-
};
|
|
10
7
|
export declare class FrameController extends DocumentController<Frame> {
|
|
11
|
-
private readonly frameControllerForwardOptions;
|
|
12
8
|
/** @deprecated should be avoided */
|
|
13
9
|
readonly frame: Frame;
|
|
14
10
|
readonly options: FrameControllerOptions;
|
|
15
|
-
constructor(frame: Frame,
|
|
11
|
+
constructor(frame: Frame, context: BrowserContextController, options: FrameControllerOptions);
|
|
16
12
|
/** Get the page containing this frame */
|
|
17
|
-
getPage(): PageController;
|
|
13
|
+
getPage(options?: PageControllerOptions): PageController;
|
|
18
14
|
/**
|
|
19
15
|
* @param frameSelector frame name, url or url predicate
|
|
20
16
|
* @returns
|
|
21
17
|
*/
|
|
22
|
-
getFrame(frameSelector: Parameters<Page['frame']>[0]): FrameController;
|
|
18
|
+
getFrame(frameSelector: Parameters<Page['frame']>[0], options?: FrameControllerOptions): FrameController;
|
|
23
19
|
}
|
|
@@ -23,30 +23,27 @@ __export(frame_controller_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(frame_controller_exports);
|
|
24
24
|
var import_type_guards = require("../utils/type-guards.js");
|
|
25
25
|
var import_document_controller = require("./document-controller.js");
|
|
26
|
-
var import_page_controller = require("./page-controller.js");
|
|
27
26
|
class FrameController extends import_document_controller.DocumentController {
|
|
28
|
-
frameControllerForwardOptions;
|
|
29
27
|
/** @deprecated should be avoided */
|
|
30
28
|
frame;
|
|
31
29
|
options;
|
|
32
|
-
constructor(frame,
|
|
33
|
-
super(frame,
|
|
30
|
+
constructor(frame, context, options) {
|
|
31
|
+
super(frame, context, options);
|
|
34
32
|
this.options = options;
|
|
35
|
-
this.frameControllerForwardOptions = forwardOptions;
|
|
36
33
|
}
|
|
37
34
|
/** Get the page containing this frame */
|
|
38
|
-
getPage() {
|
|
39
|
-
return
|
|
35
|
+
getPage(options) {
|
|
36
|
+
return this.context.getControllerByPage(this.frame.page(), options);
|
|
40
37
|
}
|
|
41
38
|
/**
|
|
42
39
|
* @param frameSelector frame name, url or url predicate
|
|
43
40
|
* @returns
|
|
44
41
|
*/
|
|
45
|
-
getFrame(frameSelector) {
|
|
42
|
+
getFrame(frameSelector, options) {
|
|
46
43
|
const frame = this.frame.page().frame(frameSelector);
|
|
47
44
|
if ((0, import_type_guards.isNull)(frame)) {
|
|
48
45
|
throw new Error("Frame not found.");
|
|
49
46
|
}
|
|
50
|
-
return
|
|
47
|
+
return this.getControllerByFrame(frame, { ...this.options, ...options });
|
|
51
48
|
}
|
|
52
49
|
}
|
package/browser/module.js
CHANGED
|
@@ -28,6 +28,8 @@ var import_injector = require("../injector/injector.js");
|
|
|
28
28
|
var import_object = require("../utils/object/object.js");
|
|
29
29
|
var import_type_guards = require("../utils/type-guards.js");
|
|
30
30
|
var import_browser_service = require("./browser.service.js");
|
|
31
|
+
var import_document_controller = require("./document-controller.js");
|
|
32
|
+
var import_frame_controller = require("./frame-controller.js");
|
|
31
33
|
const browserTypes = {
|
|
32
34
|
chromium: import_playwright.chromium,
|
|
33
35
|
firefox: import_playwright.firefox,
|
|
@@ -49,3 +51,4 @@ function getBrowserType(type) {
|
|
|
49
51
|
}
|
|
50
52
|
return browserType;
|
|
51
53
|
}
|
|
54
|
+
(0, import_document_controller.setFrameControllerConstructor)(import_frame_controller.FrameController);
|
|
@@ -2,22 +2,28 @@ import type { Page } from 'playwright';
|
|
|
2
2
|
import type { AsyncDisposable } from '../disposable/disposable.js';
|
|
3
3
|
import { disposeAsync } from '../disposable/disposable.js';
|
|
4
4
|
import type { Logger } from '../logger/logger.js';
|
|
5
|
+
import type { BrowserContextController } from './browser-context-controller.js';
|
|
5
6
|
import type { DocumentControllerOptions } from './document-controller.js';
|
|
6
7
|
import { DocumentController } from './document-controller.js';
|
|
7
|
-
import
|
|
8
|
-
import { FrameController } from './frame-controller.js';
|
|
8
|
+
import { ElementController } from './element-controller.js';
|
|
9
|
+
import type { FrameController, FrameControllerOptions } from './frame-controller.js';
|
|
9
10
|
import type { PdfRenderOptions } from './pdf-options.js';
|
|
10
11
|
import type { Abortable } from './types.js';
|
|
11
|
-
export type PageControllerOptions = DocumentControllerOptions
|
|
12
|
-
|
|
12
|
+
export type PageControllerOptions = DocumentControllerOptions;
|
|
13
|
+
export type ScrollToCoordinates = {
|
|
14
|
+
x?: number;
|
|
15
|
+
y?: number;
|
|
13
16
|
};
|
|
14
17
|
export declare class PageController extends DocumentController<Page> implements AsyncDisposable {
|
|
15
18
|
/** @deprecated should be avoided */
|
|
16
19
|
readonly page: Page;
|
|
17
20
|
readonly options: PageControllerOptions;
|
|
18
|
-
constructor(page: Page, options?: PageControllerOptions);
|
|
21
|
+
constructor(page: Page, context: BrowserContextController, options?: PageControllerOptions);
|
|
19
22
|
[disposeAsync](): Promise<void>;
|
|
20
23
|
close(): Promise<void>;
|
|
24
|
+
/** finds pages opened by this page (having opener set to this page) */
|
|
25
|
+
opened(): Promise<PageController[]>;
|
|
26
|
+
opener(): Promise<PageController | null>;
|
|
21
27
|
setExtraHttpHeaders(headers: Record<string, string>): Promise<void>;
|
|
22
28
|
waitForClose(): Promise<void>;
|
|
23
29
|
url(): string;
|
|
@@ -25,8 +31,10 @@ export declare class PageController extends DocumentController<Page> implements
|
|
|
25
31
|
* @param frameSelector frame name, url or url predicate
|
|
26
32
|
* @returns
|
|
27
33
|
*/
|
|
28
|
-
frame(frameSelector: Parameters<Page['frame']>[0]): FrameController;
|
|
34
|
+
frame(frameSelector: Parameters<Page['frame']>[0], options?: FrameControllerOptions): FrameController;
|
|
29
35
|
renderPdf(options?: PdfRenderOptions & Abortable): Promise<Uint8Array>;
|
|
36
|
+
scroll(deltaX: number, deltaY: number): Promise<void>;
|
|
37
|
+
scrollTo(coordinatesOrController: ScrollToCoordinates | ElementController): Promise<void>;
|
|
30
38
|
renderPdfStream(options?: PdfRenderOptions & Abortable): ReadableStream<Uint8Array>;
|
|
31
39
|
attachLogger(logger: Logger): void;
|
|
32
40
|
}
|
|
@@ -28,14 +28,14 @@ var import_timing = require("../utils/timing.js");
|
|
|
28
28
|
var import_type_guards = require("../utils/type-guards.js");
|
|
29
29
|
var import_units = require("../utils/units.js");
|
|
30
30
|
var import_document_controller = require("./document-controller.js");
|
|
31
|
-
var
|
|
31
|
+
var import_element_controller = require("./element-controller.js");
|
|
32
32
|
var import_utils = require("./utils.js");
|
|
33
33
|
class PageController extends import_document_controller.DocumentController {
|
|
34
34
|
/** @deprecated should be avoided */
|
|
35
35
|
page;
|
|
36
36
|
options;
|
|
37
|
-
constructor(page, options = {}) {
|
|
38
|
-
super(page,
|
|
37
|
+
constructor(page, context, options = {}) {
|
|
38
|
+
super(page, context, options);
|
|
39
39
|
this.page = page;
|
|
40
40
|
this.options = options;
|
|
41
41
|
}
|
|
@@ -45,6 +45,23 @@ class PageController extends import_document_controller.DocumentController {
|
|
|
45
45
|
async close() {
|
|
46
46
|
await this.page.close();
|
|
47
47
|
}
|
|
48
|
+
/** finds pages opened by this page (having opener set to this page) */
|
|
49
|
+
async opened() {
|
|
50
|
+
const openedPages = [];
|
|
51
|
+
for (const page of this.context.pages()) {
|
|
52
|
+
if (await page.opener() == this) {
|
|
53
|
+
openedPages.push(page);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return openedPages;
|
|
57
|
+
}
|
|
58
|
+
async opener() {
|
|
59
|
+
const opener = await this.page.opener();
|
|
60
|
+
if ((0, import_type_guards.isNull)(opener)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return this.context.getControllerByPage(opener);
|
|
64
|
+
}
|
|
48
65
|
async setExtraHttpHeaders(headers) {
|
|
49
66
|
const filtered = (0, import_object.filterUndefinedFromRecord)(headers);
|
|
50
67
|
await this.page.setExtraHTTPHeaders(filtered);
|
|
@@ -65,17 +82,63 @@ class PageController extends import_document_controller.DocumentController {
|
|
|
65
82
|
* @param frameSelector frame name, url or url predicate
|
|
66
83
|
* @returns
|
|
67
84
|
*/
|
|
68
|
-
frame(frameSelector) {
|
|
85
|
+
frame(frameSelector, options) {
|
|
69
86
|
const frame = this.page.frame(frameSelector);
|
|
70
87
|
if ((0, import_type_guards.isNull)(frame)) {
|
|
71
88
|
throw new Error("Frame not found.");
|
|
72
89
|
}
|
|
73
|
-
return
|
|
90
|
+
return this.getControllerByFrame(frame, { ...this.options, ...options });
|
|
74
91
|
}
|
|
75
92
|
async renderPdf(options = {}) {
|
|
76
93
|
const createPdfOptions = convertPdfOptions(options);
|
|
77
94
|
return (0, import_timing.withTimeout)(options.timeout ?? 30 * import_units.millisecondsPerSecond, this.page.pdf(createPdfOptions), { errorMessage: "Rendering pdf timed out." });
|
|
78
95
|
}
|
|
96
|
+
async scroll(deltaX, deltaY) {
|
|
97
|
+
await this.page.mouse.wheel(deltaX, deltaY);
|
|
98
|
+
}
|
|
99
|
+
async scrollTo(coordinatesOrController) {
|
|
100
|
+
const viewportSize = this.page.viewportSize();
|
|
101
|
+
if ((0, import_type_guards.isNull)(viewportSize)) {
|
|
102
|
+
throw new Error("Could not get page viewport size.");
|
|
103
|
+
}
|
|
104
|
+
const targetLeft = viewportSize.width / 3;
|
|
105
|
+
const targetRight = viewportSize.width / 3 * 2;
|
|
106
|
+
const targetTop = viewportSize.height / 3;
|
|
107
|
+
const targetBottom = viewportSize.height / 3 * 2;
|
|
108
|
+
const offsetX = viewportSize.width / 10;
|
|
109
|
+
const offsetY = viewportSize.height / 10;
|
|
110
|
+
const isElement = coordinatesOrController instanceof import_element_controller.ElementController;
|
|
111
|
+
while (true) {
|
|
112
|
+
const { scrollWidth, scrollHeight, scrollLeft, scrollTop, clientWidth, clientHeight } = await this.page.evaluate(async () => {
|
|
113
|
+
const { scrollWidth: scrollWidth2, scrollHeight: scrollHeight2, scrollLeft: scrollLeft2, scrollTop: scrollTop2, clientWidth: clientWidth2, clientHeight: clientHeight2 } = document.documentElement;
|
|
114
|
+
return { scrollWidth: scrollWidth2, scrollHeight: scrollHeight2, scrollLeft: scrollLeft2, scrollTop: scrollTop2, clientWidth: clientWidth2, clientHeight: clientHeight2 };
|
|
115
|
+
});
|
|
116
|
+
let targetX;
|
|
117
|
+
let targetY;
|
|
118
|
+
if (isElement) {
|
|
119
|
+
const boundingBox = await coordinatesOrController.boundingBox();
|
|
120
|
+
if ((0, import_type_guards.isNull)(boundingBox)) {
|
|
121
|
+
throw new Error("Could not get element bounding box.");
|
|
122
|
+
}
|
|
123
|
+
targetX = boundingBox.x + boundingBox.width / 2;
|
|
124
|
+
targetY = boundingBox.y + boundingBox.height / 2;
|
|
125
|
+
} else {
|
|
126
|
+
targetX = (0, import_type_guards.isDefined)(coordinatesOrController.x) ? coordinatesOrController.x - scrollLeft : void 0;
|
|
127
|
+
targetY = (0, import_type_guards.isDefined)(coordinatesOrController.y) ? coordinatesOrController.y - scrollTop : void 0;
|
|
128
|
+
}
|
|
129
|
+
const deltaX = (0, import_type_guards.isUndefined)(targetX) ? void 0 : targetX < targetLeft && scrollLeft > 0 ? -offsetX : targetX > targetRight && scrollLeft + clientWidth < scrollWidth ? offsetX : void 0;
|
|
130
|
+
const deltaY = (0, import_type_guards.isUndefined)(targetY) ? void 0 : targetY < targetTop && scrollTop > 0 ? -offsetY : targetY > targetBottom && scrollTop + clientHeight < scrollHeight ? offsetY : void 0;
|
|
131
|
+
if ((0, import_type_guards.isDefined)(deltaY)) {
|
|
132
|
+
await this.page.mouse.wheel(0, deltaY);
|
|
133
|
+
await (0, import_utils.delay)(Math.max(10, 150 - Math.abs(targetY - targetTop) / 10));
|
|
134
|
+
} else if ((0, import_type_guards.isDefined)(deltaX)) {
|
|
135
|
+
await this.page.mouse.wheel(deltaX, 0);
|
|
136
|
+
await (0, import_utils.delay)(Math.max(10, 150 - Math.abs(targetX - targetLeft) / 10));
|
|
137
|
+
} else {
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
79
142
|
renderPdfStream(options = {}) {
|
|
80
143
|
return (0, import_readable_stream_from_promise.readableStreamFromPromise)(async () => {
|
|
81
144
|
const buffer = await this.renderPdf(options);
|
package/browser/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ValueOrProvider } from '../utils/value-or-provider.js';
|
|
1
2
|
export type TimeoutOptions = {
|
|
2
3
|
timeout?: number;
|
|
3
4
|
};
|
|
@@ -8,3 +9,7 @@ export type WaitForStateOptions = {
|
|
|
8
9
|
export type Abortable = {
|
|
9
10
|
abort?: AbortSignal;
|
|
10
11
|
};
|
|
12
|
+
export type Delay = ValueOrProvider<number>;
|
|
13
|
+
export type ActionDelayOptions = {
|
|
14
|
+
actionDelay?: Delay;
|
|
15
|
+
};
|
package/browser/utils.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Logger } from '../logger/logger.js';
|
|
|
2
2
|
import type { BrowserContext, ElementHandle, Frame, LaunchOptions, Locator, Page } from 'playwright';
|
|
3
3
|
import type { NewBrowserContextOptions } from './browser-controller.js';
|
|
4
4
|
import type { NewBrowserOptions } from './browser.service.js';
|
|
5
|
+
import type { ActionDelayOptions, Delay, TimeoutOptions } from './types.js';
|
|
5
6
|
export declare function getLaunchOptions(options: NewBrowserOptions): LaunchOptions;
|
|
6
7
|
export declare function mergeNewBrowserContextOptions(a: NewBrowserContextOptions | undefined, b?: NewBrowserContextOptions, c?: NewBrowserContextOptions): NewBrowserContextOptions;
|
|
7
8
|
export declare function attachLogger(loggable: Page | BrowserContext, logger: Logger): void;
|
|
@@ -12,3 +13,5 @@ export declare function isElementHandle(locatorOrHandle: Locator | ElementHandle
|
|
|
12
13
|
export declare function isPage(pageOrFrameOrContext: Page | Frame | BrowserContext): pageOrFrameOrContext is Page;
|
|
13
14
|
export declare function isFrame(pageOrFrameOrContext: Page | Frame | BrowserContext): pageOrFrameOrContext is Frame;
|
|
14
15
|
export declare function isBrowserContext(pageOrFrameOrContext: Page | Frame | BrowserContext): pageOrFrameOrContext is BrowserContext;
|
|
16
|
+
export declare function prepareAction(options?: ActionDelayOptions & TimeoutOptions): Promise<void>;
|
|
17
|
+
export declare function delay(milliseconds: Delay | undefined): Promise<void>;
|
package/browser/utils.js
CHANGED
|
@@ -21,17 +21,21 @@ __export(utils_exports, {
|
|
|
21
21
|
assertLocator: () => assertLocator,
|
|
22
22
|
assertLocatorPass: () => assertLocatorPass,
|
|
23
23
|
attachLogger: () => attachLogger,
|
|
24
|
+
delay: () => delay,
|
|
24
25
|
getLaunchOptions: () => getLaunchOptions,
|
|
25
26
|
isBrowserContext: () => isBrowserContext,
|
|
26
27
|
isElementHandle: () => isElementHandle,
|
|
27
28
|
isFrame: () => isFrame,
|
|
28
29
|
isLocator: () => isLocator,
|
|
29
30
|
isPage: () => isPage,
|
|
30
|
-
mergeNewBrowserContextOptions: () => mergeNewBrowserContextOptions
|
|
31
|
+
mergeNewBrowserContextOptions: () => mergeNewBrowserContextOptions,
|
|
32
|
+
prepareAction: () => prepareAction
|
|
31
33
|
});
|
|
32
34
|
module.exports = __toCommonJS(utils_exports);
|
|
33
35
|
var import_object = require("../utils/object/object.js");
|
|
36
|
+
var import_timing = require("../utils/timing.js");
|
|
34
37
|
var import_type_guards = require("../utils/type-guards.js");
|
|
38
|
+
var import_value_or_provider = require("../utils/value-or-provider.js");
|
|
35
39
|
const pageLoggerMap = /* @__PURE__ */ new WeakMap();
|
|
36
40
|
function getLaunchOptions(options) {
|
|
37
41
|
const { windowSize, browserArguments, headless } = options;
|
|
@@ -125,3 +129,15 @@ function isFrame(pageOrFrameOrContext) {
|
|
|
125
129
|
function isBrowserContext(pageOrFrameOrContext) {
|
|
126
130
|
return pageOrFrameOrContext.constructor.name == "BrowserContext";
|
|
127
131
|
}
|
|
132
|
+
async function prepareAction(options) {
|
|
133
|
+
const actionDelay = options?.actionDelay;
|
|
134
|
+
if ((0, import_type_guards.isDefined)(actionDelay)) {
|
|
135
|
+
await (0, import_timing.timeout)((0, import_value_or_provider.resolveValueOrProvider)(actionDelay));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function delay(milliseconds) {
|
|
139
|
+
if ((0, import_type_guards.isUndefined)(milliseconds)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
await (0, import_timing.timeout)((0, import_value_or_provider.resolveValueOrProvider)(milliseconds));
|
|
143
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import '../../polyfills.js';
|
package/function/log.d.ts
CHANGED
package/function/log.js
CHANGED
|
@@ -23,15 +23,21 @@ __export(log_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(log_exports);
|
|
24
24
|
var import_type_guards = require("../utils/type-guards.js");
|
|
25
25
|
var import_type_of = require("../utils/type-of.js");
|
|
26
|
-
function wrapLog(fn,
|
|
27
|
-
const
|
|
28
|
-
const log = options?.logger?.trace.bind(options.logger) ?? console.log.bind(console);
|
|
26
|
+
function wrapLog(fn, { fnName = fn.name, logger } = {}) {
|
|
27
|
+
const log = logger?.trace.bind(logger) ?? console.log.bind(console);
|
|
29
28
|
const wrapped = {
|
|
30
29
|
[fnName](...args) {
|
|
31
|
-
const argString = args.map((arg) => (
|
|
30
|
+
const argString = args.map((arg) => stringifyArg(arg)).join(", ");
|
|
32
31
|
log(`[call: ${fnName}(${argString})]`);
|
|
33
32
|
return Reflect.apply(fn, this, args);
|
|
34
33
|
}
|
|
35
34
|
};
|
|
36
35
|
return wrapped[fnName];
|
|
37
36
|
}
|
|
37
|
+
function stringifyArg(arg, depth = 1) {
|
|
38
|
+
if ((0, import_type_guards.isArray)(arg) && depth > 0) {
|
|
39
|
+
const argString = arg.map((innerArg) => stringifyArg(innerArg, depth - 1)).join(", ");
|
|
40
|
+
return `[${argString}]`;
|
|
41
|
+
}
|
|
42
|
+
return (0, import_type_guards.isPrimitive)(arg) ? (0, import_type_guards.isString)(arg) ? `"${arg}"` : String(arg) : (0, import_type_of.typeOf)(arg);
|
|
43
|
+
}
|