Skip to content

Commit 3c35d7b

Browse files
authored
api(waitFor): click(waitFor) -> click(force) (#1275)
1 parent 578880c commit 3c35d7b

File tree

9 files changed

+166
-133
lines changed

9 files changed

+166
-133
lines changed

docs/api.md

+90-28
Large diffs are not rendered by default.

src/dom.ts

+15-17
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,14 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
241241
return point;
242242
}
243243

244-
async _performPointerAction(action: (point: types.Point) => Promise<void>, options?: PointerActionOptions & types.ActionWaitOptions): Promise<void> {
245-
const { waitFor = true } = (options || {});
246-
if (!helper.isBoolean(waitFor))
247-
throw new Error('waitFor option should be a boolean, got "' + (typeof waitFor) + '"');
248-
if (waitFor)
244+
async _performPointerAction(action: (point: types.Point) => Promise<void>, options?: PointerActionOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions): Promise<void> {
245+
const { force = false } = (options || {});
246+
if (!force)
249247
await this._waitForDisplayedAtStablePosition(options);
250248
const offset = options ? options.offset : undefined;
251249
await this._scrollRectIntoViewIfNeeded(offset ? { x: offset.x, y: offset.y, width: 0, height: 0 } : undefined);
252250
const point = offset ? await this._offsetPoint(offset) : await this._clickablePoint();
253-
if (waitFor)
251+
if (!force)
254252
await this._waitForHitTargetAt(point, options);
255253

256254
await this._page._frameManager.waitForNavigationsCreatedBy(async () => {
@@ -263,23 +261,23 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
263261
}, options);
264262
}
265263

266-
hover(options?: PointerActionOptions & types.ActionWaitOptionsNoNavigation): Promise<void> {
264+
hover(options?: PointerActionOptions & types.PointerActionWaitOptions): Promise<void> {
267265
return this._performPointerAction(point => this._page.mouse.move(point.x, point.y), options);
268266
}
269267

270-
click(options?: ClickOptions & types.ActionWaitOptions): Promise<void> {
268+
click(options?: ClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions): Promise<void> {
271269
return this._performPointerAction(point => this._page.mouse.click(point.x, point.y, options), options);
272270
}
273271

274-
dblclick(options?: MultiClickOptions & types.ActionWaitOptions): Promise<void> {
272+
dblclick(options?: MultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions): Promise<void> {
275273
return this._performPointerAction(point => this._page.mouse.dblclick(point.x, point.y, options), options);
276274
}
277275

278-
tripleclick(options?: MultiClickOptions & types.ActionWaitOptions): Promise<void> {
276+
tripleclick(options?: MultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions): Promise<void> {
279277
return this._performPointerAction(point => this._page.mouse.tripleclick(point.x, point.y, options), options);
280278
}
281279

282-
async select(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[], options?: types.ActionWaitOptionsNoWaitFor): Promise<string[]> {
280+
async select(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[], options?: types.NavigatingActionWaitOptions): Promise<string[]> {
283281
let vals: string[] | ElementHandle[] | types.SelectOption[];
284282
if (!Array.isArray(values))
285283
vals = [ values ] as (string[] | ElementHandle[] | types.SelectOption[]);
@@ -301,7 +299,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
301299
}, options);
302300
}
303301

304-
async fill(value: string, options?: types.ActionWaitOptionsNoWaitFor): Promise<void> {
302+
async fill(value: string, options?: types.NavigatingActionWaitOptions): Promise<void> {
305303
assert(helper.isString(value), 'Value must be string. Found value "' + value + '" of type "' + (typeof value) + '"');
306304
await this._page._frameManager.waitForNavigationsCreatedBy(async () => {
307305
const error = await this._evaluateInUtility((injected, node, value) => injected.fill(node, value), value);
@@ -356,29 +354,29 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
356354
throw new Error(errorMessage);
357355
}
358356

359-
async type(text: string, options?: { delay?: number } & types.ActionWaitOptionsNoWaitFor) {
357+
async type(text: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) {
360358
await this._page._frameManager.waitForNavigationsCreatedBy(async () => {
361359
await this.focus();
362360
await this._page.keyboard.type(text, options);
363361
}, options);
364362
}
365363

366-
async press(key: string, options?: { delay?: number, text?: string } & types.ActionWaitOptionsNoWaitFor) {
364+
async press(key: string, options?: { delay?: number, text?: string } & types.NavigatingActionWaitOptions) {
367365
await this._page._frameManager.waitForNavigationsCreatedBy(async () => {
368366
await this.focus();
369367
await this._page.keyboard.press(key, options);
370368
}, options);
371369
}
372370

373-
async check(options?: types.ActionWaitOptions) {
371+
async check(options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
374372
await this._setChecked(true, options);
375373
}
376374

377-
async uncheck(options?: types.ActionWaitOptions) {
375+
async uncheck(options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
378376
await this._setChecked(false, options);
379377
}
380378

381-
private async _setChecked(state: boolean, options?: types.ActionWaitOptions) {
379+
private async _setChecked(state: boolean, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
382380
if (await this._evaluateInUtility((injected, node) => injected.isCheckboxChecked(node)) === state)
383381
return;
384382
await this.click(options);

src/frames.ts

+38-53
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class FrameManager {
100100
}
101101
}
102102

103-
async waitForNavigationsCreatedBy<T>(action: () => Promise<T>, options?: types.ActionWaitOptionsNoWaitFor): Promise<T> {
103+
async waitForNavigationsCreatedBy<T>(action: () => Promise<T>, options?: types.NavigatingActionWaitOptions): Promise<T> {
104104
if (options && options.waitUntil === 'nowait')
105105
return action();
106106
const barrier = new PendingNavigationBarrier(options);
@@ -583,10 +583,20 @@ export class Frame {
583583
async waitForSelector(selector: string, options?: types.WaitForElementOptions): Promise<dom.ElementHandle<Element> | null> {
584584
if (options && (options as any).visibility)
585585
throw new Error('options.visibility is not supported, did you mean options.waitFor?');
586-
const handle = await this._waitForSelectorInUtilityContext(selector, options);
586+
const { timeout = this._page._timeoutSettings.timeout(), waitFor = 'attached' } = (options || {});
587+
if (!['attached', 'detached', 'visible', 'hidden'].includes(waitFor))
588+
throw new Error(`Unsupported waitFor option "${waitFor}"`);
589+
590+
const task = dom.waitForSelectorTask(selector, waitFor, timeout);
591+
const result = await this._scheduleRerunnableTask(task, 'utility', timeout, `selector "${selectorToString(selector, waitFor)}"`);
592+
if (!result.asElement()) {
593+
result.dispose();
594+
return null;
595+
}
596+
const handle = result.asElement() as dom.ElementHandle<Element>;
587597
const mainContext = await this._mainContext();
588598
if (handle && handle._context !== mainContext) {
589-
const adopted = this._page._delegate.adoptElementHandle(handle, mainContext);
599+
const adopted = await this._page._delegate.adoptElementHandle(handle, mainContext);
590600
handle.dispose();
591601
return adopted;
592602
}
@@ -801,69 +811,69 @@ export class Frame {
801811
return result!;
802812
}
803813

804-
async click(selector: string, options?: dom.ClickOptions & types.ActionWaitOptions) {
805-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
814+
async click(selector: string, options?: dom.ClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
815+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
806816
await handle.click(options);
807817
handle.dispose();
808818
}
809819

810-
async dblclick(selector: string, options?: dom.MultiClickOptions & types.ActionWaitOptions) {
811-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
820+
async dblclick(selector: string, options?: dom.MultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
821+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
812822
await handle.dblclick(options);
813823
handle.dispose();
814824
}
815825

816-
async tripleclick(selector: string, options?: dom.MultiClickOptions & types.ActionWaitOptions) {
817-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
826+
async tripleclick(selector: string, options?: dom.MultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
827+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
818828
await handle.tripleclick(options);
819829
handle.dispose();
820830
}
821831

822-
async fill(selector: string, value: string, options?: types.ActionWaitOptions) {
823-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
832+
async fill(selector: string, value: string, options?: types.NavigatingActionWaitOptions) {
833+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
824834
await handle.fill(value, options);
825835
handle.dispose();
826836
}
827837

828-
async focus(selector: string, options?: types.ActionWaitOptionsNoNavigation) {
829-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
838+
async focus(selector: string, options?: types.TimeoutOptions) {
839+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
830840
await handle.focus();
831841
handle.dispose();
832842
}
833843

834-
async hover(selector: string, options?: dom.PointerActionOptions & types.ActionWaitOptionsNoNavigation) {
835-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
844+
async hover(selector: string, options?: dom.PointerActionOptions & types.PointerActionWaitOptions) {
845+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
836846
await handle.hover(options);
837847
handle.dispose();
838848
}
839849

840-
async select(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options?: types.ActionWaitOptions): Promise<string[]> {
841-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
850+
async select(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options?: types.NavigatingActionWaitOptions): Promise<string[]> {
851+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
842852
const result = await handle.select(values, options);
843853
handle.dispose();
844854
return result;
845855
}
846856

847-
async type(selector: string, text: string, options?: { delay?: number } & types.ActionWaitOptions) {
848-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
857+
async type(selector: string, text: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) {
858+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
849859
await handle.type(text, options);
850860
handle.dispose();
851861
}
852862

853-
async press(selector: string, key: string, options?: { delay?: number, text?: string } & types.ActionWaitOptions) {
854-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
863+
async press(selector: string, key: string, options?: { delay?: number, text?: string } & types.NavigatingActionWaitOptions) {
864+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
855865
await handle.press(key, options);
856866
handle.dispose();
857867
}
858868

859-
async check(selector: string, options?: types.ActionWaitOptions) {
860-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
869+
async check(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
870+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
861871
await handle.check(options);
862872
handle.dispose();
863873
}
864874

865-
async uncheck(selector: string, options?: types.ActionWaitOptions) {
866-
const handle = await this._optionallyWaitForSelectorInUtilityContext(selector, options);
875+
async uncheck(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
876+
const handle = await this._waitForSelectorInUtilityContext(selector, options);
867877
await handle.uncheck(options);
868878
handle.dispose();
869879
}
@@ -878,35 +888,10 @@ export class Frame {
878888
return Promise.reject(new Error('Unsupported target type: ' + (typeof selectorOrFunctionOrTimeout)));
879889
}
880890

881-
private async _optionallyWaitForSelectorInUtilityContext(selector: string, options: types.ActionWaitOptions | undefined): Promise<dom.ElementHandle<Element>> {
882-
const { timeout = this._page._timeoutSettings.timeout(), waitFor = true } = (options || {});
883-
if (!helper.isBoolean(waitFor))
884-
throw new Error('waitFor option should be a boolean, got "' + (typeof waitFor) + '"');
885-
let handle: dom.ElementHandle<Element>;
886-
if (waitFor) {
887-
const maybeHandle = await this._waitForSelectorInUtilityContext(selector, { timeout, waitFor: 'attached' });
888-
if (!maybeHandle)
889-
throw new Error('No node found for selector: ' + selectorToString(selector, 'attached'));
890-
handle = maybeHandle;
891-
} else {
892-
const context = await this._context('utility');
893-
const maybeHandle = await context._$(selector);
894-
assert(maybeHandle, 'No node found for selector: ' + selector);
895-
handle = maybeHandle;
896-
}
897-
return handle;
898-
}
899-
900-
private async _waitForSelectorInUtilityContext(selector: string, options?: types.WaitForElementOptions): Promise<dom.ElementHandle<Element> | null> {
891+
private async _waitForSelectorInUtilityContext(selector: string, options?: types.WaitForElementOptions): Promise<dom.ElementHandle<Element>> {
901892
const { timeout = this._page._timeoutSettings.timeout(), waitFor = 'attached' } = (options || {});
902-
if (!['attached', 'detached', 'visible', 'hidden'].includes(waitFor))
903-
throw new Error(`Unsupported waitFor option "${waitFor}"`);
904893
const task = dom.waitForSelectorTask(selector, waitFor, timeout);
905894
const result = await this._scheduleRerunnableTask(task, 'utility', timeout, `selector "${selectorToString(selector, waitFor)}"`);
906-
if (!result.asElement()) {
907-
result.dispose();
908-
return null;
909-
}
910895
return result.asElement() as dom.ElementHandle<Element>;
911896
}
912897

@@ -1099,12 +1084,12 @@ function selectorToString(selector: string, waitFor: 'attached' | 'detached' | '
10991084

11001085
class PendingNavigationBarrier {
11011086
private _frameIds = new Map<string, number>();
1102-
private _options: types.ActionWaitOptionsNoWaitFor | undefined;
1087+
private _options: types.NavigatingActionWaitOptions | undefined;
11031088
private _protectCount = 0;
11041089
private _promise: Promise<void>;
11051090
private _promiseCallback = () => {};
11061091

1107-
constructor(options: types.ActionWaitOptionsNoWaitFor | undefined) {
1092+
constructor(options: types.NavigatingActionWaitOptions | undefined) {
11081093
this._options = options;
11091094
this._promise = new Promise(f => this._promiseCallback = f);
11101095
this.retain();

src/page.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -433,47 +433,47 @@ export class Page extends platform.EventEmitter {
433433
return this._closed;
434434
}
435435

436-
async click(selector: string, options?: dom.ClickOptions & types.ActionWaitOptions) {
436+
async click(selector: string, options?: dom.ClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
437437
return this.mainFrame().click(selector, options);
438438
}
439439

440-
async dblclick(selector: string, options?: dom.MultiClickOptions & types.ActionWaitOptions) {
440+
async dblclick(selector: string, options?: dom.MultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
441441
return this.mainFrame().dblclick(selector, options);
442442
}
443443

444-
async tripleclick(selector: string, options?: dom.MultiClickOptions & types.ActionWaitOptions) {
444+
async tripleclick(selector: string, options?: dom.MultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
445445
return this.mainFrame().tripleclick(selector, options);
446446
}
447447

448-
async fill(selector: string, value: string, options?: types.ActionWaitOptions) {
448+
async fill(selector: string, value: string, options?: types.NavigatingActionWaitOptions) {
449449
return this.mainFrame().fill(selector, value, options);
450450
}
451451

452-
async focus(selector: string, options?: types.ActionWaitOptionsNoNavigation) {
452+
async focus(selector: string, options?: types.TimeoutOptions) {
453453
return this.mainFrame().focus(selector, options);
454454
}
455455

456-
async hover(selector: string, options?: dom.PointerActionOptions & types.ActionWaitOptionsNoNavigation) {
456+
async hover(selector: string, options?: dom.PointerActionOptions & types.PointerActionWaitOptions) {
457457
return this.mainFrame().hover(selector, options);
458458
}
459459

460-
async select(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options?: types.ActionWaitOptions): Promise<string[]> {
460+
async select(selector: string, values: string | dom.ElementHandle | types.SelectOption | string[] | dom.ElementHandle[] | types.SelectOption[], options?: types.NavigatingActionWaitOptions): Promise<string[]> {
461461
return this.mainFrame().select(selector, values, options);
462462
}
463463

464-
async type(selector: string, text: string, options?: { delay?: number } & types.ActionWaitOptions) {
464+
async type(selector: string, text: string, options?: { delay?: number } & types.NavigatingActionWaitOptions) {
465465
return this.mainFrame().type(selector, text, options);
466466
}
467467

468-
async press(selector: string, key: string, options?: { delay?: number, text?: string } & types.ActionWaitOptions) {
468+
async press(selector: string, key: string, options?: { delay?: number, text?: string } & types.NavigatingActionWaitOptions) {
469469
return this.mainFrame().press(selector, key, options);
470470
}
471471

472-
async check(selector: string, options?: types.ActionWaitOptions) {
472+
async check(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
473473
return this.mainFrame().check(selector, options);
474474
}
475475

476-
async uncheck(selector: string, options?: types.ActionWaitOptions) {
476+
async uncheck(selector: string, options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) {
477477
return this.mainFrame().uncheck(selector, options);
478478
}
479479

src/types.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,14 @@ export type NavigateOptions = TimeoutOptions & {
5151
waitUntil?: LifecycleEvent,
5252
};
5353

54-
export type ActionWaitOptionsNoWaitFor = TimeoutOptions & {
54+
export type NavigatingActionWaitOptions = TimeoutOptions & {
5555
waitUntil?: LifecycleEvent | 'nowait',
5656
};
5757

58-
export type ActionWaitOptionsNoNavigation = TimeoutOptions & {
59-
waitFor?: boolean,
58+
export type PointerActionWaitOptions = TimeoutOptions & {
59+
force?: boolean,
6060
};
6161

62-
export type ActionWaitOptions = ActionWaitOptionsNoWaitFor & ActionWaitOptionsNoNavigation;
63-
6462
export type WaitForNavigationOptions = TimeoutOptions & {
6563
waitUntil?: LifecycleEvent,
6664
url?: URLMatch

0 commit comments

Comments
 (0)