スポンサーリンク

Playwright Wait Strategies in C#: Reliable E2E Testing Guide

This article is part of the “Introduction to E2E Testing with Reqnroll × Playwright” series.

Playwright Wait Strategies in C#: Reliable E2E Testing Guide

To write stable E2E tests with Playwright in .NET, you must handle waiting correctly. While Playwright provides powerful auto-waiting, knowing when and how to use explicit waits is key to avoiding flaky tests.

In this guide, you’ll learn how Playwright waits work and how to use them effectively in C#.

Why Waiting Matters in Playwright

In real-world UI tests, timing issues happen frequently:

  • Elements load after navigation
  • AJAX requests delay rendering
  • Buttons appear dynamically
  • Modals open asynchronously

Without proper waiting, tests may:

  • Click elements before they exist
  • Fail intermittently
  • Break in CI environments

Playwright Auto-Wait (Built-in Feature)

One of Playwright’s biggest advantages is auto-waiting.

Example

await Page.ClickAsync("#login-button");

Before clicking, Playwright automatically waits until:

  • The element exists in the DOM
  • The element is visible
  • The element is clickable

Key Insight

In many cases, you don’t need to write explicit waits for simple actions like clicking or typing.

Wait for an Element to Appear

When elements load dynamically, use WaitForSelectorAsync.

await Page.WaitForSelectorAsync("#login-button");
await Page.ClickAsync("#login-button");

This ensures the element is present before interaction.

Wait for Visible State

await Page.WaitForSelectorAsync(
"#login-button",
new PageWaitForSelectorOptions
{
State = WaitForSelectorState.Visible
});

Common States

  • Attached → Exists in DOM
  • Visible → Displayed on screen
  • Hidden → Not visible
  • Detached → Removed from DOM

Tip: Use Visible in most UI test cases.

Wait for Page Navigation

After clicking a link or submitting a form, wait for the page to load.

await Page.ClickAsync("#login-button");
await Page.WaitForLoadStateAsync();

This ensures the page is fully loaded before continuing.

Wait for URL Changes

If you want to confirm navigation to a specific page:

await Page.WaitForURLAsync("**/dashboard");

Example Flow

await Page.ClickAsync("#login-button");
await Page.WaitForURLAsync("**/dashboard");

Avoid Fixed Waits (Sleep)

You can use a timeout:

await Page.WaitForTimeoutAsync(2000);

However, this is not recommended.

Why Avoid It?

  • Slows down tests
  • Makes tests flaky
  • Not reliable in CI

Better Alternatives

  • Wait for elements
  • Wait for URL
  • Wait for load state

Using Locator for Waiting (Recommended)

Playwright recommends using the Locator API.

Basic Wait

await Page.Locator("#login-button").WaitForAsync();

Wait for Visible State

await Page.Locator("#login-button").WaitForAsync(
new LocatorWaitForOptions
{
State = WaitForSelectorState.Visible
});

Benefits of Locator

  • Cleaner syntax
  • Better maintainability
  • More reliable element handling

Example in Reqnroll StepDefinitions

When using Playwright with Reqnroll, waits are often used in step definitions.

Check Element Visibility

[Then(@"the login button is visible")]
public async Task ThenLoginButtonIsVisible()
{
await Page.WaitForSelectorAsync("#login-button");
}

Click Button

[When(@"the user clicks the login button")]
public async Task WhenClickLogin()
{
await Page.ClickAsync("#login-button");
}

This keeps your tests aligned with BDD-style scenarios.

Common Wait Methods in Playwright

MethodPurpose
WaitForSelectorAsyncWait for element
WaitForLoadStateAsyncWait for page load
WaitForURLAsyncWait for URL change
WaitForTimeoutAsyncFixed delay (avoid)

Best Practices for Playwright Waiting

Use This Strategy

  1. Rely on auto-wait first
  2. Add explicit waits only when needed
  3. Prefer element or URL-based waits
  4. Avoid fixed time waits

Summary

Handling waits correctly is essential for stable Playwright tests.

Key Examples

await Page.WaitForSelectorAsync("#element");
await Page.WaitForURLAsync("**/home");
await Page.WaitForLoadStateAsync();

Playwright’s auto-wait covers many cases, but for dynamic content and navigation, explicit waits ensure reliability.

By combining smart wait strategies with Playwright, you can build fast, stable, and production-ready E2E tests in .NET.