Skip to content

StepwrightContext

StepwrightContext

The context object passed to every step, providing access to the browser, data, and utilities.

Import

import type { StepwrightContext } from '@korvol/stepwright';

Properties

Playwright Primitives

browser

The Playwright Browser instance.

readonly browser: Browser

Example:

.step('Get browser info', async (ctx) => {
console.log('Browser version:', ctx.browser.version());
})

browserContext

The Playwright BrowserContext instance.

readonly browserContext: BrowserContext

Example:

.step('Get cookies', async (ctx) => {
const cookies = await ctx.browserContext.cookies();
console.log('Cookies:', cookies);
})

page

The active Playwright Page instance.

page: Page

Example:

.step('Navigate', async (ctx) => {
await ctx.page.goto('https://example.com');
await ctx.page.click('#button');
})

Configuration

config

The current script configuration (read-only).

readonly config: StepwrightConfig

Example:

.step('Check config', async (ctx) => {
if (ctx.config.headless) {
console.log('Running headless');
}
})

State Management

data

The shared data object.

data: TData

Example:

.step('Store value', async (ctx) => {
ctx.data.extractedId = await ctx.page.textContent('#id');
})
.step('Use value', async (ctx) => {
console.log('ID:', ctx.data.extractedId);
})

locators

Named locators for reuse across steps.

locators: Record<string, Locator>

Example:

.step('Setup locators', async (ctx) => {
ctx.locators.submitBtn = ctx.page.locator('button[type="submit"]');
ctx.locators.errorMsg = ctx.page.locator('.error-message');
})
.step('Use locators', async (ctx) => {
await ctx.locators.submitBtn.click();
await expect(ctx.locators.errorMsg).not.toBeVisible();
})

Step Information

step

Information about the currently executing step.

readonly step: CurrentStepInfo | null
interface CurrentStepInfo {
name: string;
index: number;
checkpoint?: string;
}

Example:

.step('Log step info', async (ctx) => {
console.log('Running step:', ctx.step?.name);
console.log('Step index:', ctx.step?.index);
console.log('Checkpoint:', ctx.step?.checkpoint);
})

results

Results of previously completed steps.

readonly results: StepResult[]

Example:

.step('Check previous', async (ctx) => {
const lastStep = ctx.results[ctx.results.length - 1];
if (lastStep?.status === 'failed') {
console.log('Previous step failed');
}
})

Multi-Page Support

pages

Map of registered pages by name.

readonly pages: Map<string, Page>

Example:

.step('Work with multiple pages', async (ctx) => {
// Open popup
const [popup] = await Promise.all([
ctx.page.waitForEvent('popup'),
ctx.page.click('#open-popup'),
]);
// Register the popup
ctx.registerPage('popup', popup);
// Switch to popup
ctx.setActivePage('popup');
await ctx.page.fill('#form', 'data');
// Switch back
ctx.setActivePage('main');
})

Methods

log(message, ...args)

Log a message (respects verbose setting).

log(message: string, ...args: unknown[]): void

Parameters:

NameTypeDescription
messagestringMessage to log
argsunknown[]Additional arguments

Example:

.step('Log messages', async (ctx) => {
ctx.log('Starting operation');
ctx.log('Found items:', items.length);
})

screenshot(name?)

Take a screenshot.

screenshot(name?: string): Promise<string>

Parameters:

NameTypeDescription
namestringOptional screenshot name

Returns: Promise<string> - Path to saved screenshot

Example:

.step('Capture state', async (ctx) => {
const path = await ctx.screenshot('after-login');
console.log('Screenshot saved:', path);
})

getDOM(selector?)

Get the current DOM as a string.

getDOM(selector?: string): Promise<string>

Parameters:

NameTypeDescription
selectorstringOptional selector to get specific element

Returns: Promise<string> - HTML content

Example:

.step('Get DOM', async (ctx) => {
// Full page
const fullDom = await ctx.getDOM();
// Specific element
const formDom = await ctx.getDOM('#signup-form');
})

evaluate<T>(fn)

Run JavaScript in the page context.

evaluate<T>(fn: () => T): Promise<T>

Parameters:

NameTypeDescription
fn() => TFunction to evaluate

Returns: Promise<T> - Result of evaluation

Example:

.step('Run in page', async (ctx) => {
const token = await ctx.evaluate(() => {
return localStorage.getItem('auth_token');
});
})

registerPage(name, page)

Register a page with a name.

registerPage(name: string, page: Page): void

Parameters:

NameTypeDescription
namestringName for the page
pagePagePlaywright Page instance

Example:

.step('Handle popup', async (ctx) => {
const popup = await ctx.page.waitForEvent('popup');
ctx.registerPage('popup', popup);
})

setActivePage(name)

Set the active page.

setActivePage(name: string): void

Parameters:

NameTypeDescription
namestringName of registered page

Example:

.step('Switch pages', async (ctx) => {
ctx.setActivePage('popup');
await ctx.page.click('#confirm');
ctx.setActivePage('main');
})

snapshot()

Take a state snapshot for checkpoint recovery.

snapshot(): ContextSnapshot<TData>

Returns: ContextSnapshot<TData>

Example:

.step('Save state', async (ctx) => {
const snapshot = ctx.snapshot();
console.log('Snapshot ID:', snapshot.id);
})

restoreLastSnapshot()

Restore from the last snapshot.

restoreLastSnapshot(): void

Example:

.step('Restore state', async (ctx) => {
ctx.restoreLastSnapshot();
})

Complete Example

Stepwright.create<{ items: string[] }>('Context Demo')
.data({ items: [] })
.step('Setup', async (ctx) => {
// Navigate
await ctx.page.goto('https://example.com');
// Log
ctx.log('Page loaded');
// Screenshot
await ctx.screenshot('initial-state');
// Store locators
ctx.locators.list = ctx.page.locator('#item-list');
})
.step('Extract items', async (ctx) => {
// Use stored locator
const items = await ctx.locators.list.locator('li').allTextContents();
// Store in data
ctx.data.items = items;
// Log step info
ctx.log(`Step ${ctx.step?.index}: Found ${items.length} items`);
})
.step('Check results', async (ctx) => {
// Access previous results
const previousStep = ctx.results.find(r => r.name === 'Extract items');
console.log('Extract took:', previousStep?.duration, 'ms');
// Check config
if (!ctx.config.headless) {
await ctx.page.pause(); // Only in headed mode
}
});

See Also