mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: implement common functions for BiDi (#10345)
This commit is contained in:
parent
e3e68a99d2
commit
a31231ef54
@ -29,7 +29,7 @@ import {
|
||||
NodeFor,
|
||||
} from '../common/types.js';
|
||||
import {KeyInput} from '../common/USKeyboardLayout.js';
|
||||
import {withSourcePuppeteerURLIfNone} from '../common/util.js';
|
||||
import {isString, withSourcePuppeteerURLIfNone} from '../common/util.js';
|
||||
import {assert} from '../util/assert.js';
|
||||
import {AsyncIterableUtil} from '../util/AsyncIterableUtil.js';
|
||||
|
||||
@ -428,9 +428,11 @@ export class ElementHandle<
|
||||
* If there are no such elements, the method will resolve to an empty array.
|
||||
* @param expression - Expression to {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate | evaluate}
|
||||
*/
|
||||
async $x(expression: string): Promise<Array<ElementHandle<Node>>>;
|
||||
async $x(): Promise<Array<ElementHandle<Node>>> {
|
||||
throw new Error('Not implemented');
|
||||
async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
|
||||
if (expression.startsWith('//')) {
|
||||
expression = `.${expression}`;
|
||||
}
|
||||
return this.$$(`xpath/${expression}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -472,12 +474,15 @@ export class ElementHandle<
|
||||
*/
|
||||
async waitForSelector<Selector extends string>(
|
||||
selector: Selector,
|
||||
options?: WaitForSelectorOptions
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null>;
|
||||
async waitForSelector<Selector extends string>(): Promise<ElementHandle<
|
||||
NodeFor<Selector>
|
||||
> | null> {
|
||||
throw new Error('Not implemented');
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
const {updatedSelector, QueryHandler} =
|
||||
getQueryHandlerAndSelector(selector);
|
||||
return (await QueryHandler.waitFor(
|
||||
this,
|
||||
updatedSelector,
|
||||
options
|
||||
)) as ElementHandle<NodeFor<Selector>> | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -591,11 +596,14 @@ export class ElementHandle<
|
||||
*/
|
||||
async toElement<
|
||||
K extends keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap
|
||||
>(tagName: K): Promise<HandleFor<ElementFor<K>>>;
|
||||
async toElement<
|
||||
K extends keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap
|
||||
>(): Promise<HandleFor<ElementFor<K>>> {
|
||||
throw new Error('Not implemented');
|
||||
>(tagName: K): Promise<HandleFor<ElementFor<K>>> {
|
||||
const isMatchingTagName = await this.evaluate((node, tagName) => {
|
||||
return node.nodeName === tagName.toUpperCase();
|
||||
}, tagName);
|
||||
if (!isMatchingTagName) {
|
||||
throw new Error(`Element is not a(n) \`${tagName}\` element`);
|
||||
}
|
||||
return this as unknown as HandleFor<ElementFor<K>>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -708,9 +716,48 @@ export class ElementHandle<
|
||||
* `multiple` attribute, all values are considered, otherwise only the first
|
||||
* one is taken into account.
|
||||
*/
|
||||
async select(...values: string[]): Promise<string[]>;
|
||||
async select(): Promise<string[]> {
|
||||
throw new Error('Not implemented');
|
||||
async select(...values: string[]): Promise<string[]> {
|
||||
for (const value of values) {
|
||||
assert(
|
||||
isString(value),
|
||||
'Values must be strings. Found value "' +
|
||||
value +
|
||||
'" of type "' +
|
||||
typeof value +
|
||||
'"'
|
||||
);
|
||||
}
|
||||
|
||||
return this.evaluate((element, vals): string[] => {
|
||||
const values = new Set(vals);
|
||||
if (!(element instanceof HTMLSelectElement)) {
|
||||
throw new Error('Element is not a <select> element.');
|
||||
}
|
||||
|
||||
const selectedValues = new Set<string>();
|
||||
if (!element.multiple) {
|
||||
for (const option of element.options) {
|
||||
option.selected = false;
|
||||
}
|
||||
for (const option of element.options) {
|
||||
if (values.has(option.value)) {
|
||||
option.selected = true;
|
||||
selectedValues.add(option.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const option of element.options) {
|
||||
option.selected = values.has(option.value);
|
||||
if (option.selected) {
|
||||
selectedValues.add(option.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
element.dispatchEvent(new Event('input', {bubbles: true}));
|
||||
element.dispatchEvent(new Event('change', {bubbles: true}));
|
||||
return [...selectedValues.values()];
|
||||
}, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -757,7 +804,12 @@ export class ElementHandle<
|
||||
* Calls {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus | focus} on the element.
|
||||
*/
|
||||
async focus(): Promise<void> {
|
||||
throw new Error('Not implemented');
|
||||
await this.evaluate(element => {
|
||||
if (!(element instanceof HTMLElement)) {
|
||||
throw new Error('Cannot focus non-HTMLElement');
|
||||
}
|
||||
return element.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -908,7 +960,14 @@ export class ElementHandle<
|
||||
* or by calling element.scrollIntoView.
|
||||
*/
|
||||
async scrollIntoView(this: ElementHandle<Element>): Promise<void> {
|
||||
throw new Error('Not implemented');
|
||||
await this.assertConnectedElement();
|
||||
await this.evaluate(async (element): Promise<void> => {
|
||||
element.scrollIntoView({
|
||||
block: 'center',
|
||||
inline: 'center',
|
||||
behavior: 'instant',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1125,9 +1125,8 @@ export class Page extends EventEmitter {
|
||||
*
|
||||
* @param expression - Expression to evaluate
|
||||
*/
|
||||
async $x(expression: string): Promise<Array<ElementHandle<Node>>>;
|
||||
async $x(): Promise<Array<ElementHandle<Node>>> {
|
||||
throw new Error('Not implemented');
|
||||
async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
|
||||
return this.mainFrame().$x(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2642,12 +2641,9 @@ export class Page extends EventEmitter {
|
||||
*/
|
||||
async waitForSelector<Selector extends string>(
|
||||
selector: Selector,
|
||||
options?: WaitForSelectorOptions
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null>;
|
||||
async waitForSelector<Selector extends string>(): Promise<ElementHandle<
|
||||
NodeFor<Selector>
|
||||
> | null> {
|
||||
throw new Error('Not implemented');
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
return await this.mainFrame().waitForSelector(selector, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,7 +107,10 @@ export interface SnapshotOptions {
|
||||
root?: ElementHandle<Node>;
|
||||
}
|
||||
|
||||
interface DataProvider {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface DataProvider {
|
||||
getFullAXTree(): Promise<Protocol.Accessibility.GetFullAXTreeResponse>;
|
||||
describeNode(id: string): Promise<Protocol.DOM.DescribeNodeResponse>;
|
||||
}
|
||||
|
@ -32,15 +32,14 @@ import {CDPSession} from './Connection.js';
|
||||
import {ExecutionContext} from './ExecutionContext.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {FrameManager} from './FrameManager.js';
|
||||
import {getQueryHandlerAndSelector} from './GetQueryHandler.js';
|
||||
import {WaitForSelectorOptions} from './IsolatedWorld.js';
|
||||
import {PUPPETEER_WORLD} from './IsolatedWorlds.js';
|
||||
import {CDPJSHandle} from './JSHandle.js';
|
||||
import {LazyArg} from './LazyArg.js';
|
||||
import {CDPPage} from './Page.js';
|
||||
import {ElementFor, HandleFor, NodeFor} from './types.js';
|
||||
import {NodeFor} from './types.js';
|
||||
import {KeyInput} from './USKeyboardLayout.js';
|
||||
import {debugError, isString} from './util.js';
|
||||
import {debugError} from './util.js';
|
||||
|
||||
const applyOffsetsToQuad = (
|
||||
quad: Point[],
|
||||
@ -120,26 +119,13 @@ export class CDPElementHandle<
|
||||
>;
|
||||
}
|
||||
|
||||
override async $x(
|
||||
expression: string
|
||||
): Promise<Array<CDPElementHandle<Node>>> {
|
||||
if (expression.startsWith('//')) {
|
||||
expression = `.${expression}`;
|
||||
}
|
||||
return this.$$(`xpath/${expression}`);
|
||||
}
|
||||
|
||||
override async waitForSelector<Selector extends string>(
|
||||
selector: Selector,
|
||||
options: WaitForSelectorOptions = {}
|
||||
options?: WaitForSelectorOptions
|
||||
): Promise<CDPElementHandle<NodeFor<Selector>> | null> {
|
||||
const {updatedSelector, QueryHandler} =
|
||||
getQueryHandlerAndSelector(selector);
|
||||
return (await QueryHandler.waitFor(
|
||||
this,
|
||||
updatedSelector,
|
||||
options
|
||||
)) as CDPElementHandle<NodeFor<Selector>> | null;
|
||||
return (await super.waitForSelector(selector, options)) as CDPElementHandle<
|
||||
NodeFor<Selector>
|
||||
> | null;
|
||||
}
|
||||
|
||||
override async waitForXPath(
|
||||
@ -182,18 +168,6 @@ export class CDPElementHandle<
|
||||
return this.#checkVisibility(false);
|
||||
}
|
||||
|
||||
override async toElement<
|
||||
K extends keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap
|
||||
>(tagName: K): Promise<HandleFor<ElementFor<K>>> {
|
||||
const isMatchingTagName = await this.evaluate((node, tagName) => {
|
||||
return node.nodeName === tagName.toUpperCase();
|
||||
}, tagName);
|
||||
if (!isMatchingTagName) {
|
||||
throw new Error(`Element is not a(n) \`${tagName}\` element`);
|
||||
}
|
||||
return this as unknown as HandleFor<ElementFor<K>>;
|
||||
}
|
||||
|
||||
override async contentFrame(): Promise<Frame | null> {
|
||||
const nodeInfo = await this.client.send('DOM.describeNode', {
|
||||
objectId: this.id,
|
||||
@ -208,7 +182,6 @@ export class CDPElementHandle<
|
||||
this: CDPElementHandle<Element>
|
||||
): Promise<void> {
|
||||
await this.assertConnectedElement();
|
||||
|
||||
try {
|
||||
await this.client.send('DOM.scrollIntoViewIfNeeded', {
|
||||
objectId: this.id,
|
||||
@ -216,13 +189,7 @@ export class CDPElementHandle<
|
||||
} catch (error) {
|
||||
debugError(error);
|
||||
// Fallback to Element.scrollIntoView if DOM.scrollIntoViewIfNeeded is not supported
|
||||
await this.evaluate(async (element): Promise<void> => {
|
||||
element.scrollIntoView({
|
||||
block: 'center',
|
||||
inline: 'center',
|
||||
behavior: 'instant',
|
||||
});
|
||||
});
|
||||
await super.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,50 +419,6 @@ export class CDPElementHandle<
|
||||
await this.#page.mouse.dragAndDrop(startPoint, targetPoint, options);
|
||||
}
|
||||
|
||||
override async select(...values: string[]): Promise<string[]> {
|
||||
for (const value of values) {
|
||||
assert(
|
||||
isString(value),
|
||||
'Values must be strings. Found value "' +
|
||||
value +
|
||||
'" of type "' +
|
||||
typeof value +
|
||||
'"'
|
||||
);
|
||||
}
|
||||
|
||||
return this.evaluate((element, vals): string[] => {
|
||||
const values = new Set(vals);
|
||||
if (!(element instanceof HTMLSelectElement)) {
|
||||
throw new Error('Element is not a <select> element.');
|
||||
}
|
||||
|
||||
const selectedValues = new Set<string>();
|
||||
if (!element.multiple) {
|
||||
for (const option of element.options) {
|
||||
option.selected = false;
|
||||
}
|
||||
for (const option of element.options) {
|
||||
if (values.has(option.value)) {
|
||||
option.selected = true;
|
||||
selectedValues.add(option.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const option of element.options) {
|
||||
option.selected = values.has(option.value);
|
||||
if (option.selected) {
|
||||
selectedValues.add(option.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
element.dispatchEvent(new Event('input', {bubbles: true}));
|
||||
element.dispatchEvent(new Event('change', {bubbles: true}));
|
||||
return [...selectedValues.values()];
|
||||
}, values);
|
||||
}
|
||||
|
||||
override async uploadFile(
|
||||
this: CDPElementHandle<HTMLInputElement>,
|
||||
...filePaths: string[]
|
||||
@ -577,15 +500,6 @@ export class CDPElementHandle<
|
||||
await this.#page.touchscreen.touchEnd();
|
||||
}
|
||||
|
||||
override async focus(): Promise<void> {
|
||||
await this.evaluate(element => {
|
||||
if (!(element instanceof HTMLElement)) {
|
||||
throw new Error('Cannot focus non-HTMLElement');
|
||||
}
|
||||
return element.focus();
|
||||
});
|
||||
}
|
||||
|
||||
override async type(text: string, options?: {delay: number}): Promise<void> {
|
||||
await this.focus();
|
||||
await this.#page.keyboard.type(text, options);
|
||||
|
@ -531,12 +531,6 @@ export class Frame extends BaseFrame {
|
||||
return this.worlds[PUPPETEER_WORLD].type(selector, text, options);
|
||||
}
|
||||
|
||||
override waitForTimeout(milliseconds: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, milliseconds);
|
||||
});
|
||||
}
|
||||
|
||||
override async title(): Promise<string> {
|
||||
return this.worlds[PUPPETEER_WORLD].title();
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ import {TargetManagerEmittedEvents} from './TargetManager.js';
|
||||
import {TaskQueue} from './TaskQueue.js';
|
||||
import {TimeoutSettings} from './TimeoutSettings.js';
|
||||
import {Tracing} from './Tracing.js';
|
||||
import {BindingPayload, EvaluateFunc, HandleFor, NodeFor} from './types.js';
|
||||
import {BindingPayload, EvaluateFunc, HandleFor} from './types.js';
|
||||
import {
|
||||
createClientError,
|
||||
createJSHandle,
|
||||
@ -554,10 +554,6 @@ export class CDPPage extends Page {
|
||||
return createJSHandle(context, response.objects) as HandleFor<Prototype[]>;
|
||||
}
|
||||
|
||||
override async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
|
||||
return this.mainFrame().$x(expression);
|
||||
}
|
||||
|
||||
override async cookies(
|
||||
...urls: string[]
|
||||
): Promise<Protocol.Network.Cookie[]> {
|
||||
@ -1557,13 +1553,6 @@ export class CDPPage extends Page {
|
||||
return this.mainFrame().waitForTimeout(milliseconds);
|
||||
}
|
||||
|
||||
override async waitForSelector<Selector extends string>(
|
||||
selector: Selector,
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
return await this.mainFrame().waitForSelector(selector, options);
|
||||
}
|
||||
|
||||
override waitForXPath(
|
||||
xpath: string,
|
||||
options: WaitForSelectorOptions = {}
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
Browser as BrowserBase,
|
||||
BrowserCloseCallback,
|
||||
BrowserContextOptions,
|
||||
BrowserEmittedEvents,
|
||||
} from '../../api/Browser.js';
|
||||
import {BrowserContext as BrowserContextBase} from '../../api/BrowserContext.js';
|
||||
import {Viewport} from '../PuppeteerViewport.js';
|
||||
@ -59,6 +60,10 @@ export class Browser extends BrowserBase {
|
||||
this.#closeCallback = opts.closeCallback;
|
||||
this.#connection = opts.connection;
|
||||
this.#defaultViewport = opts.defaultViewport;
|
||||
|
||||
this.#process?.on('close', () => {
|
||||
return this.emit(BrowserEmittedEvents.Disconnected);
|
||||
});
|
||||
}
|
||||
|
||||
get connection(): Connection {
|
||||
|
@ -94,4 +94,8 @@ export class BrowserContext extends BrowserContextBase {
|
||||
override browser(): Browser {
|
||||
return this.#browser;
|
||||
}
|
||||
|
||||
override async pages(): Promise<PageBase[]> {
|
||||
return [...this.#pages.values()];
|
||||
}
|
||||
}
|
||||
|
@ -177,6 +177,10 @@ export class Frame extends BaseFrame {
|
||||
return this.sandboxes[MAIN_SANDBOX].$$eval(selector, pageFunction, ...args);
|
||||
}
|
||||
|
||||
override $x(expression: string): Promise<Array<ElementHandle<Node>>> {
|
||||
return this.sandboxes[MAIN_SANDBOX].$x(expression);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.#context.dispose();
|
||||
}
|
||||
|
@ -112,4 +112,9 @@ export class Sandbox {
|
||||
const document = await this.document();
|
||||
return document.$$eval(selector, pageFunction, ...args);
|
||||
}
|
||||
|
||||
async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
|
||||
const document = await this.document();
|
||||
return document.$x(expression);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,18 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.isIntersectingViewport *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -203,6 +215,12 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[queryselector.spec] querySelector *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[accessibility.spec] *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -257,6 +275,30 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries should wait correctly with waitFor",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries should wait correctly with waitForSelector",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries should wait correctly with waitForSelector on an element",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Element.toElement should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.isVisible and ElementHandle.isHidden should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -372,15 +414,9 @@
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[jshandle.spec] JSHandle JSHandle.jsonValue should not work with dates",
|
||||
"testIdPattern": "[jshandle.spec] JSHandle JSHandle.jsonValue should work with dates",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[jshandle.spec] JSHandle JSHandle.toString should work for complicated objects",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"parameters": ["cdp"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
@ -413,6 +449,12 @@
|
||||
"parameters": ["chrome"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.launch tmp profile should be cleaned up",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[navigation.spec] navigation \"after each\" hook for \"should work with both domcontentloaded and load\"",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -695,6 +737,18 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL", "PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |browserURL| option should be able to connect using browserUrl, with and without trailing slash",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |browserURL| option should throw when trying to connect to non-existing browser",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[click.spec] Page.click should click on checkbox label and toggle",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1019,12 +1073,6 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[jshandle.spec] JSHandle JSHandle.jsonValue should not work with dates",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[jshandle.spec] JSHandle JSHandle.toString should work with different subtypes",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1193,6 +1241,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.launch tmp profile should be cleaned up",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[launcher.spec] Launcher specs Puppeteer Puppeteer.launch userDataDir argument with non-existent dir",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
|
@ -467,12 +467,23 @@ describe('ElementHandle specs', function () {
|
||||
it('should work', async () => {
|
||||
const {page, server} = getTestState();
|
||||
|
||||
async function getVisibilityForButton(selector: string) {
|
||||
const button = (await page.$(selector))!;
|
||||
return await button.isIntersectingViewport();
|
||||
}
|
||||
|
||||
await page.goto(server.PREFIX + '/offscreenbuttons.html');
|
||||
const buttonsPromises = [];
|
||||
// Firefox seems slow when using `isIntersectingViewport`
|
||||
// so we do all the tasks asynchronously
|
||||
for (let i = 0; i < 11; ++i) {
|
||||
buttonsPromises.push(getVisibilityForButton('#btn' + i));
|
||||
}
|
||||
const buttonVisibility = await Promise.all(buttonsPromises);
|
||||
for (let i = 0; i < 11; ++i) {
|
||||
const button = (await page.$('#btn' + i))!;
|
||||
// All but last button are visible.
|
||||
const visible = i < 10;
|
||||
expect(await button.isIntersectingViewport()).toBe(visible);
|
||||
expect(buttonVisibility[i]).toBe(visible);
|
||||
}
|
||||
});
|
||||
it('should work with threshold', async () => {
|
||||
@ -505,51 +516,69 @@ describe('ElementHandle specs', function () {
|
||||
const {page, server} = getTestState();
|
||||
|
||||
await page.goto(server.PREFIX + '/inline-svg.html');
|
||||
const visibleCircle = await page.$('circle');
|
||||
const visibleSvg = await page.$('svg');
|
||||
expect(
|
||||
await visibleCircle!.isIntersectingViewport({
|
||||
threshold: 1,
|
||||
})
|
||||
).toBe(true);
|
||||
expect(
|
||||
await visibleCircle!.isIntersectingViewport({
|
||||
threshold: 0,
|
||||
})
|
||||
).toBe(true);
|
||||
expect(
|
||||
await visibleSvg!.isIntersectingViewport({
|
||||
threshold: 1,
|
||||
})
|
||||
).toBe(true);
|
||||
expect(
|
||||
await visibleSvg!.isIntersectingViewport({
|
||||
threshold: 0,
|
||||
})
|
||||
).toBe(true);
|
||||
const [visibleCircle, visibleSvg] = await Promise.all([
|
||||
page.$('circle'),
|
||||
page.$('svg'),
|
||||
]);
|
||||
|
||||
const invisibleCircle = await page.$('div circle');
|
||||
const invisibleSvg = await page.$('div svg');
|
||||
expect(
|
||||
await invisibleCircle!.isIntersectingViewport({
|
||||
// Firefox seems slow when using `isIntersectingViewport`
|
||||
// so we do all the tasks asynchronously
|
||||
const [
|
||||
circleThresholdOne,
|
||||
circleThresholdZero,
|
||||
svgThresholdOne,
|
||||
svgThresholdZero,
|
||||
] = await Promise.all([
|
||||
visibleCircle!.isIntersectingViewport({
|
||||
threshold: 1,
|
||||
})
|
||||
).toBe(false);
|
||||
expect(
|
||||
await invisibleCircle!.isIntersectingViewport({
|
||||
}),
|
||||
visibleCircle!.isIntersectingViewport({
|
||||
threshold: 0,
|
||||
})
|
||||
).toBe(false);
|
||||
expect(
|
||||
await invisibleSvg!.isIntersectingViewport({
|
||||
}),
|
||||
visibleSvg!.isIntersectingViewport({
|
||||
threshold: 1,
|
||||
})
|
||||
).toBe(false);
|
||||
expect(
|
||||
await invisibleSvg!.isIntersectingViewport({
|
||||
}),
|
||||
visibleSvg!.isIntersectingViewport({
|
||||
threshold: 0,
|
||||
})
|
||||
).toBe(false);
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(circleThresholdOne).toBe(true);
|
||||
expect(circleThresholdZero).toBe(true);
|
||||
expect(svgThresholdOne).toBe(true);
|
||||
expect(svgThresholdZero).toBe(true);
|
||||
|
||||
const [invisibleCircle, invisibleSvg] = await Promise.all([
|
||||
page.$('div circle'),
|
||||
await page.$('div svg'),
|
||||
]);
|
||||
|
||||
// Firefox seems slow when using `isIntersectingViewport`
|
||||
// so we do all the tasks asynchronously
|
||||
const [
|
||||
invisibleCircleThresholdOne,
|
||||
invisibleCircleThresholdZero,
|
||||
invisibleSvgThresholdOne,
|
||||
invisibleSvgThresholdZero,
|
||||
] = await Promise.all([
|
||||
invisibleCircle!.isIntersectingViewport({
|
||||
threshold: 1,
|
||||
}),
|
||||
invisibleCircle!.isIntersectingViewport({
|
||||
threshold: 0,
|
||||
}),
|
||||
invisibleSvg!.isIntersectingViewport({
|
||||
threshold: 1,
|
||||
}),
|
||||
invisibleSvg!.isIntersectingViewport({
|
||||
threshold: 0,
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(invisibleCircleThresholdOne).toBe(false);
|
||||
expect(invisibleCircleThresholdZero).toBe(false);
|
||||
expect(invisibleSvgThresholdOne).toBe(false);
|
||||
expect(invisibleSvgThresholdZero).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -158,14 +158,14 @@ describe('JSHandle', function () {
|
||||
expect(await bHandle.jsonValue()).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should not work with dates', async () => {
|
||||
it('should work with dates', async () => {
|
||||
const {page} = getTestState();
|
||||
|
||||
const dateHandle = await page.evaluateHandle(() => {
|
||||
return new Date('2017-09-26T00:00:00.000Z');
|
||||
});
|
||||
const json = await dateHandle.jsonValue();
|
||||
expect(json).toEqual({});
|
||||
const date = await dateHandle.jsonValue();
|
||||
expect(date.toISOString()).toEqual('2017-09-26T00:00:00.000Z');
|
||||
});
|
||||
it('should throw for circular objects', async () => {
|
||||
const {page} = getTestState();
|
||||
@ -277,7 +277,10 @@ describe('JSHandle', function () {
|
||||
const aHandle = await page.evaluateHandle(() => {
|
||||
return window;
|
||||
});
|
||||
expect(aHandle.toString()).toBe('JSHandle@object');
|
||||
expect(aHandle.toString()).atLeastOneToContain([
|
||||
'JSHandle@object',
|
||||
'JSHandle@window',
|
||||
]);
|
||||
});
|
||||
it('should work with different subtypes', async () => {
|
||||
const {page} = getTestState();
|
||||
|
Loading…
Reference in New Issue
Block a user