Skip to content

Core Concepts

Core Concepts

Understanding these concepts will help you write effective automation scripts.

Steps

A step is a single unit of work in your automation script.

.step('Click the button', async (ctx) => {
await ctx.page.click('button.submit');
})

Each step:

  • Has a name for identification and logging
  • Receives a context (ctx) with page access and utilities
  • Can be configured with options like timeout and retries
  • Is executed sequentially

Step Options

.step('Slow operation', async (ctx) => {
// ...
}, {
timeout: 30000, // Custom timeout
critical: true, // Fail script if this fails
retry: {
times: 3, // Retry up to 3 times
delay: 1000, // Wait 1 second between retries
backoff: 'exponential'
}
})

Checkpoints

A checkpoint groups related steps together.

.checkpoint('Login Flow', { required: true, maxRetries: 2 })
.step('Enter username', ...)
.step('Enter password', ...)
.step('Click login', ...)
.endCheckpoint()

Checkpoints provide:

  • Logical grouping - Organize related steps
  • Checkpoint-level retries - Retry all steps if any fail
  • Required vs optional - Required checkpoints fail the script if they fail
  • Clean failure boundaries - Easier debugging and reporting

Context

The context (ctx) is passed to every step and provides:

.step('Example', async (ctx) => {
// Page access
await ctx.page.goto('https://example.com');
// Logging
ctx.log('Something happened');
// Data access
ctx.data.myValue = 'stored';
console.log(ctx.data.existingValue);
// Screenshots
const path = await ctx.screenshot('my-screenshot');
// Configuration access
console.log(ctx.config.headless);
})

Data

Data is shared state that persists across steps.

Stepwright.create<{ username: string; token?: string }>('My Script')
.data({ username: 'testuser' })
.step('Login', async (ctx) => {
// Read initial data
await ctx.page.fill('#user', ctx.data.username);
// Store new data
ctx.data.token = await getToken();
})
.step('Use token', async (ctx) => {
// Access previously stored data
console.log('Token:', ctx.data.token);
})

Data is:

  • Type-safe - Define your data shape with TypeScript
  • Mutable - Steps can read and write
  • Included in results - Available after script completes

Configuration

Configuration controls script behavior:

.config({
// Browser
headless: true,
defaultTimeout: 30000,
// Artifacts
screenshotOnFailure: true,
domOnFailure: true,
artifactDir: './artifacts',
// Reporting
verbose: true,
})

See Configuration Reference for all options.

Failure Cases

When a script fails, Stepwright can generate a failure case:

import { generateFailureCase } from '@korvol/stepwright';
const result = await script.run();
if (!result.success && result.failedStep) {
const failureCase = generateFailureCase(result, {
scriptInfo: {
name: 'My Script',
path: 'scripts/my-script.ts',
},
});
// Save to file or database for Fixwright
}

A failure case contains:

  • Script information
  • Error details and stack trace
  • Source code location
  • Artifact paths (screenshots, DOM, console logs)

Fixwright Integration

Fixwright consumes failure cases and attempts to fix them:

import { FixWright } from '@korvol/fixwright';
const fixwright = new FixWright({
ai: { apiKey: process.env.ANTHROPIC_API_KEY! },
});
fixwright.useFileSource('./failure-cases');
fixwright.on('attempt:success', (attempt) => {
console.log('Fix found:', attempt.proposedFix);
});
await fixwright.start();

The fix loop:

  1. Receives a failure case
  2. Analyzes with Claude AI
  3. Proposes a code fix
  4. Validates by re-running the script
  5. Creates a PR if successful

Next Steps