All posts

Playwright - cleaning up URLs and configuration
Playwright - cleaning up URLs and configuration

Polski

Playwright - cleaning up URLs and configuration

Set a default site address and shared preconditions once, then keep URL checks explicit and predictable. Environment variables split the web app from the API, mirroring the Cypress URLs article with Playwright configuration habits.

Playwright

Introduction

Repeating full page.goto('http://localhost:4100/login') and asserting that the URL merely “contains /” invites false greens. The Cypress cleanup article walked through hooks and baseUrl; here is the same discipline with Playwright Test.

Previous post: Playwright refactoring - app actions vs POM.

Hooks - test.beforeEach

Playwright reuses Mocha-style hooks. A common pattern: open /login before each test:

import { test } from "@playwright/test"

test.describe("login", () => {
  test.beforeEach(async ({ page }) => {
    await page.goto("/login")
  })

  test("successful login", async ({ page, request }) => {
    // ...
  })
})

In UI mode (npx playwright test --ui) the beforeEach steps are clearly grouped, similar to Cypress’s BEFORE EACH block.

beforeEach in the runner (asset from the Cypress series)

baseURL

In playwright.config.ts:

import { defineConfig } from "@playwright/test"

export default defineConfig({
  use: {
    baseURL: process.env.BASE_URL ?? "http://localhost:4100",
  },
})

Now page.goto("/login") resolves against the frontend origin - the same idea as baseUrl in cypress.json.

URL assertions - substring traps

Checking only / still passes if the app navigates to /you_should_not_be_here. Prefer equality (or a tight regex):

import { expect } from "@playwright/test"

const base = process.env.BASE_URL ?? "http://localhost:4100"

await expect(page).toHaveURL(`${base}/`)
await expect(page).toHaveURL(`${base}/login`)

Wrong “include /” assertion (from the Cypress article)

API base URL

Keep the ASP.NET host (http://localhost:5000) in process.env.API_URL and reuse it inside HTTP helpers. Optionally mirror values into defineConfig({ env: { ... } }) if you prefer reading from test.info(), but shared modules reading process.env are usually enough.

Remember: issue DELETE before POST when seeding users - the same logical bug described in login tests and the URL refactor post if create skips cleanup.

On CI, define BASE_URL and API_URL as pipeline variables (Cypress on Azure shows the idea). Playwright needs no Cypress plugin: Node already sees process.env before tests start.

Summary

Cypress Playwright Test
cypress.json playwright.config.ts
cy.visit('/x') page.goto('/x') + baseURL
Cypress.config() process.env / defineConfig

Reference branch from the Cypress series:

https://github.com/12masta/react-redux-realworld-example-app/tree/4-cypress

https://github.com/12masta/react-redux-realworld-example-app/pull/4/files

Next: data-testid selectors in Playwright.