← Back to Playwright Mastery
Basic16 min read

Navigation & Pages

Navigate URLs, history, reload, and handle page lifecycle events.

page.goto()

goto accepts path relative to baseURL or absolute URL. waitUntil option controls navigation completion: load, domcontentloaded, networkidle, commit.

Default waitUntil load suits most SPAs; networkidle flaky on sites with perpetual polling—prefer domcontentloaded or explicit locators.

await page.goto("/dashboard");
await page.goto("https://example.com", { waitUntil: "domcontentloaded" });

Back, Forward, and Reload

page.goBack and page.goForward navigate history. page.reload refreshes current page. Assert URL with expect(page).toHaveURL after navigation.

Test browser back button behavior on multi-step forms and SPA route stack.

await page.getByRole("link", { name: "Details" }).click();
await expect(page).toHaveURL(/\/items\/\d+/);
await page.goBack();
await expect(page).toHaveURL("/items");

Page Lifecycle Events

Listen to page.on("load"), domcontentloaded, console, pageerror, and request/response for debugging. dialog event handles alert, confirm, prompt.

Close dialogs with dialog.accept() or dismiss() in handler before they block automation.

  • page.waitForURL pattern waits for client-side routing
  • Framenavigated events help with iframe-heavy apps
  • Avoid race between goto and early assertions—locators auto-wait
page.on("dialog", async (dialog) => {
  expect(dialog.message()).toContain("Delete");
  await dialog.accept();
});

Multiple Pages and Tabs

context.waitForEvent("page") captures popup or new tab from target=_blank click. Interact with both pages in same test for OAuth popup flows.

Close pages with page.close() when done to free resources in long tests.

const popupPromise = context.waitForEvent("page");
await page.getByText("Open docs").click();
const popup = await popupPromise;
await expect(popup.getByRole("heading")).toHaveText("Documentation");

Navigation Best Practices

Use baseURL in config so tests use relative paths—easier environment switching. Avoid hard-coded production URLs in tests.

Wait for meaningful UI ready state (heading visible, skeleton gone) not arbitrary timeouts after navigation.

  • Test deep links directly with goto for speed
  • Verify 404 and unauthorized routes with URL and content assertions
  • Record HAR for replay debugging slow navigations

Get In Touch


Ready to discuss your next project? Drop me a message.