Reading the documentation, I found that using the function click()
of page
element is discouraged, as we can see here.
Instead, we can use the locator.click()
method, as shown here.
I am interested in understanding if there's some technical difference between the two methods, and if so what's exactly this difference.
I am recently updating a bunch of old functions created a year ago or so, and for some reasons when I change for example
await this.page.click('.add-card')
with
await this.page.locator('.add-card').click()
the behaviour changes, and some elements are not waited anymore; so the test fails.
I am pretty sure I need to change the rest of the code before trying to run everything again, since I think the issue is due not to this change but to the various old functions present.
But nonetheless I am interested to better understand if there's something that changes in the click
function, or if nothing really changes.
page.click()
does auto-wait, so that's not a factor. I can offer a number of reasons to prefer locators:
page.click()
doesn't enforce strictness by default, so if there are two elements on the page, it'll click the first without error, whereas locator.click()
will raise an error if there's any ambiguity. This avoids regressions and helps guarantee the element you locate remains stable.page.action()
operations don't exist, leading to consistent test suites that are mostly comprised of getByRole
and a few other key methods. Playwright has a fairly extensive and complex API, so anything you can do to set a portion of its methods off-limits is a good thing.page.click()
, you have to re-write the selector string (or use a string constant) on every call, harming reusability. With locators, you can declare the locator once in the POM constructor, then take a variety of different actions on it over time.page.locator(selector).action(options)
over and over in different forms, unbroken by the page.action(selector, options)
idiom. Some Playwright users are confused by where the options go and may not be using TypeScript, so consistently sticking to the second pattern can improve clarity.page.locator()
. Other locators are page.getByRole()
, page.getByLabel()
, page.getByText()
and similar methods that enforce user-visible best practice selections. If you're using page.click()
, you're likely using CSS or XPath, which are discouraged. The API tries to steer you to use page.getByRole()
, even over plain page.locator()
, as well as page.click()
, page.$()
, etc.page.action()
methods. The lack of chaining can result in an over-reliance on CSS and XPath to disambiguate selections.page.click()
is saving a few keystrokes.You wrote
I am recently updating a bunch of old functions created a year ago or so, and for some reasons when I change for example
await this.page.click('.add-card')
withawait this.page.locator('.add-card').click()
the behaviour changes, and some elements are not waited anymore; so the test fails.
This doesn't make sense. locator.click()
definitely auto-waits, so the only failure I can imagine is due to strictness (matching more than one element). You'd need to share a minimal, reproducible example and full stack trace or assertion failure to get help with this. A common mistake is failing to await
a locator action, so check that first.