chore: implement boxModel, contentFrame, and nested frame boundingBox (#10773)

This commit is contained in:
jrandolf 2023-08-23 16:58:18 +02:00 committed by GitHub
parent 8fd0157c95
commit 27636afacf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 525 additions and 160 deletions

View File

@ -182,6 +182,7 @@ sidebar_label: API
| [ProtocolLifeCycleEvent](./puppeteer.protocollifecycleevent.md) | |
| [PuppeteerLifeCycleEvent](./puppeteer.puppeteerlifecycleevent.md) | |
| [PuppeteerNodeLaunchOptions](./puppeteer.puppeteernodelaunchoptions.md) | Utility type exposed to enable users to define options that can be passed to <code>puppeteer.launch</code> without having to list the set of all types. |
| [Quad](./puppeteer.quad.md) | |
| [ResourceType](./puppeteer.resourcetype.md) | Resource types for HTTPRequests as perceived by the rendering engine. |
| [TargetFilterCallback](./puppeteer.targetfiltercallback.md) | |
| [VisibilityOption](./puppeteer.visibilityoption.md) | |

View File

@ -12,11 +12,11 @@ export interface BoxModel
## Properties
| Property | Modifiers | Type | Description | Default |
| -------- | --------- | --------------------------------- | ----------- | ------- |
| border | | [Point](./puppeteer.point.md)\[\] | | |
| content | | [Point](./puppeteer.point.md)\[\] | | |
| height | | number | | |
| margin | | [Point](./puppeteer.point.md)\[\] | | |
| padding | | [Point](./puppeteer.point.md)\[\] | | |
| width | | number | | |
| Property | Modifiers | Type | Description | Default |
| -------- | --------- | --------------------------- | ----------- | ------- |
| border | | [Quad](./puppeteer.quad.md) | | |
| content | | [Quad](./puppeteer.quad.md) | | |
| height | | number | | |
| margin | | [Quad](./puppeteer.quad.md) | | |
| padding | | [Quad](./puppeteer.quad.md) | | |
| width | | number | | |

View File

@ -4,16 +4,22 @@ sidebar_label: ElementHandle.contentFrame
# ElementHandle.contentFrame() method
Resolves to the content frame for element handles referencing iframe nodes, or null otherwise
Resolves the frame associated with the element.
#### Signature:
```typescript
class ElementHandle {
contentFrame(): Promise<Frame | null>;
contentFrame(this: ElementHandle<HTMLIFrameElement>): Promise<Frame>;
}
```
## Parameters
| Parameter | Type | Description |
| --------- | ---------------------------------------------------------------------- | ----------- |
| this | [ElementHandle](./puppeteer.elementhandle.md)&lt;HTMLIFrameElement&gt; | |
**Returns:**
Promise&lt;[Frame](./puppeteer.frame.md) \| null&gt;
Promise&lt;[Frame](./puppeteer.frame.md)&gt;

View File

@ -0,0 +1,17 @@
---
sidebar_label: ElementHandle.contentFrame_1
---
# ElementHandle.contentFrame() method
#### Signature:
```typescript
class ElementHandle {
contentFrame(): Promise<Frame | null>;
}
```
**Returns:**
Promise&lt;[Frame](./puppeteer.frame.md) \| null&gt;

View File

@ -60,7 +60,8 @@ The constructor for this class is marked as internal. Third-party code should no
| [boxModel()](./puppeteer.elementhandle.boxmodel.md) | | This method returns boxes of the element, or <code>null</code> if the element is not visible. |
| [click(this, options)](./puppeteer.elementhandle.click.md) | | This method scrolls element into view if needed, and then uses [Page.mouse](./puppeteer.page.md) to click in the center of the element. If the element is detached from DOM, the method throws an error. |
| [clickablePoint(offset)](./puppeteer.elementhandle.clickablepoint.md) | | Returns the middle point within an element unless a specific offset is provided. |
| [contentFrame()](./puppeteer.elementhandle.contentframe.md) | | Resolves to the content frame for element handles referencing iframe nodes, or null otherwise |
| [contentFrame(this)](./puppeteer.elementhandle.contentframe.md) | | Resolves the frame associated with the element. |
| [contentFrame()](./puppeteer.elementhandle.contentframe_1.md) | | |
| [drag(this, target)](./puppeteer.elementhandle.drag.md) | | This method creates and captures a dragevent from the element. |
| [dragAndDrop(this, target, options)](./puppeteer.elementhandle.draganddrop.md) | | This method triggers a dragenter, dragover, and drop on the element. |
| [dragEnter(this, data)](./puppeteer.elementhandle.dragenter.md) | | This method creates a <code>dragenter</code> event on the element. |

View File

@ -0,0 +1,13 @@
---
sidebar_label: Quad
---
# Quad type
#### Signature:
```typescript
export type Quad = [Point, Point, Point, Point];
```
**References:** [Point](./puppeteer.point.md)

View File

@ -30,7 +30,11 @@ import {
NodeFor,
} from '../common/types.js';
import {KeyInput} from '../common/USKeyboardLayout.js';
import {isString, withSourcePuppeteerURLIfNone} from '../common/util.js';
import {
debugError,
isString,
withSourcePuppeteerURLIfNone,
} from '../common/util.js';
import {assert} from '../util/assert.js';
import {AsyncIterableUtil} from '../util/AsyncIterableUtil.js';
@ -42,14 +46,19 @@ import {
import {JSHandle} from './JSHandle.js';
import {ScreenshotOptions} from './Page.js';
/**
* @public
*/
export type Quad = [Point, Point, Point, Point];
/**
* @public
*/
export interface BoxModel {
content: Point[];
padding: Point[];
border: Point[];
margin: Point[];
content: Quad;
padding: Quad;
border: Quad;
margin: Quad;
width: number;
height: number;
}
@ -620,9 +629,10 @@ export class ElementHandle<
}
/**
* Resolves to the content frame for element handles referencing
* iframe nodes, or null otherwise
* Resolves the frame associated with the element.
*/
async contentFrame(this: ElementHandle<HTMLIFrameElement>): Promise<Frame>;
async contentFrame(): Promise<Frame | null>;
async contentFrame(): Promise<Frame | null> {
throw new Error('Not implemented');
}
@ -885,7 +895,72 @@ export class ElementHandle<
* or `null` if the element is not visible.
*/
async boundingBox(): Promise<BoundingBox | null> {
throw new Error('Not implemented');
const adoptedThis = await this.frame.isolatedRealm().adoptHandle(this);
const box = await adoptedThis.evaluate(element => {
if (!(element instanceof Element)) {
return null;
}
// Element is not visible.
if (element.getClientRects().length === 0) {
return null;
}
const rect = element.getBoundingClientRect();
return {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height,
};
});
void adoptedThis.dispose().catch(debugError);
if (!box) {
return null;
}
const offset = await this.#getTopLeftCornerOfFrame();
if (!offset) {
return null;
}
box.x += offset.x;
box.y += offset.y;
return box;
}
async #getTopLeftCornerOfFrame() {
const point = {x: 0, y: 0};
let frame: Frame | null | undefined = this.frame;
let element: HandleFor<HTMLIFrameElement> | null | undefined;
while ((element = await frame?.frameElement())) {
try {
element = await element.frame.isolatedRealm().transferHandle(element);
const parentBox = await element.evaluate(element => {
// Element is not visible.
if (element.getClientRects().length === 0) {
return null;
}
const rect = element.getBoundingClientRect();
const style = window.getComputedStyle(element);
return {
left:
rect.left +
parseInt(style.paddingLeft, 10) +
parseInt(style.borderLeftWidth, 10),
top:
rect.top +
parseInt(style.paddingTop, 10) +
parseInt(style.borderTopWidth, 10),
};
});
if (!parentBox) {
return null;
}
point.x += parentBox.left;
point.y += parentBox.top;
frame = frame?.parentFrame();
} finally {
void element.dispose().catch(debugError);
}
}
return point;
}
/**
@ -897,7 +972,99 @@ export class ElementHandle<
* Each Point is an object `{x, y}`. Box points are sorted clock-wise.
*/
async boxModel(): Promise<BoxModel | null> {
throw new Error('Not implemented');
const adoptedThis = await this.frame.isolatedRealm().adoptHandle(this);
const model = await adoptedThis.evaluate(element => {
if (!(element instanceof Element)) {
return null;
}
// Element is not visible.
if (element.getClientRects().length === 0) {
return null;
}
const rect = element.getBoundingClientRect();
const style = window.getComputedStyle(element);
const offsets = {
padding: {
left: parseInt(style.paddingLeft, 10),
top: parseInt(style.paddingTop, 10),
right: parseInt(style.paddingRight, 10),
bottom: parseInt(style.paddingBottom, 10),
},
margin: {
left: -parseInt(style.marginLeft, 10),
top: -parseInt(style.marginTop, 10),
right: -parseInt(style.marginRight, 10),
bottom: -parseInt(style.marginBottom, 10),
},
border: {
left: parseInt(style.borderLeft, 10),
top: parseInt(style.borderTop, 10),
right: parseInt(style.borderRight, 10),
bottom: parseInt(style.borderBottom, 10),
},
};
const border: Quad = [
{x: rect.left, y: rect.top},
{x: rect.left + rect.width, y: rect.top},
{x: rect.left + rect.width, y: rect.top + rect.bottom},
{x: rect.left, y: rect.top + rect.bottom},
];
const padding = transformQuadWithOffsets(border, offsets.border);
const content = transformQuadWithOffsets(padding, offsets.padding);
const margin = transformQuadWithOffsets(border, offsets.margin);
return {
content,
padding,
border,
margin,
width: rect.width,
height: rect.height,
};
function transformQuadWithOffsets(
quad: Quad,
offsets: {top: number; left: number; right: number; bottom: number}
): Quad {
return [
{
x: quad[0].x + offsets.left,
y: quad[0].y + offsets.top,
},
{
x: quad[1].x - offsets.right,
y: quad[1].y + offsets.top,
},
{
x: quad[2].x - offsets.right,
y: quad[2].y - offsets.bottom,
},
{
x: quad[3].x + offsets.left,
y: quad[3].y - offsets.bottom,
},
];
}
});
void adoptedThis.dispose().catch(debugError);
if (!model) {
return null;
}
const offset = await this.#getTopLeftCornerOfFrame();
if (!offset) {
return null;
}
for (const attribute of [
'content',
'padding',
'border',
'margin',
] as const) {
for (const point of model[attribute]) {
point.x += offset.x;
point.y += offset.y;
}
}
return model;
}
/**

View File

@ -22,6 +22,7 @@ import {DeviceRequestPrompt} from '../common/DeviceRequestPrompt.js';
import {EventEmitter} from '../common/EventEmitter.js';
import {ExecutionContext} from '../common/ExecutionContext.js';
import {getQueryHandlerAndSelector} from '../common/GetQueryHandler.js';
import {transposeIterableHandle} from '../common/HandleIterator.js';
import {
IsolatedWorldChart,
WaitForSelectorOptions,
@ -36,7 +37,7 @@ import {
InnerLazyParams,
NodeFor,
} from '../common/types.js';
import {importFSPromises} from '../common/util.js';
import {debugError, importFSPromises} from '../common/util.js';
import {TaskManager} from '../common/WaitTask.js';
import {KeyboardTypeOptions} from './Input.js';
@ -380,6 +381,27 @@ export class Frame extends EventEmitter {
throw new Error('Not implemented');
}
/**
* @internal
*/
async frameElement(): Promise<HandleFor<HTMLIFrameElement> | null> {
const parentFrame = this.parentFrame();
if (!parentFrame) {
return null;
}
const list = await parentFrame.isolatedRealm().evaluateHandle(() => {
return document.querySelectorAll('iframe');
});
for await (const iframe of transposeIterableHandle(list)) {
const frame = await iframe.contentFrame();
if (frame._id === this._id) {
return iframe;
}
void iframe.dispose().catch(debugError);
}
return null;
}
/**
* Behaves identically to {@link Page.evaluateHandle} except it's run within
* the context of this frame.

View File

@ -18,14 +18,13 @@ import {Protocol} from 'devtools-protocol';
import {
AutofillData,
BoundingBox,
BoxModel,
ClickOptions,
ElementHandle,
Offset,
Point,
Quad,
} from '../api/ElementHandle.js';
import {KeyPressOptions, KeyboardTypeOptions} from '../api/Input.js';
import {KeyboardTypeOptions, KeyPressOptions} from '../api/Input.js';
import {Page, ScreenshotOptions} from '../api/Page.js';
import {assert} from '../util/assert.js';
@ -45,9 +44,11 @@ const applyOffsetsToQuad = (
offsetX: number,
offsetY: number
) => {
assert(quad.length === 4);
return quad.map(part => {
return {x: part.x + offsetX, y: part.y + offsetY};
});
// SAFETY: We know this is a quad from the length check.
}) as Quad;
};
/**
@ -127,6 +128,9 @@ export class CDPElementHandle<
> | null;
}
override async contentFrame(
this: ElementHandle<HTMLIFrameElement>
): Promise<Frame>;
override async contentFrame(): Promise<Frame | null> {
const nodeInfo = await this.client.send('DOM.describeNode', {
objectId: this.id,
@ -251,15 +255,6 @@ export class CDPElementHandle<
};
}
#getBoxModel(): Promise<void | Protocol.DOM.GetBoxModelResponse> {
const params: Protocol.DOM.GetBoxModelRequest = {
objectId: this.id,
};
return this.client.send('DOM.getBoxModel', params).catch(error => {
return debugError(error);
});
}
#fromProtocolQuad(quad: number[]): Point[] {
return [
{x: quad[0]!, y: quad[1]!},
@ -462,59 +457,6 @@ export class CDPElementHandle<
await this.#page.keyboard.press(key, options);
}
override async boundingBox(): Promise<BoundingBox | null> {
const result = await this.#getBoxModel();
if (!result) {
return null;
}
const {offsetX, offsetY} = await this.#getOOPIFOffsets(this.#frame);
const quad = result.model.border;
const x = Math.min(quad[0]!, quad[2]!, quad[4]!, quad[6]!);
const y = Math.min(quad[1]!, quad[3]!, quad[5]!, quad[7]!);
const width = Math.max(quad[0]!, quad[2]!, quad[4]!, quad[6]!) - x;
const height = Math.max(quad[1]!, quad[3]!, quad[5]!, quad[7]!) - y;
return {x: x + offsetX, y: y + offsetY, width, height};
}
override async boxModel(): Promise<BoxModel | null> {
const result = await this.#getBoxModel();
if (!result) {
return null;
}
const {offsetX, offsetY} = await this.#getOOPIFOffsets(this.#frame);
const {content, padding, border, margin, width, height} = result.model;
return {
content: applyOffsetsToQuad(
this.#fromProtocolQuad(content),
offsetX,
offsetY
),
padding: applyOffsetsToQuad(
this.#fromProtocolQuad(padding),
offsetX,
offsetY
),
border: applyOffsetsToQuad(
this.#fromProtocolQuad(border),
offsetX,
offsetY
),
margin: applyOffsetsToQuad(
this.#fromProtocolQuad(margin),
offsetX,
offsetY
),
width,
height,
};
}
override async screenshot(
this: CDPElementHandle<Element>,
options: ScreenshotOptions = {}

View File

@ -19,15 +19,15 @@ import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import {
AutofillData,
ElementHandle as BaseElementHandle,
BoundingBox,
ClickOptions,
} from '../../api/ElementHandle.js';
import {KeyPressOptions, KeyboardTypeOptions} from '../../api/Input.js';
import {KeyboardTypeOptions, KeyPressOptions} from '../../api/Input.js';
import {assert} from '../../util/assert.js';
import {KeyInput} from '../USKeyboardLayout.js';
import {debugError} from '../util.js';
import {Frame} from './Frame.js';
import {JSHandle} from './JSHandle.js';
import {JSHandle as BidiJSHandle, JSHandle} from './JSHandle.js';
import {Realm} from './Realm.js';
/**
@ -86,26 +86,24 @@ export class ElementHandle<
});
}
override async boundingBox(): Promise<BoundingBox | null> {
if (this.frame.parentFrame()) {
throw new Error(
'Elements within nested iframes are currently not supported.'
);
}
const box = await this.frame.isolatedRealm().evaluate(element => {
const rect = (element as unknown as Element).getBoundingClientRect();
if (!rect.left && !rect.top && !rect.width && !rect.height) {
// TODO(jrandolf): Detect if the element is truly not visible.
return null;
override async contentFrame(
this: ElementHandle<HTMLIFrameElement>
): Promise<Frame>;
override async contentFrame(): Promise<Frame | null> {
const adoptedThis = await this.frame.isolatedRealm().adoptHandle(this);
const handle = (await adoptedThis.evaluateHandle(element => {
if (element instanceof HTMLIFrameElement) {
return element.contentWindow;
}
return {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height,
};
}, this);
return box;
return;
})) as BidiJSHandle;
void handle.dispose().catch(debugError);
void adoptedThis.dispose().catch(debugError);
const value = handle.remoteValue();
if (value.type === 'window') {
return this.frame.page().frame(value.value.context);
}
return null;
}
// ///////////////////

View File

@ -36,8 +36,8 @@ import {Page} from './Page.js';
import {
MAIN_SANDBOX,
PUPPETEER_SANDBOX,
SandboxChart,
Sandbox,
SandboxChart,
} from './Sandbox.js';
/**

View File

@ -219,7 +219,7 @@
"testIdPattern": "[page.spec] Page Page.Events.PageError *",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS", "TIMEOUT"]
"expectations": ["PASS"]
},
{
"testIdPattern": "[page.spec] Page Page.pdf *",
@ -605,6 +605,12 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should handle nested frames",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should return null for invisible elements",
"platforms": ["darwin", "linux", "win32"],
@ -623,6 +629,18 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boxModel should return null for invisible elements",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boxModel should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should not work for TextNodes",
"platforms": ["darwin", "linux", "win32"],
@ -647,6 +665,12 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.contentFrame should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.hover should work",
"platforms": ["darwin", "linux", "win32"],
@ -666,10 +690,16 @@
"expectations": ["PASS"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should have different execution contexts",
"testIdPattern": "[emulation.spec] Emulation Page.viewport should get the proper viewport size",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
"expectations": ["PASS"]
},
{
"testIdPattern": "[emulation.spec] Emulation Page.viewport should support mobile emulation",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should throw a nice error after a navigation",
@ -731,12 +761,36 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should report frame from-inside shadow DOM",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should report frame.parent()",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should support lazy frames",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should support url fragment",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame.client should return the client instance",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame.evaluate allows readonly array to be an argument",
"platforms": ["darwin", "linux", "win32"],
@ -881,6 +935,12 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[keyboard.spec] Keyboard should type emoji into an iframe",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[keyboard.spec] Keyboard should type into a textarea",
"platforms": ["darwin", "linux", "win32"],
@ -1001,6 +1061,24 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[mouse.spec] Mouse should select the text with mouse",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[mouse.spec] Mouse should send mouse wheel events",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[mouse.spec] Mouse should set modifier keys on click",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[mouse.spec] Mouse should trigger hover state",
"platforms": ["darwin", "linux", "win32"],
@ -1013,6 +1091,12 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[mouse.spec] Mouse should work with mobile viewports and cross process navigations",
"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"],
@ -1085,24 +1169,12 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network Page.Events.Request should fire for iframes",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network raw network headers Cross-origin set-cookie",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[network.spec] network Request.frame should work for subframe navigation request",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network Request.headers should define Chrome as user agent header",
"platforms": ["darwin", "linux", "win32"],
@ -1181,6 +1253,12 @@
"parameters": ["firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[page.spec] Page Page.client should return the client instance",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[page.spec] Page Page.close should *not* run beforeunload by default",
"platforms": ["darwin", "linux", "win32"],
@ -1361,6 +1439,24 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[proxy.spec] request proxy in incognito browser context should respect proxy bypass list when configured at browser level",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[proxy.spec] request proxy in incognito browser context should respect proxy bypass list when configured at context level",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[proxy.spec] request proxy should respect proxy bypass list",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors",
"platforms": ["darwin", "linux", "win32"],
@ -1427,18 +1523,42 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target Browser.targets should return all of the targets",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target Browser.waitForTarget should timeout waiting for a non-existent target",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[target.spec] Target should be able to use async waitForTarget",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target should be able to use the default page in the browser",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target should contain browser target",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target should not crash while redirecting if original request was missed",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[TargetManager.spec] *",
"platforms": ["darwin", "linux", "win32"],
@ -1601,18 +1721,6 @@
"parameters": ["webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should run in specified frame",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should throw when frame is detached",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Page.waitForTimeout waits for the given timeout before resolving",
"platforms": ["darwin", "linux", "win32"],
@ -1625,6 +1733,12 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[accessibility.spec] Accessibility filtering children of leaf nodes rich text editable fields should have children",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[accessibility.spec] Accessibility get snapshots while the tree is re-calculated",
"platforms": ["darwin", "linux", "win32"],
@ -1781,6 +1895,12 @@
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[click.spec] Page.click should click the button after navigation",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[click.spec] Page.click should click the button if window.Node is removed",
"platforms": ["darwin", "linux", "win32"],
@ -1943,6 +2063,12 @@
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should handle nested frames",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should handle nested frames",
"platforms": ["darwin", "linux", "win32"],
@ -1950,9 +2076,9 @@
"expectations": ["FAIL"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should return null for invisible elements",
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
@ -1962,17 +2088,11 @@
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boundingBox should work",
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boxModel should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.boxModel should return null for invisible elements",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.click should return Point data",
"platforms": ["darwin", "linux", "win32"],
@ -1991,6 +2111,12 @@
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.contentFrame should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[emulation.spec] Emulation Page.emulate should support clicking",
"platforms": ["darwin", "linux", "win32"],
@ -2105,6 +2231,18 @@
"parameters": ["cdp", "firefox"],
"expectations": ["PASS", "TIMEOUT"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should have different execution contexts",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should have different execution contexts",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[evaluation.spec] Evaluation specs Page.evaluate should await promise",
"platforms": ["darwin", "linux", "win32"],
@ -2195,6 +2333,12 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should report frame.parent()",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[frame.spec] Frame specs Frame Management should report frame.parent()",
"platforms": ["darwin", "linux", "win32"],
@ -2291,6 +2435,12 @@
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[ignorehttpserrors.spec] ignoreHTTPSErrors should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[ignorehttpserrors.spec] ignoreHTTPSErrors should work with mixed content",
"platforms": ["darwin", "linux", "win32"],
@ -2417,6 +2567,12 @@
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[keyboard.spec] Keyboard should type emoji into an iframe",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[keyboard.spec] Keyboard should type emoji into an iframe",
"platforms": ["darwin", "linux", "win32"],
@ -3029,6 +3185,18 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[network.spec] network Page.Events.Request should fire for iframes",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network Page.Events.Request should fire for iframes",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network Page.setExtraHTTPHeaders should work",
"platforms": ["darwin", "linux", "win32"],
@ -3071,6 +3239,18 @@
"parameters": ["cdp", "chrome"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[network.spec] network Request.frame should work for subframe navigation request",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[network.spec] network Request.frame should work for subframe navigation request",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[network.spec] network Request.headers should define Firefox as user agent header",
"platforms": ["darwin", "linux", "win32"],
@ -3701,12 +3881,6 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[screenshot.spec] Screenshots ElementHandle.screenshot should fail to screenshot a detached element",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[screenshot.spec] Screenshots ElementHandle.screenshot should work for an element with an offset",
"platforms": ["darwin", "linux", "win32"],
@ -3851,6 +4025,12 @@
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target should not report uninitialized pages",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[target.spec] Target should report when a new page is created and closed",
"platforms": ["darwin", "linux", "win32"],
@ -3953,12 +4133,36 @@
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should run in specified frame",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should run in specified frame",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should run in specified frame",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should throw when frame is detached",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS", "TIMEOUT"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should throw when frame is detached",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForXPath should throw when frame is detached",
"platforms": ["darwin", "linux", "win32"],
@ -3971,12 +4175,6 @@
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[accessibility.spec] Accessibility filtering children of leaf nodes rich text editable fields should have children",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[CDPSession.spec] Target.createCDPSession should send events",
"platforms": ["win32"],

View File

@ -145,7 +145,7 @@ describe('ElementHandle specs', function () {
y: 2 + 5,
});
expect(box.content[0]).toEqual({
x: 1 + 4 + 3 + 1 + 2, // frame.left + div.left + div.marginLeft + div.borderLeft + dif.paddingLeft
x: 1 + 4 + 3 + 1 + 2, // frame.left + div.left + div.marginLeft + div.borderLeft + div.paddingLeft
y: 2 + 5,
});
});