CamdyCorn
CamdyCorn

Reputation: 151

Using Playwright, page.url() is getting a previous url instead of the current url

I'm testing the navigation on our website using expect(page.url()).toContain('/nav');. When walking through the code I can clearly see that we hit that url string after the click.

I've tried putting my code into and outside of a promise granting the same error:

Expected substring: "/nav"
Received string:    "https://website.com/about"

      283 |     page.waitForNavigation();
      284 |     await page.hover('nav >> text=Nav');
      285 |     await page.click('nav >> text=Nav');
      286 |     console.log(page.url());
    > 287 |     expect(page.url()).toContain('/nav');
          |                        ^
      288 |
      289 |     page.click('text=Next Nav')
      290 |     expect(page.url()).toContain('/nextNav');

The link itself is a simple <a href="/nav" class="list__item__link" data-v-0df6efc8>Nav</a>.

The console log shows https://website.com/about.

Here's a snippet related to the comments:

////##OURSTORY##////
    page.hover('nav >> text=Our Story');
    page.waitForNavigation();
    await page.click('nav >> text=About');
    expect(page.url()).toContain('story');

    //await page.pause();

    await page.hover('nav >> text=Our Story');
    await page.hover('nav >> text=360° Wellness');
    await page.click('nav >> text=360° Wellness'); 
    console.log(page.url());
    await page.waitForNavigation();
    expect(page.url()).toContain('/360-wellness');

Upvotes: 12

Views: 20841

Answers (5)

Elvina Gareeva
Elvina Gareeva

Reputation: 1

I do it like this:

       old_url = page.url
       page.wait_for_url(lambda url: old_url != url, timeout=1.5*1000)
       print(f'Go to URL : {page.url}')

Most of the time it works But sometimes it doesn't So I try to find some element before get current URL

page.wait_for_selector(selector='//body')
print(f'Go to URL : {page.url}')

Upvotes: 0

Vishal Aggarwal
Vishal Aggarwal

Reputation: 4178

You may cover it in Promise.all to avoid race condition as Promise.all waits till all promises are resolved declared inside it.

const [response] = await Promise.all([
          page.waitForNavigation(),
          page.click('nav >> text=360° Wellness')
     ]);


await expect(page.url()).toContain('/360-wellness');

Source: https://playwright.dev/docs/navigations

Upvotes: 3

Ny0ttt
Ny0ttt

Reputation: 37

I am working on a project that requires the same output as this question. Just would like to add up what works for me is to make an interaction before getting the page.url()

for me, I did an interaction like clicking a search bar

  await page.locator('input[placeholder=\'Choose starting point, or click on the map...\']').click();

then call

page.url();

I couldn't explain further as I am still new in this, just would like to share what works for me. Hope this helps for anyone working on these days.

Upvotes: 1

mseyfayi
mseyfayi

Reputation: 144

Playwright API for this is waitForURL, like this:

await page.goto('/');
await page.waitForURL('**/auth/login');

Upvotes: 2

Hari Reddy
Hari Reddy

Reputation: 369

Okay, so I was a little wary of using page.waitForNavigation() from the start, so I gave it a second thought about needing to use it here. Turns out, we don't really need it. Considering load time variations, I added a waitForSelector() which should allow it 30 seconds (or you could do setTimeout to set a custom wait time).

Also, here's a little something about the waitForNavigation() method -

page.waitForNavigation() returns a promise that resolves only after the navigation has finished. The documentation mentions -

In case of navigation to a different anchor or navigation due to History API usage, the navigation will resolve with null.

Since the site development approach can be ambiguous, its perhaps better to steer clear of using the said function. Especially since it also states -

It is useful for when you run code which will indirectly cause the page to navigate

... which in all honesty, I don't clearly understand the use case for.

Anyway, here is what worked; the full test.spec.ts file -

import { Page } from "playwright-core";

describe("Test Suite for a patient random guy on Stack Overflow", () => {
  it("Test Gen: [URL Text] Testing the correct URL path", async () => {
    let page: Page;
    page = await context.newPage();
    await page.goto("https://ariix.newage.com");
    page.hover("nav >> text=Our Story");
    await page.waitForSelector("nav >> text=About");
    await page.click("nav >> text=About");
    console.log(page.url());
    expect(page.url()).toContain("story");
    //await page.pause();
    await page.hover("nav >> text=Our Story");
    await page.waitForSelector("nav >> text=360° Wellness");
    await page.click("nav >> text=360° Wellness");
    console.log(page.url());
    expect(page.url()).toContain("/360-wellness");
  });
});

And it seems to do/print what you were aiming to -

enter image description here

Hopefully this solves this issue at your end. Let us know :)

Upvotes: 1

Related Questions