Skip to content
HN
Back to projects

Featured Project

Playwright Automation Framework

A maintainable, scalable end-to-end testing framework built to test a real app I built myself.

A Playwright + TypeScript framework validating Blog Person, a full-stack blogging platform I designed and built myself (Next.js frontend, Express/MongoDB backend) — structured around Page Object Model, data-driven testing and a deliberate retry strategy so the suite stays maintainable as it grows.

PlaywrightTypeScriptNode.jsGitHub ActionsHTML Report

Overview

This framework tests Blog Person, a personal full-stack blogging platform I built from scratch — a Next.js + TypeScript frontend and an Express + MongoDB backend — so every test scenario maps to a real feature rather than a demo app. The focus was on what makes automation sustainable long-term: not the number of tests, but how cheaply they can be extended and how quickly a failure can be diagnosed. Every design decision — folder structure, locator strategy, retry policy — was made with a six-months-from-now maintainer in mind.

Application Under Test

Blog Person is a full-stack blogging platform: a Next.js + TypeScript frontend with locale-based routing and i18n, and an Express + MongoDB backend handling authentication (Clerk), image uploads (ImageKit) and real-time features (Socket.io). The suite covers post management, language switching, trending/popular content sections and navigation, organized into smoke and regression suites so CI can run a fast subset on every push.

Architecture

  • Layered design: tests never talk to the page directly — only through page objects.
  • Config-driven environments (base URL, timeouts, credentials) kept out of test code.
  • Central fixtures file to inject page objects and API clients into every test with zero boilerplate.
  • Reporting layer decoupled from test logic — HTML report and traces are generated the same way regardless of which suite ran.

Folder Structure

.github/
  workflows/
tests/
pages/
fixtures/
data/
utils/
playwright.config.ts
tsconfig.json

Page Object Model

Every screen is modeled as a class exposing intent-based methods (login(), addToCart()) rather than raw locators, so a UI change updates one file instead of every test that touches that screen.

Data Driven Testing

Test data lives in typed fixtures separate from test logic, so adding a new scenario (e.g. another invalid-login case) means adding a data row, not duplicating a test.

Retry Strategy

Retries are configured at the project level for genuine environment flakiness, but any test that needs a retry to pass locally is treated as a bug in the test — usually a missing wait condition or a race with app state — and gets fixed rather than left to retry silently.

Screenshot & HTML Report

Screenshots and traces are captured only on first retry to keep CI artifacts lean, and the built-in HTML report is published as a CI artifact for one-click triage of any failure.

Cross Browser & Mobile Testing

The same spec files run across Chromium, Firefox and WebKit projects, plus emulated mobile viewports, using Playwright's project configuration instead of duplicating test files per browser.

Lessons Learned

  • A clean folder structure pays for itself the first time a locator breaks across 20 tests.
  • Auto-waiting removes most flakiness — most of the rest comes from application state, not Playwright.
  • Retries should be a safety net for infrastructure noise, never a substitute for fixing a real race condition.