While debugging @mynar7's issue on slack, I noticed that the page.waitForNavigation was not a reliable way to ensure that the #catalog-title is visible. Replacing it with a page.waitForSelector fixed it.
However, since we are moving towards auto-waits in API calls that refer to element selectors, I was wondering if the page.$eval method could auto-wait for the element, thereby eliminating the need to waitForSelector.
const { firefox, chromium, webkit } = require('playwright');
const assert = require('assert');
(async() => {
const browser = await firefox.launch();
const page = await browser.newPage();
await page.goto('https://realtruck.com/?disableIntegration=all');
await Promise.all([
page.click('text=Tonneau Covers'),
page.waitForSelector('#catalog-title') // was earlier using page.waitForNavigation()
]);
const header = await page.$eval('#catalog-title', el => el.textContent);
assert(header, "Tonneau Covers");
await browser.close();
})();
since we are moving towards auto-waits in API calls that refer to element selectors
We keep thinking in this direction, but there are a few concerns particularly regarding page.$eval:
waitForSelector has some interesting options and might get more in future; and there's no good shape for page.$eval to accept these options. waitFor.. - it self-explains the API for non-experienced users.So we'll keep thinking about this! For now, I think I can re-write your snippet in a slightly nicer way:
await page.goto('https://realtruck.com/?disableIntegration=all');
await page.click('text=Tonneau Covers');
const catalog = await page.waitForSelector('#catalog-title');
const header = await catalog.evaluate(el => el.textContent);
assert(header, "Tonneau Covers");
Should this work const handle = await page.$('"foo"'); shown here? Should that one not wait for the selector to appear? Because I just tested this and it does not. It would maybe then mean page.$wait() is unecessary, but I am sure I am missing something?
Should that one not wait for the selector to appear?
@thernstig yes, it does not wait for selector to appear. The semantic is the same as the $ in devtools console, or in jquery - they just fetch element from the page.
If you want to wait for a selector, you should use page.waitfor("foo")
@aslushnikov page.$wait and page.waitForSelector returns an ElementHandle whereas page.waitfor returns a JSHandle, is that intentional?
@thernstig page.waitFor will return an ElementHandle once called with a string as an argument. (cc @JoelEinbinder - can we actually signify this in our .d.ts types?)
@thernstig
page.waitForwill return an ElementHandle once called with a string as an argument. (cc @JoelEinbinder - can we actually signify this in our .d.ts types?)
Yes, I'll add it to #6.
Closing this for now. We will use the guide to outline the difference in how "actions" like click, fill, etc work, versus the $ and $eval.
Most helpful comment
@thernstig yes, it does not wait for selector to appear. The semantic is the same as the
$in devtools console, or in jquery - they just fetch element from the page.If you want to wait for a selector, you should use
page.waitfor("foo")