Skip to main content

Ports Reference

Complete reference for all port interfaces in @esimplicity/stack-tests.

Overview

Ports define the contracts that adapters must implement. They enable the Ports and Adapters (Hexagonal) architecture pattern.

ApiPort

HTTP API operations interface.

Import

import type { ApiPort, ApiMethod, ApiResult } from '@esimplicity/stack-tests';

Interface

interface ApiPort {
sendJson(
method: ApiMethod,
path: string,
body?: unknown,
headers?: Record<string, string>
): Promise<ApiResult>;

sendForm(
method: 'POST' | 'PUT' | 'PATCH',
path: string,
form: Record<string, string>,
headers?: Record<string, string>
): Promise<ApiResult>;
}

Types

type ApiMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';

type ApiResult = {
status: number;
text: string;
json?: unknown;
headers: Record<string, string>;
contentType?: string;
response: APIResponse; // Playwright APIResponse
};

Methods

sendJson(method, path, body?, headers?)

Sends an HTTP request with JSON body.

ParameterTypeRequiredDescription
methodApiMethodYesHTTP method
pathstringYesRequest path (appended to base URL)
bodyunknownNoRequest body (serialized to JSON)
headersRecord<string, string>NoAdditional headers

Returns: Promise<ApiResult>

Example:

const result = await api.sendJson('POST', '/users', {
email: 'test@example.com',
name: 'Test User',
}, {
'X-Request-ID': '123',
});

console.log(result.status); // 201
console.log(result.json); // { id: '...', email: '...' }

sendForm(method, path, form, headers?)

Sends an HTTP request with form-urlencoded body.

ParameterTypeRequiredDescription
method'POST' | 'PUT' | 'PATCH'YesHTTP method
pathstringYesRequest path
formRecord<string, string>YesForm fields
headersRecord<string, string>NoAdditional headers

Returns: Promise<ApiResult>

Example:

const result = await api.sendForm('POST', '/auth/login', {
username: 'admin@example.com',
password: 'secret',
});

UiPort

Browser UI operations interface.

Import

import type { 
UiPort,
UiClickMode,
UiInputMode,
UiUrlAssertMode,
UiLocatorMethod,
UiElementState
} from '@esimplicity/stack-tests';

Interface

interface UiPort {
// Navigation
goto(path: string): Promise<void>;
goBack(): Promise<void>;
reload(): Promise<void>;
getCurrentUrl(): Promise<string>;
waitForPageLoad(): Promise<void>;

// Basic Interactions
clickButton(name: string): Promise<void>;
clickLink(name: string): Promise<void>;
fillPlaceholder(placeholder: string, value: string): Promise<void>;
fillLabel(label: string, value: string): Promise<void>;

// Advanced Interactions
clickElementThatContains(clickMode: UiClickMode, elementType: string, text: string): Promise<void>;
clickElementWith(clickMode: UiClickMode, ordinal: string, text: string, method: UiLocatorMethod): Promise<void>;
fillDropdown(value: string, dropdownLabel: string): Promise<void>;
inputInElement(action: UiInputMode, value: string, ordinal: string, text: string, method: UiLocatorMethod): Promise<void>;

// Keyboard
typeText(text: string): Promise<void>;
pressKey(key: string): Promise<void>;

// Waiting
waitSeconds(seconds: number): Promise<void>;

// Viewport
zoomTo(scale: number): Promise<void>;

// Assertions
expectText(text: string): Promise<void>;
expectUrlContains(part: string): Promise<void>;
expectUrl(mode: UiUrlAssertMode, expected: string): Promise<void>;
expectNewTabUrl(mode: UiUrlAssertMode, expected: string): Promise<void>;
expectElementWithTextVisible(elementType: string, text: string, shouldBeVisible: boolean): Promise<void>;
expectElementState(ordinal: string, text: string, method: UiLocatorMethod, state: UiElementState): Promise<void>;
expectElementStateWithin(ordinal: string, text: string, method: UiLocatorMethod, state: UiElementState, seconds: number): Promise<void>;
}

Types

type UiClickMode = 'click' | 'dispatch click' | 'force click' | 'force dispatch click';
type UiInputMode = 'type' | 'fill' | 'choose';
type UiUrlAssertMode = 'contains' | 'doesntContain' | 'equals';
type UiLocatorMethod = 'text' | 'label' | 'placeholder' | 'role' | 'test ID' | 'alternative text' | 'title' | 'locator';
type UiElementState = 'visible' | 'hidden' | 'editable' | 'disabled' | 'enabled' | 'read-only';

Key Methods

goto(path)

Navigates to a URL path.

await ui.goto('/login');
await ui.goto('https://example.com');

clickButton(name)

Clicks a button by its accessible name.

await ui.clickButton('Submit');
await ui.clickButton('Sign In');

fillLabel(label, value)

Fills an input field by its label.

await ui.fillLabel('Email', 'user@example.com');
await ui.fillLabel('Password', 'secret123');

expectText(text)

Asserts that text is visible on the page.

await ui.expectText('Welcome');
await ui.expectText('Login successful');

TuiPort

Terminal UI operations interface.

Import

import type {
TuiPort,
TuiConfig,
TuiKeyModifiers,
TuiWaitOptions,
TuiScreenCapture,
TuiSnapshotResult,
TuiMouseEvent,
TuiMouseButton,
} from '@esimplicity/stack-tests';

Interface

interface TuiPort {
// Lifecycle
start(): Promise<void>;
stop(): Promise<void>;
restart(): Promise<void>;
isRunning(): boolean;

// Input
typeText(text: string, options?: { delay?: number }): Promise<void>;
pressKey(key: string, modifiers?: TuiKeyModifiers): Promise<void>;
sendText(text: string): Promise<void>;
fillField(fieldLabel: string, value: string): Promise<void>;
selectOption(option: string): Promise<void>;

// Mouse
sendMouse(event: TuiMouseEvent): Promise<void>;
click(x: number, y: number, button?: TuiMouseButton): Promise<void>;
clickOnText(text: string): Promise<void>;

// Assertions
expectText(text: string, options?: TuiWaitOptions): Promise<void>;
expectPattern(pattern: RegExp, options?: TuiWaitOptions): Promise<void>;
expectNotText(text: string): Promise<void>;
assertScreenContains(text: string): Promise<void>;
assertScreenMatches(pattern: RegExp): Promise<void>;

// Waiting
waitForText(text: string, options?: TuiWaitOptions): Promise<void>;
waitForPattern(pattern: RegExp, options?: TuiWaitOptions): Promise<void>;
waitForReady(): Promise<void>;
waitSeconds(seconds: number): Promise<void>;

// Screen Capture
captureScreen(): Promise<TuiScreenCapture>;
getScreenText(): Promise<string>;
getScreenLines(): Promise<string[]>;

// Snapshots
takeSnapshot(name: string): Promise<void>;
matchSnapshot(name: string): Promise<TuiSnapshotResult>;

// Utility
clear(): Promise<void>;
resize(size: { cols: number; rows: number }): Promise<void>;
getSize(): { cols: number; rows: number };
getConfig(): TuiConfig;
}

Types

type TuiConfig = {
command: string[];
size?: { cols: number; rows: number };
cwd?: string;
env?: Record<string, string>;
debug?: boolean;
snapshotDir?: string;
shell?: string;
};

type TuiKeyModifiers = {
ctrl?: boolean;
alt?: boolean;
shift?: boolean;
meta?: boolean;
};

type TuiWaitOptions = {
timeout?: number;
interval?: number;
};

type TuiScreenCapture = {
text: string;
lines: string[];
timestamp: number;
size: { cols: number; rows: number };
};

type TuiSnapshotResult = {
pass: boolean;
diff?: string;
snapshotPath?: string;
};

type TuiMouseButton = 'left' | 'right' | 'middle';
type TuiMouseEventType = 'click' | 'down' | 'up' | 'drag' | 'scroll';

type TuiMouseEvent = {
type: TuiMouseEventType;
position: { x: number; y: number };
button?: TuiMouseButton;
};

AuthPort

Authentication operations interface.

Import

import type { AuthPort } from '@esimplicity/stack-tests';

Interface

interface AuthPort {
apiLoginAsAdmin(world: World): Promise<void>;
apiLoginAsUser(world: World): Promise<void>;
apiSetBearer(world: World, token: string): void;
uiLoginAsAdmin(world: World): Promise<void>;
uiLoginAsUser(world: World): Promise<void>;
}

Methods

apiLoginAsAdmin(world)

Authenticates as admin via API, setting bearer token in world.headers.

apiLoginAsUser(world)

Authenticates as standard user via API.

apiSetBearer(world, token)

Manually sets a bearer token.

uiLoginAsAdmin(world)

Performs admin login through the UI.

uiLoginAsUser(world)

Performs user login through the UI.


CleanupPort

Resource cleanup interface.

Import

import type { CleanupPort } from '@esimplicity/stack-tests';

Interface

interface CleanupPort {
registerFromVar(world: World, varName: string, id: unknown, meta?: unknown): void;
}

Methods

registerFromVar(world, varName, id, meta?)

Registers a resource for cleanup based on variable naming conventions.

ParameterTypeRequiredDescription
worldWorldYesTest world state
varNamestringYesVariable name (used to determine cleanup path)
idunknownYesResource ID
metaunknownNoAdditional metadata

Example:

cleanup.registerFromVar(world, 'userId', '123');
// Registers DELETE /admin/users/123 based on 'user' pattern