Testing utilities
Helpers for unit and integration testing. Import from @arlopass/react/testing.
import {
createMockTransport,
MockArlopassProvider,
mockWindowArlopass,
cleanupWindowArlopass,
simulateExternalDisconnect,
waitForSnapshot,
waitForChat,
waitForStream,
waitForState,
} from "@arlopass/react/testing";
createMockTransport
Creates a ArlopassTransport that responds to protocol capabilities without a real extension. Supports configurable responses, errors, latency, and streaming.
<ApiTable
props={[
{
name: "capabilities",
type: "readonly string[]",
default:
'[
"session.create",
"provider.list",
"chat.completions",
"chat.stream"
]',
description: "Capabilities returned on session.create.",
},
{
name: "providers",
type: "readonly { providerId: string; providerName: string; models: readonly string[] }[]",
default:
'[{ providerId: "mock", providerName: "Mock Provider", models: ["mock-model"] }]'} ,
description: "Providers returned on provider.list.",
},
{
name: "chatResponse",
type: "string | (() => string)",
default: '"Hello from mock!"',
description:
"Response for chat.completions. Can be a string or a factory function.",
},
{
name: "failOn",
type: "string",
description:
'Capability name to throw an error on (e.g. "chat.completions").',
},
{
name: "chatError",
type: "Error",
description: "Specific error to throw on chat.completions.",
},
{
name: "latency",
type: "number",
default: "0",
description: "Simulated latency in milliseconds before responding.",
},
{
name: "streamChunks",
type: "readonly string[]",
description:
"Individual chunks for chat.stream. Each string becomes a chunk payload.",
},
{
name: "streamResponse",
type: "string",
description: "Full stream response — overrides streamChunks when set.",
},
]}
/>
const transport = createMockTransport({
chatResponse: "Hello!",
latency: 100,
});
MockArlopassProvider
Test wrapper that injects a mock transport into window.arlopass and wraps children with <ArlopassProvider>. Drop-in replacement for the real provider in test renders.
<ApiTable
props={[
{
name: "transport",
type: "ArlopassTransport",
required: true,
description: "Mock transport to inject as window.arlopass.",
},
{
name: "appId",
type: "string",
default: '"test"',
description: "App ID for the provider.",
},
{
name: "children",
type: "ReactNode",
required: true,
description: "Components under test.",
},
{
name: "...rest",
type: "ArlopassProviderProps",
description:
"All other ArlopassProvider props (defaultProvider, autoConnect, etc.).",
},
]}
/>
const transport = createMockTransport();
render(
<MockArlopassProvider transport={transport}>
<MyComponent />
</MockArlopassProvider>,
);
Window mocks
Low-level functions for controlling window.arlopass in tests.
<ApiTable
props={[
{
name: "mockWindowArlopass",
type: "(transport: ArlopassTransport) => void",
description:
"Injects a transport as window.arlopass. Use before rendering ArlopassProvider in tests.",
},
{
name: "cleanupWindowArlopass",
type: "() => void",
description:
"Removes window.arlopass to simulate extension not installed.",
},
{
name: "simulateExternalDisconnect",
type: "(transport: ArlopassTransport) => Promise
description:
"Removes window.arlopass and calls transport.disconnect() if available.",
},
]}
/>
// Setup
mockWindowArlopass(transport);
// Teardown
cleanupWindowArlopass();
// Simulate disconnect
await simulateExternalDisconnect(transport);
Wait helpers
Polling utilities for async test assertions. All accept an optional timeout (default 3000ms, poll interval 50ms).
<ApiTable
props={[
{
name: "waitForSnapshot",
type: "(store: ClientStore, predicate: (snapshot: ClientSnapshot) => boolean, options?: { timeout?: number }) => Promise
description:
"Polls the store until the predicate returns true. Default timeout: 3000ms.",
},
{
name: "waitForChat",
type: "(screen: Screen, testId?: string) => Promise
description:
'Waits for an element with the given data-testid (default: "chat-ready") to appear.',
},
{
name: "waitForStream",
type: "(screen: Screen, options?: { timeout?: number }) => Promise
description:
'Waits until the streaming indicator disappears (data-testid="streaming" is removed).',
},
{
name: "waitForState",
type: "(screen: Screen, state: string, options?: { timeout?: number }) => Promise
description:
'Waits until data-testid="state" has the given text content.',
},
]}
/>
// Wait for connected state
await waitForState(screen, "connected");
// Wait for streaming to finish
await waitForStream(screen, { timeout: 5000 });