CITApp Playwright testing: from repeated actions to reusable workflows#
I needed an E2E testing suite that could support several TOL web applications, including legacy applications whose frontend I often could not change. I started by recording browser interactions, then moved repeated work into shared functions. Tests could describe a workflow while those functions handled the application’s controls, labels, and navigation.
That foundation supported more than test maintenance. Documented helpers gave agents a vocabulary for drafting and repairing tests. User stories, readable test steps, and named screenshots also supplied material for user-manual drafts.
When the work happened#
I began using Playwright for E2E automation on another application in mid-2024. This project began in early 2025, with much of the Claude and agent work taking place from early 2025 through December 2025. The general timeline places the stages in that window; individual milestone months remain approximate.
Follow the progression#
The walkthrough starts with repeated browser actions, explains the shared functions in detail, and returns to those functions when following generated tests and documentation. Code examples are visible on the page as fenced, syntax-highlighted blocks. The helper chapters show complete implementations and larger call examples with their setup and configuration.
Chapter |
What it explains |
|---|---|
Recorded actions, function-based POM principles, shared setup, and common values. |
|
Where application workflows, components, data, and execution reporting live. |
|
A guide to the four detailed helper walkthroughs below. |
|
Common template interactions, optional sections, reminders, iframe cells, and complete inline/JSON examples. |
|
Primary and mailing forms, the original and configurable implementations, and complete inline/JSON examples. |
|
Capture implementation, test lifecycle, filenames, documentation destinations, and a manual image reference. |
|
|
|
How helper source became a developer reference, including Sphinx presentation and deprecation. |
|
Recordings → stories → helper-based tests → execution feedback and repairs. |
|
A complete spec with its imports, shared lifecycle, calls, and outputs explained. |
|
How stories, test steps, configuration, and images became material for a reviewed manual draft. |
What the abstraction made possible#
The email-template functions are a small example of the design. Several applications handled templates in similar ways, so the test could name a template and its differences. The email walkthrough shows all three implementations and the complete test around calls like these:
// Illustrative calls: page is authenticated and at the template screen.
await verifyTemplateFields(page, 'Welcome Email', {
hasHelperTags: true,
hasNotice: false
});
await setReminderHours(page, 'Reminder Settings', {
first: '24',
second: '48',
afterSecond: '72'
});
await interactWithIframeCell(page, 'Email Body');
When a common control changed, its helper supplied one place to investigate and repair the interaction. When values differed, arguments or configuration supplied those values. Application-specific behavior still needed the appropriate navigation, login, and component implementation.
The same division carried into the final feature tests: setup established the starting screen, workflow helpers performed actions, configuration supplied expected labels, and screenshot utilities named the resulting images.
flowchart TD
S[Readable test specification] --> H[Setup and login harness]
S --> D[Application workflow helpers]
S --> C[Component and verification helpers]
V[Shared values and application configuration] --> D
V --> C
H --> B[Existing application in the browser]
D --> C
C --> B
S --> A[Named test and documentation screenshots]
A --> M[User-manual drafts and author review]
R[Runner and reporters] --> E[Execution results and diagnostics]
E --> F[Agent investigation and rerun]
F --> S
D --> J[Generated helper reference]
C --> J
The implementation applies POM principles through functions and modules that encapsulate page behavior. The source examples show that organization directly. They also preserve limitations such as fixed waits, fallback selectors, and helpers that log a missing condition instead of asserting it.