From 78ab2955f3693d41ac95333c5c42e97f86e20559 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 10 Feb 2021 07:12:43 -0800 Subject: [PATCH] fix(isVisible): do not wait for the selector to be resolved (#5393) --- docs/src/api/class-frame.md | 6 +++--- docs/src/api/class-page.md | 4 ++-- src/server/frames.ts | 5 ++--- test/elementhandle-convenience.spec.ts | 5 +++++ types/types.d.ts | 12 ++++++++---- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/src/api/class-frame.md b/docs/src/api/class-frame.md index afdecdc2e7..f11c7b7de0 100644 --- a/docs/src/api/class-frame.md +++ b/docs/src/api/class-frame.md @@ -385,7 +385,7 @@ If the function passed to the [`method: Frame.evaluate`] returns a [Promise], th resolve and return its value. If the function passed to the [`method: Frame.evaluate`] returns a non-[Serializable] value, then -[`method: Frame.evaluate`] returns `undefined`. Playwright also supports transferring some +[`method: Frame.evaluate`] returns `undefined`. Playwright also supports transferring some additional values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`. ```js @@ -723,7 +723,7 @@ Returns whether the element is [enabled](./actionability.md#enabled). ## async method: Frame.isHidden - returns: <[boolean]> -Returns whether the element is hidden, the opposite of [visible](./actionability.md#visible). +Returns whether the element is hidden, the opposite of [visible](./actionability.md#visible). [`option: selector`] that does not match any elements is considered hidden. ### param: Frame.isHidden.selector = %%-input-selector-%% @@ -732,7 +732,7 @@ Returns whether the element is hidden, the opposite of [visible](./actionability ## async method: Frame.isVisible - returns: <[boolean]> -Returns whether the element is [visible](./actionability.md#visible). +Returns whether the element is [visible](./actionability.md#visible). [`option: selector`] that does not match any elements is considered not visible. ### param: Frame.isVisible.selector = %%-input-selector-%% diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index bb7dc30732..8e638e4859 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -1448,7 +1448,7 @@ Returns whether the element is [enabled](./actionability.md#enabled). ## async method: Page.isHidden - returns: <[boolean]> -Returns whether the element is hidden, the opposite of [visible](./actionability.md#visible). +Returns whether the element is hidden, the opposite of [visible](./actionability.md#visible). [`option: selector`] that does not match any elements is considered hidden. ### param: Page.isHidden.selector = %%-input-selector-%% @@ -1457,7 +1457,7 @@ Returns whether the element is hidden, the opposite of [visible](./actionability ## async method: Page.isVisible - returns: <[boolean]> -Returns whether the element is [visible](./actionability.md#visible). +Returns whether the element is [visible](./actionability.md#visible). [`option: selector`] that does not match any elements is considered not visible. ### param: Page.isVisible.selector = %%-input-selector-%% diff --git a/src/server/frames.ts b/src/server/frames.ts index f0f14d08ec..d64d9fdef4 100644 --- a/src/server/frames.ts +++ b/src/server/frames.ts @@ -946,11 +946,10 @@ export class Frame extends SdkObject { async isVisible(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise { const controller = new ProgressController(metadata, this); - const info = this._page.selectors._parseSelector(selector); - const task = dom.visibleTask(info); return controller.run(async progress => { progress.log(` checking visibility of "${selector}"`); - return this._scheduleRerunnableTask(progress, info.world, task); + const element = await this.$(selector); + return element ? await element.isVisible() : false; }, this._page._timeoutSettings.timeout(options)); } diff --git a/test/elementhandle-convenience.spec.ts b/test/elementhandle-convenience.spec.ts index 39d2954d0f..3f7cea8135 100644 --- a/test/elementhandle-convenience.spec.ts +++ b/test/elementhandle-convenience.spec.ts @@ -159,16 +159,21 @@ it('getAttribute should be atomic', async ({ playwright, page }) => { it('isVisible and isHidden should work', async ({ page }) => { await page.setContent(`
Hi
`); + const div = await page.$('div'); expect(await div.isVisible()).toBe(true); expect(await div.isHidden()).toBe(false); expect(await page.isVisible('div')).toBe(true); expect(await page.isHidden('div')).toBe(false); + const span = await page.$('span'); expect(await span.isVisible()).toBe(false); expect(await span.isHidden()).toBe(true); expect(await page.isVisible('span')).toBe(false); expect(await page.isHidden('span')).toBe(true); + + expect(await page.isVisible('no-such-element')).toBe(false); + expect(await page.isHidden('no-such-element')).toBe(true); }); it('isEnabled and isDisabled should work', async ({ page }) => { diff --git a/types/types.d.ts b/types/types.d.ts index bf05d662dd..c0b4096023 100644 --- a/types/types.d.ts +++ b/types/types.d.ts @@ -2037,7 +2037,8 @@ export interface Page { }): Promise; /** - * Returns whether the element is hidden, the opposite of [visible](https://playwright.dev/docs/actionability#visible). + * Returns whether the element is hidden, the opposite of [visible](https://playwright.dev/docs/actionability#visible). `selector` that does not + * match any elements is considered hidden. * @param selector A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param options */ @@ -2052,7 +2053,8 @@ export interface Page { }): Promise; /** - * Returns whether the element is [visible](https://playwright.dev/docs/actionability#visible). + * Returns whether the element is [visible](https://playwright.dev/docs/actionability#visible). `selector` that does not match any elements is + * considered not visible. * @param selector A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param options */ @@ -3992,7 +3994,8 @@ export interface Frame { }): Promise; /** - * Returns whether the element is hidden, the opposite of [visible](https://playwright.dev/docs/actionability#visible). + * Returns whether the element is hidden, the opposite of [visible](https://playwright.dev/docs/actionability#visible). `selector` that does not + * match any elements is considered hidden. * @param selector A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param options */ @@ -4007,7 +4010,8 @@ export interface Frame { }): Promise; /** - * Returns whether the element is [visible](https://playwright.dev/docs/actionability#visible). + * Returns whether the element is [visible](https://playwright.dev/docs/actionability#visible). `selector` that does not match any elements is + * considered not visible. * @param selector A selector to search for element. If there are multiple elements satisfying the selector, the first will be used. See [working with selectors](https://playwright.dev/docs/selectors) for more details. * @param options */