playwright icon indicating copy to clipboard operation
playwright copied to clipboard

[BUG] page.getByPlaceholder().fill() is flaky in headless mode

Open TadasV1 opened this issue 1 year ago • 3 comments

System info

  • Playwright Version: [v1.34]
  • Operating System: Windows 11
  • Browser: Chromium
  • Other info:

Source code

//my.test.js
import entry from 'entry.js'
await enter.placeholder(page, 'First Name', person.fname);
await enter.placeholder(page, 'Last Name', person.lname);
await enter.placeholder(page, 'Email', person.email);
await enter.placeholder(page, 'Password', person.password);
await page.getByRole('button', { name: 'Create Account'}).click();
//entry.js
await page.getByPlaceholder(field, { exact: true}).click();
await expect(page.getByPlaceholder(field, { exact: true})).toBeFocused();
await page.getByPlaceholder(field, { exact: true}).fill(value);

  • [ x ] I provided exact source code that allows reproducing the issue locally.

Expected to fill form fields

Actual fills and then dissappears

I have no problem in either --debug or --ui modes

video.webm

TadasV1 avatar May 22 '23 10:05 TadasV1

@TadasV1 Most likely, that's an issue on the page. Playwright is really fast, and some pages are just not ready for that. Take a look at this guide and let me know whether that's the case.

dgozman avatar May 23 '23 23:05 dgozman

Yes, unfortunately, this is the case.

Shouldn't playwright auto-await until all is done? await page.getByPlaceholder(field, { exact: true}).click();

How can I force playwright wait until page had final rehyratation? In my case, it is last .js file that rehydrates page.


Also waiting to fully load all js with await popup.waitForLoadState('networkidle'); 'networkidle' - DISCOURAGED wait until there are no network connections for at least 500 ms. Don't use this method for testing, rely on web assertions to assess readiness instead.

It seems using web assertions does not do this in my case.

TadasV1 avatar May 24 '23 06:05 TadasV1

@TadasV1 If something on the page changes after hydration, you can wait for some text to appear.

await expect(page.getByText('Done loading')).toBeVisible();

Alternatively, you can wait for the specific javascript file to load.

await page.waitForResponse('**/last.js');

However, the right fix is to mark inputs in the non-hydrated page as disabled. This way both Playwright and real user on the slow network connection will not be able to enter values before the page is ready to accept them.

dgozman avatar May 24 '23 17:05 dgozman

Thank you for your time and great advices. I am closing it since its not a bug:/

TadasV1 avatar May 25 '23 12:05 TadasV1

@TadasV1 If something on the page changes after hydration, you can wait for some text to appear.

await expect(page.getByText('Done loading')).toBeVisible();

Alternatively, you can wait for the specific javascript file to load.

await page.waitForResponse('**/last.js');

However, the right fix is to mark inputs in the non-hydrated page as disabled. This way both Playwright and real user on the slow network connection will not be able to enter values before the page is ready to accept them.

Hi @dgozman!

What if I can't control the website? I'm automating some task on a 3rd party website and can't change the HTML.

I guess in that case page.waitForResponse is my best bet?

helpermethod avatar Nov 23 '23 11:11 helpermethod

Note to future self, if you hit this problem, it might be caused the placeholder text being i18n translated when running as headless=false and in english when headless=true 🤦

esselius avatar Jun 27 '24 09:06 esselius