From 87ca58f97a38738483e2c588e3f05dd7edc1e193 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Mon, 22 May 2023 11:57:51 +0200 Subject: [PATCH] chore: implement locators for scroll and hover (#10219) --- packages/puppeteer-core/src/api/Locator.ts | 49 +++++++++++++++++++- test/src/locator.spec.ts | 53 ++++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/packages/puppeteer-core/src/api/Locator.ts b/packages/puppeteer-core/src/api/Locator.ts index 695de681e65..2ac870f0c1f 100644 --- a/packages/puppeteer-core/src/api/Locator.ts +++ b/packages/puppeteer-core/src/api/Locator.ts @@ -342,7 +342,7 @@ export class Locator extends EventEmitter { signal?: AbortSignal; } ): Promise { - await this.#run( + return await this.#run( async element => { await element.click(clickOptions); }, @@ -357,4 +357,51 @@ export class Locator extends EventEmitter { } ); } + + async hover(hoverOptions?: {signal?: AbortSignal}): Promise { + return await this.#run( + async element => { + await element.hover(); + }, + { + signal: hoverOptions?.signal, + conditions: [ + this.#ensureElementIsInTheViewport, + this.#waitForVisibility, + this.#waitForStableBoundingBox, + ], + } + ); + } + + async scroll(scrollOptions?: { + scrollTop?: number; + scrollLeft?: number; + signal?: AbortSignal; + }): Promise { + return await this.#run( + async element => { + await element.evaluate( + (el, scrollTop, scrollLeft) => { + if (scrollTop !== undefined) { + el.scrollTop = scrollTop; + } + if (scrollLeft !== undefined) { + el.scrollLeft = scrollLeft; + } + }, + scrollOptions?.scrollTop, + scrollOptions?.scrollLeft + ); + }, + { + signal: scrollOptions?.signal, + conditions: [ + this.#ensureElementIsInTheViewport, + this.#waitForVisibility, + this.#waitForStableBoundingBox, + ], + } + ); + } } diff --git a/test/src/locator.spec.ts b/test/src/locator.spec.ts index 159b23ed85b..8cdc94a34bb 100644 --- a/test/src/locator.spec.ts +++ b/test/src/locator.spec.ts @@ -226,4 +226,57 @@ describe('Locator', function () { } }); }); + + describe('Locator.hover', function () { + it('should work', async () => { + const {page} = getTestState(); + + await page.setViewport({width: 500, height: 500}); + await page.setContent(` + + `); + let hovered = false; + await page + .locator('button') + .on(LocatorEmittedEvents.Action, () => { + hovered = true; + }) + .hover(); + const button = await page.$('button'); + const text = await button?.evaluate(el => { + return el.innerText; + }); + expect(text).toBe('hovered'); + expect(hovered).toBe(true); + }); + }); + + describe('Locator.scroll', function () { + it('should work', async () => { + const {page} = getTestState(); + + await page.setViewport({width: 500, height: 500}); + await page.setContent(` +
+
test
+
+ `); + let scrolled = false; + await page + .locator('div') + .on(LocatorEmittedEvents.Action, () => { + scrolled = true; + }) + .scroll({ + scrollTop: 500, + scrollLeft: 500, + }); + const scrollable = await page.$('div'); + const scroll = await scrollable?.evaluate(el => { + return el.scrollTop + ' ' + el.scrollLeft; + }); + expect(scroll).toBe('500 500'); + expect(scrolled).toBe(true); + }); + }); });