playwright-adventures
A browser-automation playground with TypeScript and Python Playwright stacks, shared executable journeys, a local test application, and MCP browser tools.
- Goal
- Experiment with Playwright features and patterns
- My role
- Solo developer
- Status
- Active
- Started
- Playwright
- TypeScript
- Python
- MCP
- Node.js
- GitHub Actions
I created Playwright Adventures as a place to experiment with browser automation and work out which testing patterns I would want to carry into other projects. I was interested in complete user journeys, such as signing in and checking account details, and in how the same intent could be expressed in both TypeScript and Python. Keeping the two implementations together gives me a way to compare their APIs and conventions against the same small application. The project also explores how those journeys can be exposed to an agent through the Model Context Protocol, or MCP, alongside individual browser actions.
The repository contains two Playwright stacks, shared journey specifications, and a small local application built with the Node.js standard library. That application supplies a homepage, login flow, dashboard, and account-detail page with predictable test data. Both smoke-test suites start and stop it automatically unless I configure another compatible target, so the default workflow does not depend on a separate service being available. The fixture is deliberately test-only; the account screens exist to exercise browser behavior, not to serve as the beginnings of a production account-management application. Around it, the project brings together page objects, reusable journeys, and a selector policy favoring accessible roles, labels, and stable test IDs.
The scope is still small enough that I can follow a scenario from its written definition through both implementations and into the browser. The major capabilities are:
- Parallel TypeScript and Python test stacks exercising the same login, dashboard, and account-detail flows.
- Shared executable YAML journeys with reusable parent flows and generated adapters for both languages.
- A managed local test application, plus the option to run those journeys against another application implementing the same contract.
- MCP servers exposing navigation, clicking, form filling, text retrieval, screenshots, and complete journeys, together with the shared specifications as readable resources.
- Automated checks for generated files, MCP protocol behavior, browser-tool boundaries, and browser journeys, with an optional live-target CI run.
One implementation challenge was keeping the TypeScript and Python journeys equivalent as the shared specifications evolved. A prose description alone would still leave two sets of handwritten steps free to drift. I made the YAML executable instead: it defines the ordered actions, selectors, fixture references, and journey composition, and a generator produces typed specifications and journey IDs for both languages. Small handwritten runners translate that common vocabulary into each Playwright API. The build rejects missing or stale generated files, and generation validates unsupported actions, duplicate IDs, missing parents, and inheritance cycles. I also represented text matching as literal alternatives with explicit matching options, so each runner can construct its own escaped regular expressions without relying on language-specific regex syntax in the shared document.
I treat the MCP side as an experiment in giving browser automation explicit boundaries. Document navigation is checked against an origin allowlist, screenshots are restricted to new files in a configured directory, and predefined journeys receive fresh browser contexts that are closed after success or failure. Those controls are useful, but the navigation allowlist is not a complete network sandbox: page resources, fetch requests, and other browser traffic are outside that policy. The project remains an active learning scaffold rather than a hosted product. What I want from it is a small, inspectable place to try automation patterns, compare the two language stacks, and understand what changes when a test runner’s capabilities become tools an agent can call.