Fix Flaky Playwright Tests: Why .press() is Better Than .click()

📝 Why You Should Stop Using .click() Everywhere in Playwright



When I first started using Playwright, it was easy to fall into the habit of using .click() for everything.

Click the login button?
.click()
Open a modal?
.click()
Submit a form?
You guessed it — .click()

But as my test suite grew, I started noticing flaky behaviors. Some tests passed locally but failed in CI. Others failed intermittently without any code changes.

At first, I blamed the usual suspects: slow internet, unstable builds, maybe even gremlins in the matrix. But the more I dug in, the more I realized something important:

       .click() isn’t always your best friend.


⚠️ The Problem with .click()

Here’s the thing. In real-world applications — especially SPAs (Single Page Applications) — elements don’t always behave predictably:

  • Buttons might still be animating into view

  • JavaScript might not have finished attaching listeners

  • The page might be transitioning, even if waitForNavigation() has already resolved

So while .click() works in many cases, it can cause trouble when used blindly.


✅ The Better Approach: Simulate Keyboard Interactions

Instead of forcing a click, sometimes it’s better to do what a user would naturally do: press the "Enter" key.

Here’s what I now use in my tests:

await page.getByText('Login').press('Enter');

Or if I need to make sure it’s focused first:

await page.getByText('Login').focus();
await page.keyboard.press('Enter');

🔥 Why This Works Better

  1. More Realistic: Users often submit forms by pressing Enter — not by clicking.

  2. Avoids Timing Issues: It doesn’t rely on full render or animation completion.

  3. Bypasses Animations: Keyboard events are less likely to be interrupted by moving elements.

  4. Cleaner in Headless Mode: Works well in CI without visual flakiness.


🧪 Real-World Example

Let’s say you have a login form that fades in after a short animation. Your test script tries to .click() the "Login" button — but sometimes it fails because the animation isn’t fully complete.

Instead of adding a hard wait or a flaky waitForSelector, just use:

await page.getByRole('button', { name: 'Login' }).press('Enter');

Boom. Rock solid.


💡 Pro Tip

This method also works great inside modals, popups, and custom components that rely on keyboard accessibility. You’ll often find fewer bugs when you simulate user behavior — not force interaction.


Final Thoughts

If you're facing flaky tests that just don't feel right, review where you’re using .click(). Ask yourself: Would a real user click here or press a key? The answer might save you hours of debugging.

See you tomorrow for Day 3 — where we’ll talk about another little-known trick to stabilize your test suite even further.


🧵 Following along? Don’t forget to share your favorite Playwright hacks using #30DaysOfPlaywrightAutomation and tag @thebughacker!


Previous Post Next Post

Contact Form