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.
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.jsonPage 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.