Advanced Usage
Laika exposes a few capabilities that are easy to miss if you only start from the basic intercept(...).mockResult(...) flow.
Match more precisely
Interceptors can match on:
operationNameoperationvariablesclientNamefeature- a custom matcher function
const interceptor = laika.intercept({
clientName: 'support-web',
feature: 'ticket-sidebar',
operationName: 'GetTicket',
variables: { id: '123' },
})
If another link tags the operation context with feature, you can use that to scope logging and mocking more narrowly.
Every interceptor also records its matched variables in interceptor.calls, similar to jest.fn().mock.calls.
Queue responses and choose how long they live
Use mockResultOnce() when a response should be consumed a limited number of times:
const interceptor = laika.intercept({ operationName: 'GetUsers' })
interceptor
.mockResultOnce({ result: { data: { users: [{ id: '1' }] } } })
.mockResultOnce({ result: { data: { users: [{ id: '2' }] } } })
.mockResult({ result: { data: { users: [] } } })
Use:
mockReset()to clear the current mock configuration but keep the interceptor registeredmockRestore()to remove just that interceptormockRestoreAll()to remove every interceptor created by theLaikainstance
Wait for subscriptions and mount events
You can wait for the next matching operation:
const interceptor = laika.intercept({ operationName: 'GetUsers' })
await interceptor.waitForNextSubscription()
Or attach a lifecycle callback:
const interceptor = laika.intercept({ operationName: 'GetUsers' })
interceptor.onSubscribe(({ operation, observer }) => {
if (operation.variables.preview) {
observer.next?.({
data: {
users: [],
},
})
observer.complete?.()
}
})
Return a cleanup function from onSubscribe() if the interceptor needs to dispose any test-local state when the observer disconnects.
Turn off network fallback
By default, unmatched queries and mutations can still fall through to the next Apollo link. If you want a request to stay in a loading state until your test explicitly responds, disable that fallback:
const interceptor = laika.intercept({ operationName: 'GetUsers' })
interceptor.disableNetworkFallback()
interceptor.onSubscribe(({ observer }) => {
observer.next?.({
data: {
users: [{ id: '1', name: 'Mouse' }],
},
})
observer.complete?.()
})
Use allowNetworkFallback() to restore the default passthrough behavior.
Modify real backend responses without fully mocking them
modifyRemote() is the higher-level API for the "let the request go through, then adjust the result" pattern:
laika.modifyRemote({ operationName: 'GetTicket' }, (result) => ({
...result,
data: {
...result.data,
injectedByLaika: true,
},
}))
This is useful for fuzzing edge cases while still exercising the real backend response shape.
Customize the global singleton
createGlobalLaikaLink() and createLazyLoadableLaikaLink() support a few options that are easy to overlook:
createLazyLoadableLaikaLink({
clientName: 'support-web',
globalPropertyName: 'supportLaika',
startLoggingImmediately: true,
onLaikaReady: (laika) => {
laika.log.startRecording('opening a ticket')
},
})
This changes the singleton name from window.laika to window.supportLaika.
Browser tests can hook into the same lifecycle with:
window.supportLaikaReadyCallbacks = window.supportLaikaReadyCallbacks ?? []
window.supportLaikaReadyCallbacks.push((laika) => {
laika.intercept({ operationName: 'GetTicket' })
})
See Usage in Playwright and Usage in Cypress for the browser-runner patterns built on top of that hook.