添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
乖乖的数据线  ·  [email protected] | ...·  2 月前    · 
慷慨的汽水  ·  Forum GeoRezo / ...·  5 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

When automating a login for, I perform click on an element that it could lead to navigation to another page but in case of invalid password it will just display error message on the same page without actually causing a navigation.

I have tried:

await Promise.all([
      this.page.submitButton.click(),
      this.page.waitForNavigation()

But it will fail for the case when no navigation happens. I was thinking about interception the response, to check if the login succeed/failed, but may be there is a more clear way to do so ?

This code should give you an example of how to understand if you stay on the same page or navigate:

await this.page.submitButton.click();
try {
    await this.page.waitForNavigation();
    // if we are here it means login was successful
} catch(e) {
    // if we are here it means login failed
                @Zaky exactly. But you can check some exact thing instead of waitForNavigation. For example, you might check an error message in case of the wrong password. But it also implies waiting I guess.
– Vadim
                Jan 25, 2022 at 10:18
                i wanted to avoid waiting for the waitForNavigation, but what is worked for me was the opposite approach. I just waited for the selector with short time-out and if it failed (meaning the page started navigation, i called to await page.waitForNavigation().
– Zaky
                Jan 25, 2022 at 22:24
                i afraid that it can introduce an race condition, since in case the navigation actually should take place i will need to call again for the waitForNavigation on some hardcoded timeout
– Zaky
                Jan 27, 2022 at 10:39

I don't think you need some extra code besides this.page.submitButton.click().
The click function will wait for the navigation for you. So you could check after the click if your are in the same URL or not.

await this.page.submitButton.click(); // This will wait for a possible navigation
if(this.page.url() == destinationOnValidLogin) {
 // Good login stuff
} else {
 // Login failed
                If I understand correctly, the click() will return as soon as navigation started, before the page is completely loaded. On the other hand, in my scenario click() could lead only to new request to update the page without actually causing the navigation. Ideally, I want to distinguish these flows: if click() caused only update or actual navigation.
– Zaky
                Jan 25, 2022 at 13:11
                According to the doc click will Wait for initiated navigations to either succeed or fail, unless noWaitAfter option is set.
– hardkoded
                Jan 25, 2022 at 13:15
                Do you mean that i can click with option noWaitAfter set, (assuming the click with return when page is updated or started navigation) and then to check for page.$('some-marker) - exists otherwise call to page.waitForNavigation() ?
– Zaky
                Jan 25, 2022 at 13:20
                You don't need to set noWaitAfter, that's the default behavior. I added a code a example. Let me know if it helps.
– hardkoded
                Jan 25, 2022 at 13:59
                well, it doesn't. If I check the page url just after calling await this.page.click(), I'm getting the same url (in both cases). moreover, i tried to intercept responses from the back-end to check the login success / failed - i couldn't get it since the request was originated form the service worker, and surprisingly playwright doesn't intercept it.
– Zaky
                Jan 25, 2022 at 22:20

Looks like you have two competing promises to await for here - one for the error message to appear, and another one for navigation to happen. Only one will initially resolve, hence we can use Promise.any to avoid excessive waiting or code branching.

await submitButton.click({
  noWaitAfter: true, // since we are handling potential navigation ourselves
// adding custom then callbacks to distinguish between the two
const navigationPromise = page.waitForURL('**').then(() => true);
const errorMessagePromise = messageLocator.isVisible().then(() => false);
const isLoggedIn = await Promise.any([
  navigationPromise,
  errorMessagePromise,
// at this stage we have either new page loaded OR login form with error message displayed

See waitUntil option of waitForURL method for more precise control of page navigation event you are interested in.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.