fix(isVisible): make sure isVisible check is atomic (#16004)

This commit is contained in:
Dmitry Gozman 2022-07-28 14:09:36 -07:00 committed by GitHub
parent a089bf3df5
commit 829a1b8444
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 2 deletions

View file

@ -1256,8 +1256,13 @@ export class Frame extends SdkObject {
const pair = await this.resolveFrameForSelectorNoWait(selector, options);
if (!pair)
return false;
const element = await this._page.selectors.query(pair.frame, pair.info);
return element ? await element.isVisible() : false;
const context = await pair.frame._context(pair.info.world);
const injectedScript = await context.injectedScript();
return await injectedScript.evaluate((injected, { parsed, strict }) => {
const element = injected.querySelector(parsed, document, strict);
const state = element ? injected.elementState(element, 'visible') : false;
return state === 'error:notconnected' ? false : state;
}, { parsed: pair.info.parsed, strict: pair.info.strict });
}, this._page._timeoutSettings.timeout({}));
}

View file

@ -308,3 +308,25 @@ it('isChecked should work', async ({ page }) => {
const error = await page.isChecked('div').catch(e => e);
expect(error.message).toContain('Not a checkbox or radio button');
});
it('isVisible should be atomic', async ({ playwright, page }) => {
const createDummySelector = () => ({
query(root, selector) {
const result = root.querySelector(selector);
if (result)
Promise.resolve().then(() => result.style.display = 'none');
return result;
},
queryAll(root: HTMLElement, selector: string) {
const result = Array.from(root.querySelectorAll(selector));
for (const e of result)
Promise.resolve().then(() => (e as HTMLElement).style.display = 'none');
return result;
}
});
await playwright.selectors.register('isVisible', createDummySelector);
await page.setContent(`<div>Hello</div>`);
const result = await page.isVisible('isVisible=div');
expect(result).toBe(true);
expect(await page.evaluate(() => document.querySelector('div').style.display)).toBe('none');
});