Skip to content

Commit

Permalink
feat: add threshold to Page.isIntersectingViewport (#6497)
Browse files Browse the repository at this point in the history
  • Loading branch information
ron0115 committed Sep 15, 2021
1 parent 9399c97 commit 54c4318
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 15 deletions.
7 changes: 4 additions & 3 deletions docs/api.md
Expand Up @@ -322,7 +322,7 @@
* [elementHandle.getProperties()](#elementhandlegetproperties)
* [elementHandle.getProperty(propertyName)](#elementhandlegetpropertypropertyname)
* [elementHandle.hover()](#elementhandlehover)
* [elementHandle.isIntersectingViewport()](#elementhandleisintersectingviewport)
* [elementHandle.isIntersectingViewport([options])](#elementhandleisintersectingviewportoptions)
* [elementHandle.jsonValue()](#elementhandlejsonvalue)
* [elementHandle.press(key[, options])](#elementhandlepresskey-options)
* [elementHandle.screenshot([options])](#elementhandlescreenshotoptions)
Expand Down Expand Up @@ -4574,8 +4574,9 @@ Fetches a single property from the objectHandle.
This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to hover over the center of the element.
If the element is detached from DOM, the method throws an error.

#### elementHandle.isIntersectingViewport()

#### elementHandle.isIntersectingViewport([options])
- `options` <[Object]>
- `threshold` <[number]> threshold for the intersection between 0 (no intersection) and 1 (full intersection). Defaults to 1.
- returns: <[Promise]<[boolean]>> Resolves to true if the element is visible in the current viewport.

#### elementHandle.jsonValue()
Expand Down
25 changes: 13 additions & 12 deletions src/common/JSHandle.ts
Expand Up @@ -994,19 +994,20 @@ export class ElementHandle<
/**
* Resolves to true if the element is visible in the current viewport.
*/
async isIntersectingViewport(): Promise<boolean> {
return await this.evaluate<(element: Element) => Promise<boolean>>(
async (element) => {
const visibleRatio = await new Promise((resolve) => {
const observer = new IntersectionObserver((entries) => {
resolve(entries[0].intersectionRatio);
observer.disconnect();
});
observer.observe(element);
async isIntersectingViewport(options?: {
threshold?: number;
}): Promise<boolean> {
const { threshold = 0 } = options || {};
return await this.evaluate(async (element: Element, threshold: number) => {
const visibleRatio = await new Promise<number>((resolve) => {
const observer = new IntersectionObserver((entries) => {
resolve(entries[0].intersectionRatio);
observer.disconnect();
});
return visibleRatio > 0;
}
);
observer.observe(element);
});
return threshold === 1 ? visibleRatio === 1 : visibleRatio > threshold;
}, threshold);
}
}

Expand Down
2 changes: 2 additions & 0 deletions test/assets/offscreenbuttons.html
Expand Up @@ -17,6 +17,7 @@
#btn8 { right: -80px; top: 200px; }
#btn9 { right: -90px; top: 225px; }
#btn10 { right: -100px; top: 250px; }
#btn11 { right: -99.999px; top: 275px; }
</style>
<button id=btn0>0</button>
<button id=btn1>1</button>
Expand All @@ -29,6 +30,7 @@
<button id=btn8>8</button>
<button id=btn9>9</button>
<button id=btn10>10</button>
<button id=btn11>11</button>
<script>
for (const button of document.querySelectorAll('button')) {
button.addEventListener('click', () => {
Expand Down
26 changes: 26 additions & 0 deletions test/elementhandle.spec.ts
Expand Up @@ -282,6 +282,32 @@ describe('ElementHandle specs', function () {
expect(await button.isIntersectingViewport()).toBe(visible);
}
});
it('should work with threshold', async () => {
const { page, server } = getTestState();

await page.goto(server.PREFIX + '/offscreenbuttons.html');
// a button almost cannot be seen
// sometimes we expect to return false by isIntersectingViewport1
const button = await page.$('#btn11');
expect(
await button.isIntersectingViewport({
threshold: 0.001,
})
).toBe(false);
});
it('should work with threshold of 1', async () => {
const { page, server } = getTestState();

await page.goto(server.PREFIX + '/offscreenbuttons.html');
// a button almost cannot be seen
// sometimes we expect to return false by isIntersectingViewport1
const button = await page.$('#btn0');
expect(
await button.isIntersectingViewport({
threshold: 1,
})
).toBe(true);
});
});

describe('Custom queries', function () {
Expand Down

0 comments on commit 54c4318

Please sign in to comment.