Skip to main content

Transport simulation

Each Laika instance owns transport simulation for its link. Configure laika.transport, then use the normal laika.createLink() path; no second Apollo link or controller needs to be composed into the chain.

import { ApolloLink } from '@apollo/client/core'
import { Laika } from '@zendesk/laika/esm/laika'

const laika = new Laika()
laika.transport.set({
mode: 'targeted',
rules: [
{
matcher: { operationName: 'GetProfile' },
latencyMs: 500,
},
],
})

const link = ApolloLink.from([laika.createLink(), terminatingLink])

Laika observes every operation first. Its usual interception and mocking behavior runs next; when an operation is passed through, simulation runs immediately before the following transport link. Mocked responses are not simulated as transport requests. Use delay on a mocked result when that is the behavior you need to test.

Targeted simulation​

Targeted rules use Laika's normal Matcher, so they can scope effects by operation name, client, feature, variables, document, or a matcher function. The first matching rule supplies both the delay and optional failure.

laika.transport.set({
mode: 'targeted',
rules: [
{
matcher: {
clientName: 'support-web',
operationName: 'GetTicket',
},
latencyMs: 500,
},
{
matcher: { operationName: 'UpdateTicket' },
failure: {
kind: 'graphql',
message: 'Ticket updates are unavailable',
},
},
],
})

Use kind: 'network' to fail through Apollo's error path. A GraphQL failure emits { data: null, errors } and does not call the following link.

Chaos simulation​

Chaos applies a randomized delay and independently samples the error probability for every matching passthrough operation.

laika.transport.set({
mode: 'chaos',
matcher: { clientName: 'support-web' },
latency: { minMs: 100, maxMs: 600 },
errorProbability: 20,
})

Chaos skips subscriptions by default because they are long-lived. Enable them only when testing subscription startup or reconnect behavior:

laika.transport.set({
mode: 'chaos',
latency: { minMs: 100, maxMs: 600 },
errorProbability: 20,
includeSubscriptions: true,
})

Pass undefined to disable transport simulation for future passthrough operations:

laika.transport.set(undefined)

Diagnostics​

snapshot() provides the configuration, first-seen operations, and a bounded history of decisions. A consumer-owned DevTools panel can subscribe and render that snapshot without becoming part of the request path.

const unsubscribe = laika.transport.subscribe(() => {
const { operations, decisions } = laika.transport.snapshot()
renderOperationPicker(operations)
renderSimulationLog(decisions)
})

unsubscribe()

Listener failures are ignored so a broken panel cannot break an Apollo operation.

onLaikaReady configures the same instance-owned controls when using the global link:

import { createGlobalLaikaLink } from '@zendesk/laika/createGlobalLaikaLink'

createGlobalLaikaLink({
clientName: 'support-web',
onLaikaReady: (laika) => {
laika.transport.set({
mode: 'chaos',
latency: { minMs: 100, maxMs: 600 },
errorProbability: 20,
})
},
})

See the generated transport API for the complete public contract.