@itmetsam/samurai-framework 0.22.9 → 0.22.11

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.
@@ -0,0 +1,169 @@
1
+ import type { ElementRectangle } from "../types/bidi-modules/browsing-context.js";
2
+ import type { PageFunction } from "../script/call-function.js";
3
+ import type { ElementScreenshotOptions } from "../browser/screenshot.js";
4
+ import type { FileInput } from "../browser/generated-files.js";
5
+ import { type ActionabilityContext, type ActionOptions } from "./actionability.js";
6
+ import { type CheckOptions } from "./check-actions.js";
7
+ import type { ElementAccess } from "./element-access.js";
8
+ import { type ClickOptions, type PointerOptions } from "./pointer-element-actions.js";
9
+ import { type BoundingBox } from "./element-reads.js";
10
+ import type { WaitForState } from "./element-state.js";
11
+ import { type SelectOptionValue } from "./select-actions.js";
12
+ /**
13
+ * The actions and reads of a `Locator` that work on the element its `access` resolves. `Locator` extends this
14
+ * and adds the chain, the fallbacks and the steps that build new locators.
15
+ */
16
+ export declare abstract class LocatorElementMethods {
17
+ /** What the reads and actions use of this locator */
18
+ protected abstract access: ElementAccess;
19
+ /** What the actionability waits use of this locator */
20
+ protected abstract actionability: ActionabilityContext;
21
+ /**
22
+ * Waits until the element is attached, visible, stable, enabled and not covered, then clicks it with real pointer
23
+ * input: its centre, or `position` (pixels from its top left corner). `button`, `clickCount`, `delay` (ms between press
24
+ * and release) and `modifiers` (keys held down) are as in Playwright
25
+ */
26
+ click(options?: ClickOptions): Promise<void>;
27
+ /** `click` with `clickCount: 2` */
28
+ dblclick(options?: ClickOptions): Promise<void>;
29
+ /** Waits until the element is attached, visible, stable and not covered, then moves the mouse onto it (`:hover`, `mouseover`, tooltips) */
30
+ hover(options?: PointerOptions): Promise<void>;
31
+ /** Waits like `click`, then touches the element with a touch pointer: `touchstart`, `touchend`, then the mouse events a tap ends in */
32
+ tap(options?: PointerOptions): Promise<void>;
33
+ /** Waits until the element is attached, then fires a synthetic event (`click`, `keydown`, ...; the class follows the type) at it, bubbling and composed */
34
+ dispatchEvent(type: string, eventInit?: Record<string, unknown>, options?: ActionOptions): Promise<void>;
35
+ /** Waits until the element is attached, then removes focus from it */
36
+ blur(options?: ActionOptions): Promise<void>;
37
+ /** Empties an input, textarea or editable element, as `fill("")` does */
38
+ clear(options?: ActionOptions): Promise<void>;
39
+ /** Focuses the element and types `text` into it one key press at a time, `delay` ms apart */
40
+ pressSequentially(text: string, options?: ActionOptions & {
41
+ delay?: number;
42
+ }): Promise<void>;
43
+ /**
44
+ * Checks a checkbox, radio or `role=checkbox|radio|switch` element; does nothing when it is already checked.
45
+ * Waits like `click`, but a hidden input counts as reachable through its `<label>`, which is what gets clicked.
46
+ * `trial` waits without clicking. Throws when the click did not change the state.
47
+ * @example
48
+ * await page.getByLabel("I accept the terms").check();
49
+ */
50
+ check(options?: CheckOptions): Promise<void>;
51
+ /** Unchecks a checkbox or `role=checkbox|switch` element; does nothing when it is already unchecked. A radio button cannot be unchecked: throws */
52
+ uncheck(options?: CheckOptions): Promise<void>;
53
+ /** `check()` or `uncheck()`, whichever brings the element to `checked` */
54
+ setChecked(checked: boolean, options?: CheckOptions): Promise<void>;
55
+ /**
56
+ * Selects options of a `<select>` or `<select multiple>` (which replaces its selection) and fires `input` and
57
+ * `change`. A string matches an option's value or its label; `{ value, label, index }` must match every field
58
+ * given. Waits until the select is visible and enabled and every option exists. Returns the values now selected.
59
+ * @example
60
+ * await page.getByLabel("Country").selectOption("Netherlands");
61
+ * await page.locator("select").selectOption([{ index: 0 }, { value: "b" }]);
62
+ */
63
+ selectOption(values: SelectOptionValue | SelectOptionValue[], options?: ActionOptions): Promise<string[]>;
64
+ /**
65
+ * Sets the files of an `<input type=file>`; `[]` clears it. Paths are relative to the project folder (absolute
66
+ * ones are used as they are); `generatedFile(…)` writes a file of a given size when the step runs.
67
+ * Waits for the input to be attached and enabled; it need not be visible, file inputs are often hidden behind a label.
68
+ * @example
69
+ * await page.getByLabel("Avatar").setInputFiles("files/avatar.png");
70
+ * await page.getByLabel("Upload").setInputFiles(generatedFile({ name: "huge.pdf", size: "60 MB" }));
71
+ */
72
+ setInputFiles(files: FileInput | FileInput[], options?: {
73
+ timeout?: number;
74
+ }): Promise<void>;
75
+ /**
76
+ * Drops files on the element, as dragging them from the desktop does: `dragenter`, `dragover` and `drop`
77
+ * with a `DataTransfer` holding the files. Takes what `setInputFiles` takes. The events are synthetic
78
+ * (`isTrusted` is false); a page that only accepts trusted drops ignores them.
79
+ * Waits for the element to be attached and visible.
80
+ * @example
81
+ * await page.getByTestId("dropzone").dropFiles(["files/a.png", "files/b.png"]);
82
+ */
83
+ dropFiles(files: FileInput | FileInput[], options?: {
84
+ timeout?: number;
85
+ }): Promise<void>;
86
+ /**
87
+ * Takes a screenshot of just this element, after scrolling it into view and waiting until it is attached and
88
+ * visible. Returns the image (also written to `options.path`).
89
+ * @example
90
+ * await page.locator("div[@id='chart']").screenshot({ path: "out/chart.png" });
91
+ */
92
+ screenshot(options?: ElementScreenshotOptions & {
93
+ timeout?: number;
94
+ }): Promise<Buffer>;
95
+ /** Waits until the element is attached, then focuses it */
96
+ focus(options?: ActionOptions): Promise<void>;
97
+ /** Waits until the element reaches `state` (default "visible"); does not scroll */
98
+ waitFor(options?: {
99
+ state?: WaitForState;
100
+ timeout?: number;
101
+ }): Promise<void>;
102
+ /** Returns the browser's getBoundingClientRect result for the given element */
103
+ getBoundingClientRect(): Promise<ElementRectangle>;
104
+ /** Whether the element exists, has a non-empty box and is not hidden by CSS */
105
+ isVisible(): Promise<boolean>;
106
+ /** The opposite of `isVisible`: true for a hidden element and for one that is not there */
107
+ isHidden(): Promise<boolean>;
108
+ /** Trimmed text content, or null when the element is missing */
109
+ textContent(): Promise<string | null>;
110
+ /** Rendered text of the element (as a person would copy it, hidden text left out), untrimmed, or null when the element is missing */
111
+ innerText(): Promise<string | null>;
112
+ /** The markup inside the element, or null when the element is missing */
113
+ innerHTML(): Promise<string | null>;
114
+ /** `textContent` of every match, as the page has it (untrimmed, unlike `textContent()`); `[]` when none match. Does not wait */
115
+ allTextContents(): Promise<string[]>;
116
+ /** `innerText` of every match; `[]` when none match. Does not wait */
117
+ allInnerTexts(): Promise<string[]>;
118
+ /** The element's box in CSS pixels from the viewport's top left, or null when it is missing or not rendered (`display: none`). Does not wait or scroll */
119
+ boundingBox(): Promise<BoundingBox | null>;
120
+ /**
121
+ * Waits until the element is attached (hidden is fine), then calls `fn(element, arg)` in the page and returns the result
122
+ * (see `page.evaluate` for what comes back). `fn` is a function or the source of one; a strict locator throws when several match.
123
+ * @example
124
+ * const id = await page.getByTestId("row").evaluate((el) => el.dataset.id);
125
+ */
126
+ evaluate<R = unknown, A = unknown>(fn: PageFunction<[any, A], R>, arg?: A, options?: {
127
+ timeout?: number;
128
+ }): Promise<R>;
129
+ /** Calls `fn(elements, arg)` in the page with an array of every match (empty when none; does not wait) and returns the result */
130
+ evaluateAll<R = unknown, A = unknown>(fn: PageFunction<[any[], A], R>, arg?: A): Promise<R>;
131
+ /** Value of an input/textarea/select, or null when missing */
132
+ inputValue(): Promise<string | null>;
133
+ /** Attribute value, or null when the element or attribute is missing */
134
+ getAttribute(name: string): Promise<string | null>;
135
+ /** Whether the element exists and is not disabled; does not wait */
136
+ isEnabled(): Promise<boolean>;
137
+ /** The opposite of `isEnabled`: true for a disabled element and for one that is not there; does not wait */
138
+ isDisabled(): Promise<boolean>;
139
+ /** Like `isEnabled`, but null when the element is missing, so callers can tell "disabled" from "not there"; does not wait */
140
+ enabledState(): Promise<boolean | null>;
141
+ /** Whether a checkbox or radio input is checked or the element has `aria-checked="true"`; null when the element is missing */
142
+ isChecked(): Promise<boolean | null>;
143
+ /** The accessible name (what `getByRole`'s `name` is matched against), "" when there is none, or null when the element is missing */
144
+ accessibleName(): Promise<string | null>;
145
+ /** The accessible description (`aria-describedby`, `aria-description`, else `title` when it is not the name), or null when the element is missing */
146
+ accessibleDescription(): Promise<string | null>;
147
+ /** The class attribute as written ("" when the element has none), or null when the element is missing */
148
+ classAttribute(): Promise<string | null>;
149
+ /** Computed value of a CSS property (camelCase names become kebab-case, `--custom` is kept), or null when the element is missing */
150
+ cssValue(name: string): Promise<string | null>;
151
+ /** Whether the element exists and accepts typing (enabled, not readonly, a text field); does not wait */
152
+ isEditable(): Promise<boolean>;
153
+ /**
154
+ * Waits until the element is attached, visible and enabled, focuses it and presses `key` with real keyboard input.
155
+ * Named keys are `Enter`, `Escape`, `Tab`, `Backspace`, `Delete`, `Space`, `Insert`, `Home`, `End`, `PageUp`, `PageDown`,
156
+ * `F1` to `F12` and the arrows; any other key must be a single character. A chord holds modifiers (`Control`, `Shift`,
157
+ * `Alt`, `Meta`, `ControlOrMeta`) while the last key is pressed.
158
+ * @example
159
+ * await page.getByLabel("New todo").press("Enter");
160
+ * await page.getByLabel("Name").press("Control+a");
161
+ */
162
+ press(key: string, options?: ActionOptions & {
163
+ delay?: number;
164
+ }): Promise<void>;
165
+ /** Waits until the field is editable and not covered, then replaces its value by typing `value`; an empty string clears it */
166
+ fill(value: string, options?: ActionOptions & {
167
+ output?: string;
168
+ }): Promise<void>;
169
+ }
@@ -0,0 +1,228 @@
1
+ import { waitForState, } from "./actionability.js";
2
+ import { setChecked } from "./check-actions.js";
3
+ import { clearElement, fillElement, focusElement, pressOnElement, pressSequentially, screenshotElement, } from "./element-actions.js";
4
+ import { blurElement, dispatchEventOn } from "./event-actions.js";
5
+ import { clickElement, hoverElement, tapElement, } from "./pointer-element-actions.js";
6
+ import { readAccessibleDescription, readAccessibleName, readAllInnerTexts, readAllTextContents, readAttribute, readBoundingBox, readBoundingClientRect, readClassAttribute, readCssValue, readEnabledState, readInnerHTML, readInnerText, readInputValue, readIsChecked, readIsEditable, readIsEnabled, readIsVisible, readTextContent, } from "./element-reads.js";
7
+ import { evaluateOnAll, evaluateOnElement } from "./evaluate.js";
8
+ import { dropFiles, setInputFiles } from "./file-actions.js";
9
+ import { selectOptions } from "./select-actions.js";
10
+ /**
11
+ * The actions and reads of a `Locator` that work on the element its `access` resolves. `Locator` extends this
12
+ * and adds the chain, the fallbacks and the steps that build new locators.
13
+ */
14
+ export class LocatorElementMethods {
15
+ /**
16
+ * Waits until the element is attached, visible, stable, enabled and not covered, then clicks it with real pointer
17
+ * input: its centre, or `position` (pixels from its top left corner). `button`, `clickCount`, `delay` (ms between press
18
+ * and release) and `modifiers` (keys held down) are as in Playwright
19
+ */
20
+ async click(options) {
21
+ await clickElement(this.access, options);
22
+ }
23
+ /** `click` with `clickCount: 2` */
24
+ async dblclick(options) {
25
+ await clickElement(this.access, { ...options, clickCount: 2 }, "dblclick");
26
+ }
27
+ /** Waits until the element is attached, visible, stable and not covered, then moves the mouse onto it (`:hover`, `mouseover`, tooltips) */
28
+ async hover(options) {
29
+ await hoverElement(this.access, options);
30
+ }
31
+ /** Waits like `click`, then touches the element with a touch pointer: `touchstart`, `touchend`, then the mouse events a tap ends in */
32
+ async tap(options) {
33
+ await tapElement(this.access, options);
34
+ }
35
+ /** Waits until the element is attached, then fires a synthetic event (`click`, `keydown`, ...; the class follows the type) at it, bubbling and composed */
36
+ async dispatchEvent(type, eventInit, options) {
37
+ await dispatchEventOn(this.access, type, eventInit, options);
38
+ }
39
+ /** Waits until the element is attached, then removes focus from it */
40
+ async blur(options) {
41
+ await blurElement(this.access, options);
42
+ }
43
+ /** Empties an input, textarea or editable element, as `fill("")` does */
44
+ async clear(options) {
45
+ await clearElement(this.access, options);
46
+ }
47
+ /** Focuses the element and types `text` into it one key press at a time, `delay` ms apart */
48
+ async pressSequentially(text, options) {
49
+ await pressSequentially(this.access, text, options);
50
+ }
51
+ /**
52
+ * Checks a checkbox, radio or `role=checkbox|radio|switch` element; does nothing when it is already checked.
53
+ * Waits like `click`, but a hidden input counts as reachable through its `<label>`, which is what gets clicked.
54
+ * `trial` waits without clicking. Throws when the click did not change the state.
55
+ * @example
56
+ * await page.getByLabel("I accept the terms").check();
57
+ */
58
+ async check(options) {
59
+ await setChecked(this.access, "check", true, options);
60
+ }
61
+ /** Unchecks a checkbox or `role=checkbox|switch` element; does nothing when it is already unchecked. A radio button cannot be unchecked: throws */
62
+ async uncheck(options) {
63
+ await setChecked(this.access, "uncheck", false, options);
64
+ }
65
+ /** `check()` or `uncheck()`, whichever brings the element to `checked` */
66
+ async setChecked(checked, options) {
67
+ await setChecked(this.access, "setChecked", checked, options);
68
+ }
69
+ /**
70
+ * Selects options of a `<select>` or `<select multiple>` (which replaces its selection) and fires `input` and
71
+ * `change`. A string matches an option's value or its label; `{ value, label, index }` must match every field
72
+ * given. Waits until the select is visible and enabled and every option exists. Returns the values now selected.
73
+ * @example
74
+ * await page.getByLabel("Country").selectOption("Netherlands");
75
+ * await page.locator("select").selectOption([{ index: 0 }, { value: "b" }]);
76
+ */
77
+ async selectOption(values, options) {
78
+ return selectOptions(this.access, values, options);
79
+ }
80
+ /**
81
+ * Sets the files of an `<input type=file>`; `[]` clears it. Paths are relative to the project folder (absolute
82
+ * ones are used as they are); `generatedFile(…)` writes a file of a given size when the step runs.
83
+ * Waits for the input to be attached and enabled; it need not be visible, file inputs are often hidden behind a label.
84
+ * @example
85
+ * await page.getByLabel("Avatar").setInputFiles("files/avatar.png");
86
+ * await page.getByLabel("Upload").setInputFiles(generatedFile({ name: "huge.pdf", size: "60 MB" }));
87
+ */
88
+ async setInputFiles(files, options) {
89
+ await setInputFiles(this.access, files, options);
90
+ }
91
+ /**
92
+ * Drops files on the element, as dragging them from the desktop does: `dragenter`, `dragover` and `drop`
93
+ * with a `DataTransfer` holding the files. Takes what `setInputFiles` takes. The events are synthetic
94
+ * (`isTrusted` is false); a page that only accepts trusted drops ignores them.
95
+ * Waits for the element to be attached and visible.
96
+ * @example
97
+ * await page.getByTestId("dropzone").dropFiles(["files/a.png", "files/b.png"]);
98
+ */
99
+ async dropFiles(files, options) {
100
+ await dropFiles(this.access, files, options);
101
+ }
102
+ /**
103
+ * Takes a screenshot of just this element, after scrolling it into view and waiting until it is attached and
104
+ * visible. Returns the image (also written to `options.path`).
105
+ * @example
106
+ * await page.locator("div[@id='chart']").screenshot({ path: "out/chart.png" });
107
+ */
108
+ async screenshot(options = {}) {
109
+ return screenshotElement(this.access, options);
110
+ }
111
+ /** Waits until the element is attached, then focuses it */
112
+ async focus(options) {
113
+ await focusElement(this.access, options);
114
+ }
115
+ /** Waits until the element reaches `state` (default "visible"); does not scroll */
116
+ async waitFor(options = {}) {
117
+ await waitForState(this.actionability, options);
118
+ }
119
+ /** Returns the browser's getBoundingClientRect result for the given element */
120
+ async getBoundingClientRect() {
121
+ return readBoundingClientRect(this.access);
122
+ }
123
+ /** Whether the element exists, has a non-empty box and is not hidden by CSS */
124
+ async isVisible() {
125
+ return readIsVisible(this.actionability);
126
+ }
127
+ /** The opposite of `isVisible`: true for a hidden element and for one that is not there */
128
+ async isHidden() {
129
+ return !(await this.isVisible());
130
+ }
131
+ /** Trimmed text content, or null when the element is missing */
132
+ async textContent() {
133
+ return readTextContent(this.access);
134
+ }
135
+ /** Rendered text of the element (as a person would copy it, hidden text left out), untrimmed, or null when the element is missing */
136
+ async innerText() {
137
+ return readInnerText(this.access);
138
+ }
139
+ /** The markup inside the element, or null when the element is missing */
140
+ async innerHTML() {
141
+ return readInnerHTML(this.access);
142
+ }
143
+ /** `textContent` of every match, as the page has it (untrimmed, unlike `textContent()`); `[]` when none match. Does not wait */
144
+ async allTextContents() {
145
+ return readAllTextContents(this.access);
146
+ }
147
+ /** `innerText` of every match; `[]` when none match. Does not wait */
148
+ async allInnerTexts() {
149
+ return readAllInnerTexts(this.access);
150
+ }
151
+ /** The element's box in CSS pixels from the viewport's top left, or null when it is missing or not rendered (`display: none`). Does not wait or scroll */
152
+ async boundingBox() {
153
+ return readBoundingBox(this.access);
154
+ }
155
+ /**
156
+ * Waits until the element is attached (hidden is fine), then calls `fn(element, arg)` in the page and returns the result
157
+ * (see `page.evaluate` for what comes back). `fn` is a function or the source of one; a strict locator throws when several match.
158
+ * @example
159
+ * const id = await page.getByTestId("row").evaluate((el) => el.dataset.id);
160
+ */
161
+ async evaluate(fn, arg, options) {
162
+ return evaluateOnElement(this.access, fn, arg, options);
163
+ }
164
+ /** Calls `fn(elements, arg)` in the page with an array of every match (empty when none; does not wait) and returns the result */
165
+ async evaluateAll(fn, arg) {
166
+ return evaluateOnAll(this.access, fn, arg);
167
+ }
168
+ /** Value of an input/textarea/select, or null when missing */
169
+ async inputValue() {
170
+ return readInputValue(this.access);
171
+ }
172
+ /** Attribute value, or null when the element or attribute is missing */
173
+ async getAttribute(name) {
174
+ return readAttribute(this.access, name);
175
+ }
176
+ /** Whether the element exists and is not disabled; does not wait */
177
+ async isEnabled() {
178
+ return readIsEnabled(this.actionability);
179
+ }
180
+ /** The opposite of `isEnabled`: true for a disabled element and for one that is not there; does not wait */
181
+ async isDisabled() {
182
+ return !(await this.isEnabled());
183
+ }
184
+ /** Like `isEnabled`, but null when the element is missing, so callers can tell "disabled" from "not there"; does not wait */
185
+ async enabledState() {
186
+ return readEnabledState(this.actionability);
187
+ }
188
+ /** Whether a checkbox or radio input is checked or the element has `aria-checked="true"`; null when the element is missing */
189
+ async isChecked() {
190
+ return readIsChecked(this.access);
191
+ }
192
+ /** The accessible name (what `getByRole`'s `name` is matched against), "" when there is none, or null when the element is missing */
193
+ async accessibleName() {
194
+ return readAccessibleName(this.access);
195
+ }
196
+ /** The accessible description (`aria-describedby`, `aria-description`, else `title` when it is not the name), or null when the element is missing */
197
+ async accessibleDescription() {
198
+ return readAccessibleDescription(this.access);
199
+ }
200
+ /** The class attribute as written ("" when the element has none), or null when the element is missing */
201
+ async classAttribute() {
202
+ return readClassAttribute(this.access);
203
+ }
204
+ /** Computed value of a CSS property (camelCase names become kebab-case, `--custom` is kept), or null when the element is missing */
205
+ async cssValue(name) {
206
+ return readCssValue(this.access, name);
207
+ }
208
+ /** Whether the element exists and accepts typing (enabled, not readonly, a text field); does not wait */
209
+ async isEditable() {
210
+ return readIsEditable(this.actionability);
211
+ }
212
+ /**
213
+ * Waits until the element is attached, visible and enabled, focuses it and presses `key` with real keyboard input.
214
+ * Named keys are `Enter`, `Escape`, `Tab`, `Backspace`, `Delete`, `Space`, `Insert`, `Home`, `End`, `PageUp`, `PageDown`,
215
+ * `F1` to `F12` and the arrows; any other key must be a single character. A chord holds modifiers (`Control`, `Shift`,
216
+ * `Alt`, `Meta`, `ControlOrMeta`) while the last key is pressed.
217
+ * @example
218
+ * await page.getByLabel("New todo").press("Enter");
219
+ * await page.getByLabel("Name").press("Control+a");
220
+ */
221
+ async press(key, options) {
222
+ await pressOnElement(this.access, key, options);
223
+ }
224
+ /** Waits until the field is editable and not covered, then replaces its value by typing `value`; an empty string clears it */
225
+ async fill(value, options) {
226
+ await fillElement(this.access, value, options);
227
+ }
228
+ }
@@ -1,23 +1,17 @@
1
1
  import type { BiDiConnector } from "../transport/bidi-connection.js";
2
- import type { BrowsingContext, ElementRectangle } from "../types/bidi-modules/browsing-context.js";
2
+ import type { BrowsingContext } from "../types/bidi-modules/browsing-context.js";
3
3
  import { ElementHandle } from "../script/element-handle.js";
4
- import type { PageFunction } from "../script/call-function.js";
5
- import type { ElementScreenshotOptions } from "../browser/screenshot.js";
6
- import type { FileInput } from "../browser/generated-files.js";
7
- import { type ActionOptions } from "./actionability.js";
8
- import { type CheckOptions } from "./check-actions.js";
4
+ import { type ActionabilityContext } from "./actionability.js";
5
+ import { type ElementAccess } from "./element-access.js";
9
6
  import { type DragOptions } from "./drag-actions.js";
10
- import { type ClickOptions, type PointerOptions } from "./pointer-element-actions.js";
11
- import { type BoundingBox } from "./element-reads.js";
12
- import type { WaitForState } from "./element-state.js";
13
7
  import type { HelperInstaller } from "./helper-realm.js";
14
8
  import { type StrictSource } from "./strict-mode.js";
15
9
  import type { RoleOptions } from "./role-locator.js";
16
10
  import { type Selector, type ExactOption, type TextOptions } from "./selector.js";
17
- import { type SelectOptionValue } from "./select-actions.js";
18
11
  import { type FilterOptions } from "./filter-step.js";
12
+ import { LocatorElementMethods } from "./locator-element-methods.js";
19
13
  export type { ActionOptions } from "./actionability.js";
20
- export default class Locator {
14
+ export default class Locator extends LocatorElementMethods {
21
15
  private biDiConnector;
22
16
  private contextId;
23
17
  private chain;
@@ -29,9 +23,9 @@ export default class Locator {
29
23
  private matched;
30
24
  private resolver;
31
25
  /** What the actionability waits use of this locator */
32
- private actionability;
26
+ protected actionability: ActionabilityContext;
33
27
  /** What the reads and actions use of this locator */
34
- private access;
28
+ protected access: ElementAccess;
35
29
  /**
36
30
  * `selector` is an xpath, or a chain of selector steps that each search inside the previous step's matches.
37
31
  * `helpers` is the page's helper realm. With it the actionability probe is installed once per
@@ -134,160 +128,12 @@ export default class Locator {
134
128
  */
135
129
  private resolveOne;
136
130
  private waitForActionable;
137
- /**
138
- * Waits until the element is attached, visible, stable, enabled and not covered, then clicks it with real pointer
139
- * input: its centre, or `position` (pixels from its top left corner). `button`, `clickCount`, `delay` (ms between press
140
- * and release) and `modifiers` (keys held down) are as in Playwright
141
- */
142
- click(options?: ClickOptions): Promise<void>;
143
- /** `click` with `clickCount: 2` */
144
- dblclick(options?: ClickOptions): Promise<void>;
145
- /** Waits until the element is attached, visible, stable and not covered, then moves the mouse onto it (`:hover`, `mouseover`, tooltips) */
146
- hover(options?: PointerOptions): Promise<void>;
147
- /** Waits like `click`, then touches the element with a touch pointer: `touchstart`, `touchend`, then the mouse events a tap ends in */
148
- tap(options?: PointerOptions): Promise<void>;
149
131
  /** Drags this element onto `target` with real pointer input; `sourcePosition`, `targetPosition` and `steps` shape the gesture. Firefox needs synthetic drop events, see the wiki */
150
132
  dragTo(target: Locator, options?: DragOptions): Promise<void>;
151
- /** Waits until the element is attached, then fires a synthetic event (`click`, `keydown`, ...; the class follows the type) at it, bubbling and composed */
152
- dispatchEvent(type: string, eventInit?: Record<string, unknown>, options?: ActionOptions): Promise<void>;
153
- /** Waits until the element is attached, then removes focus from it */
154
- blur(options?: ActionOptions): Promise<void>;
155
- /** Empties an input, textarea or editable element, as `fill("")` does */
156
- clear(options?: ActionOptions): Promise<void>;
157
- /** Focuses the element and types `text` into it one key press at a time, `delay` ms apart */
158
- pressSequentially(text: string, options?: ActionOptions & {
159
- delay?: number;
160
- }): Promise<void>;
161
- /**
162
- * Checks a checkbox, radio or `role=checkbox|radio|switch` element; does nothing when it is already checked.
163
- * Waits like `click`, but a hidden input counts as reachable through its `<label>`, which is what gets clicked.
164
- * `trial` waits without clicking. Throws when the click did not change the state.
165
- * @example
166
- * await page.getByLabel("I accept the terms").check();
167
- */
168
- check(options?: CheckOptions): Promise<void>;
169
- /** Unchecks a checkbox or `role=checkbox|switch` element; does nothing when it is already unchecked. A radio button cannot be unchecked: throws */
170
- uncheck(options?: CheckOptions): Promise<void>;
171
- /** `check()` or `uncheck()`, whichever brings the element to `checked` */
172
- setChecked(checked: boolean, options?: CheckOptions): Promise<void>;
173
- /**
174
- * Selects options of a `<select>` or `<select multiple>` (which replaces its selection) and fires `input` and
175
- * `change`. A string matches an option's value or its label; `{ value, label, index }` must match every field
176
- * given. Waits until the select is visible and enabled and every option exists. Returns the values now selected.
177
- * @example
178
- * await page.getByLabel("Country").selectOption("Netherlands");
179
- * await page.locator("select").selectOption([{ index: 0 }, { value: "b" }]);
180
- */
181
- selectOption(values: SelectOptionValue | SelectOptionValue[], options?: ActionOptions): Promise<string[]>;
182
- /**
183
- * Sets the files of an `<input type=file>`; `[]` clears it. Paths are relative to the project folder (absolute
184
- * ones are used as they are); `generatedFile(…)` writes a file of a given size when the step runs.
185
- * Waits for the input to be attached and enabled; it need not be visible, file inputs are often hidden behind a label.
186
- * @example
187
- * await page.getByLabel("Avatar").setInputFiles("files/avatar.png");
188
- * await page.getByLabel("Upload").setInputFiles(generatedFile({ name: "huge.pdf", size: "60 MB" }));
189
- */
190
- setInputFiles(files: FileInput | FileInput[], options?: {
191
- timeout?: number;
192
- }): Promise<void>;
193
- /**
194
- * Drops files on the element, as dragging them from the desktop does: `dragenter`, `dragover` and `drop`
195
- * with a `DataTransfer` holding the files. Takes what `setInputFiles` takes. The events are synthetic
196
- * (`isTrusted` is false); a page that only accepts trusted drops ignores them.
197
- * Waits for the element to be attached and visible.
198
- * @example
199
- * await page.getByTestId("dropzone").dropFiles(["files/a.png", "files/b.png"]);
200
- */
201
- dropFiles(files: FileInput | FileInput[], options?: {
202
- timeout?: number;
203
- }): Promise<void>;
204
- /**
205
- * Takes a screenshot of just this element, after scrolling it into view and waiting until it is attached and
206
- * visible. Returns the image (also written to `options.path`).
207
- * @example
208
- * await page.locator("div[@id='chart']").screenshot({ path: "out/chart.png" });
209
- */
210
- screenshot(options?: ElementScreenshotOptions & {
211
- timeout?: number;
212
- }): Promise<Buffer>;
213
- /** Waits until the element is attached, then focuses it */
214
- focus(options?: ActionOptions): Promise<void>;
215
- /** Waits until the element reaches `state` (default "visible"); does not scroll */
216
- waitFor(options?: {
217
- state?: WaitForState;
218
- timeout?: number;
219
- }): Promise<void>;
220
- /** Returns the browser's getBoundingClientRect result for the given element */
221
- getBoundingClientRect(): Promise<ElementRectangle>;
222
- /** Whether the element exists, has a non-empty box and is not hidden by CSS */
223
- isVisible(): Promise<boolean>;
224
- /** The opposite of `isVisible`: true for a hidden element and for one that is not there */
225
- isHidden(): Promise<boolean>;
226
- /** Trimmed text content, or null when the element is missing */
227
- textContent(): Promise<string | null>;
228
- /** Rendered text of the element (as a person would copy it, hidden text left out), untrimmed, or null when the element is missing */
229
- innerText(): Promise<string | null>;
230
- /** The markup inside the element, or null when the element is missing */
231
- innerHTML(): Promise<string | null>;
232
- /** `textContent` of every match, as the page has it (untrimmed, unlike `textContent()`); `[]` when none match. Does not wait */
233
- allTextContents(): Promise<string[]>;
234
- /** `innerText` of every match; `[]` when none match. Does not wait */
235
- allInnerTexts(): Promise<string[]>;
236
- /** The element's box in CSS pixels from the viewport's top left, or null when it is missing or not rendered (`display: none`). Does not wait or scroll */
237
- boundingBox(): Promise<BoundingBox | null>;
238
- /**
239
- * Waits until the element is attached (hidden is fine), then calls `fn(element, arg)` in the page and returns the result
240
- * (see `page.evaluate` for what comes back). `fn` is a function or the source of one; a strict locator throws when several match.
241
- * @example
242
- * const id = await page.getByTestId("row").evaluate((el) => el.dataset.id);
243
- */
244
- evaluate<R = unknown, A = unknown>(fn: PageFunction<[any, A], R>, arg?: A, options?: {
245
- timeout?: number;
246
- }): Promise<R>;
247
- /** Calls `fn(elements, arg)` in the page with an array of every match (empty when none; does not wait) and returns the result */
248
- evaluateAll<R = unknown, A = unknown>(fn: PageFunction<[any[], A], R>, arg?: A): Promise<R>;
249
- /** Value of an input/textarea/select, or null when missing */
250
- inputValue(): Promise<string | null>;
251
- /** Attribute value, or null when the element or attribute is missing */
252
- getAttribute(name: string): Promise<string | null>;
253
133
  /** References to the elements currently matching, in document order. Internal: for tooling that identifies elements */
254
134
  elements(): Promise<ElementHandle[]>;
255
135
  /** Number of elements currently matching */
256
136
  count(): Promise<number>;
257
- /** Whether the element exists and is not disabled; does not wait */
258
- isEnabled(): Promise<boolean>;
259
- /** The opposite of `isEnabled`: true for a disabled element and for one that is not there; does not wait */
260
- isDisabled(): Promise<boolean>;
261
- /** Like `isEnabled`, but null when the element is missing, so callers can tell "disabled" from "not there"; does not wait */
262
- enabledState(): Promise<boolean | null>;
263
- /** Whether a checkbox or radio input is checked or the element has `aria-checked="true"`; null when the element is missing */
264
- isChecked(): Promise<boolean | null>;
265
- /** The accessible name (what `getByRole`'s `name` is matched against), "" when there is none, or null when the element is missing */
266
- accessibleName(): Promise<string | null>;
267
- /** The accessible description (`aria-describedby`, `aria-description`, else `title` when it is not the name), or null when the element is missing */
268
- accessibleDescription(): Promise<string | null>;
269
- /** The class attribute as written ("" when the element has none), or null when the element is missing */
270
- classAttribute(): Promise<string | null>;
271
- /** Computed value of a CSS property (camelCase names become kebab-case, `--custom` is kept), or null when the element is missing */
272
- cssValue(name: string): Promise<string | null>;
273
- /** Whether the element exists and accepts typing (enabled, not readonly, a text field); does not wait */
274
- isEditable(): Promise<boolean>;
275
137
  /** Wait for certain time (ms). Default: 300ms */
276
138
  wait(duration?: number): Promise<void>;
277
- /**
278
- * Waits until the element is attached, visible and enabled, focuses it and presses `key` with real keyboard input.
279
- * Named keys are `Enter`, `Escape`, `Tab`, `Backspace`, `Delete`, `Space`, `Insert`, `Home`, `End`, `PageUp`, `PageDown`,
280
- * `F1` to `F12` and the arrows; any other key must be a single character. A chord holds modifiers (`Control`, `Shift`,
281
- * `Alt`, `Meta`, `ControlOrMeta`) while the last key is pressed.
282
- * @example
283
- * await page.getByLabel("New todo").press("Enter");
284
- * await page.getByLabel("Name").press("Control+a");
285
- */
286
- press(key: string, options?: ActionOptions & {
287
- delay?: number;
288
- }): Promise<void>;
289
- /** Waits until the field is editable and not covered, then replaces its value by typing `value`; an empty string clears it */
290
- fill(value: string, options?: ActionOptions & {
291
- output?: string;
292
- }): Promise<void>;
293
139
  }