Skip to content

Overview

Stepwright Overview

Stepwright is a fluent API wrapper for Playwright that makes browser automation scripts more readable, maintainable, and resilient.

Why Stepwright?

While Playwright is a powerful browser automation library, complex scripts can become difficult to read and maintain. Stepwright addresses this with:

Fluent API

Chain steps together for readable, self-documenting scripts

Checkpoints

Group related steps with automatic retry on failure

Data Management

Type-safe data passing between steps

Artifact Capture

Automatic screenshots and DOM capture on failure

Basic Example

import { Stepwright } from '@korvol/stepwright';
const script = Stepwright.create('Login Flow')
.config({
headless: false,
screenshotOnFailure: true,
})
.checkpoint('Login')
.step('Navigate to login', async (ctx) => {
await ctx.page.goto('https://app.example.com/login');
})
.step('Enter credentials', async (ctx) => {
await ctx.page.fill('#email', 'user@example.com');
await ctx.page.fill('#password', 'password123');
})
.step('Submit form', async (ctx) => {
await ctx.page.click('button[type="submit"]');
await ctx.page.waitForURL('**/dashboard');
})
.endCheckpoint()
.checkpoint('Verify Dashboard')
.step('Check welcome message', async (ctx) => {
const welcome = ctx.page.locator('h1');
await expect(welcome).toContainText('Welcome');
})
.endCheckpoint();
const result = await script.run();
console.log('Success:', result.success);

Key Features

Fluent API

Chain methods together to build readable scripts:

Stepwright.create('My Script')
.config({ headless: true })
.data({ userId: '123' })
.checkpoint('Setup')
.step('Step 1', ...)
.step('Step 2', ...)
.endCheckpoint()
.run();

Step-by-Step Execution

Each step runs sequentially with full error handling:

  • Individual timeouts and retries
  • Automatic artifact capture on failure
  • Clear error reporting with step context

Checkpoint-Based Recovery

Group related steps into checkpoints for intelligent retry:

.checkpoint('Login', { maxRetries: 2 })
.step('Fill form', ...)
.step('Submit', ...)
.endCheckpoint()

If any step in a checkpoint fails, the entire checkpoint retries from the beginning.

Type-Safe Data

Pass data between steps with full TypeScript support:

interface MyData {
username: string;
token?: string;
}
Stepwright.create<MyData>('My Script')
.data({ username: 'testuser' })
.step('Get token', async (ctx) => {
ctx.data.token = await fetchToken();
});

Architecture

┌─────────────────────────────────────────────────────────────────┐
│ Stepwright │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Config │ │ Data │ │ Steps │ │Reporters │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ TaskQueue (Execution) │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────────────────────┐ │
│ │ Checkpoints │ │ Background Tasks │ │
│ └─────────────────┘ └─────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Playwright (Browser) │
└─────────────────────────────────────────────────────────────────┘

When to Use Stepwright

Use Stepwright when:

  • Writing complex multi-step automations
  • You need checkpoint-based retry logic
  • You want automatic artifact capture
  • You’re building scripts that Fixwright will maintain

Consider vanilla Playwright when:

  • Simple one-off scripts
  • Performance-critical scenarios
  • You need maximum control

Next Steps