Skip to content
Latest stable: v0.8.0.

Presets

Presets are the recommended quick-start path. They wrap realistic scenarios - flaky backend, mobile-3g, degraded checkout - into named bundles you drop into a config:

import { injectChaos } from '@chaos-maker/playwright';
await injectChaos(page, {
presets: ['mobile-3g', 'checkout-degraded'],
seed: 1234,
});

Layer presets for compound scenarios (mobile network + checkout instability), or mix a preset with explicit rules when a single endpoint needs tighter control:

await injectChaos(page, {
presets: ['mobile-3g'],
network: {
failures: [{ urlPattern: '/api/checkout', statusCode: 500, probability: 1 }],
},
});

Lead with presets for onboarding, smoke coverage, and exploratory resilience tests. Drop down to explicit configs for product-critical flows where the exact status code, selector, message direction, and probability matter.

Pick presets the way engineers describe scenarios - flaky backend, bad mobile network, checkout degradation, lossy realtime. Layer multiple presets when a scenario spans transports.

camelCase nameKebab aliasesTransportsIntent
slowNetworkslow-apinetworkEvery request is delayed by 2000ms. Smoke-test loading states.
flakyConnectionflaky-api, api-flakynetworkRare aborts (5%) and latency (10% @ 3000ms) on every request.
offlineModeoffline-modenetworkBlock all requests like an offline browser.
unstableApihigh-latencynetwork10% 500s and 20% latency (1000ms) scoped to /api/.
mobileThreeGmobile-3gnetworkAll requests get 1500ms latency plus 2% aborts. Approximates 3G round-trip; does not throttle bytes.
checkoutDegradedcheckout-degradednetworkPayment instability scoped to /checkout and /api/payments - 30% latency at 800ms, occasional 503/500.
degradedUiuiDisable buttons (20%) and hide links (10%).
unreliableWebSocketwebsocket-instabilitywebsocket10% drops, 500ms inbound delays, 5% truncations.
unreliableEventStreamrealtime-lagsse5% drops, 200ms delays, 2% close-after-2s on every stream.

The presets fire deterministically given a fixed seed. Existence-check, not rate, keeps tests stable across browsers:

  • mobile-3g - observed elapsed time on a fetch should exceed 1000ms (well below the 1500ms target).
  • checkout-degraded - every rule on /checkout and /api/payments is probabilistic (30% latency, 5% / 10% failure), so a single request is not enough to assert against. Issue a small fixed batch (e.g. 20 sequential requests across /checkout and /api/payments) under a fixed seed, then call getChaosLog() and assert at least one event whose detail.url matches /checkout or /api/payments (any of network:latency, network:failure).
  • unreliableWebSocket - chaos log should contain at least one websocket:delay event with applied: true.
  • unreliableEventStream - chaos log should contain at least one sse:delay or sse:close event.

Kebab-case aliases (slow-api, flaky-api, api-flaky, offline-mode, high-latency, mobile-3g, checkout-degraded, websocket-instability, realtime-lag) are registry-only. They resolve via presets: ['mobile-3g'] and new PresetRegistry().get('mobile-3g'). They are NOT keys on the legacy presets record export - presets['mobile-3g'] is undefined by design. Use the camelCase key (presets.mobileThreeG) when reading from the record.

Register your own bundle inline via customPresets. Names collide fail-fast against built-ins and against each other.

await injectChaos(page, {
customPresets: {
'team-flow': {
network: {
failures: [{ urlPattern: '/checkout', statusCode: 503, probability: 1 }],
},
},
},
presets: ['team-flow'],
});

Custom preset values may carry only rule arrays plus the optional groups field. presets, customPresets, seed, and debug are rejected at validation. Dependency chains are out of scope.

import { ChaosConfigBuilder } from '@chaos-maker/core';
const config = new ChaosConfigBuilder()
.usePreset('slow-api')
.failRequests('/api/checkout', 500, 1)
.build();

.usePreset() silently dedupes within the builder while preserving insertion order. Empty / whitespace-only names throw, matching the schema and registry rules.

Every failure mode surfaces as a ChaosConfigError at construction time, never at runtime:

  • Unknown preset name in presets[] - message names the offending name and lists the registered ones.
  • Custom preset value carrying presets, customPresets, seed, or debug - strict-key rejection.
  • Empty or whitespace-only preset name (in either presets[] or customPresets keys).
  • Custom preset whose name collides with a built-in (slowNetwork, slow-api, etc.) or with another custom preset.
  • Group name collision between a preset’s groups and the user’s groups. Workaround: copy the preset locally via customPresets and rename the colliding group.

Built-in preset configs are deep-frozen. Attempts to mutate them via presets.slowNetwork or registry.get(...) throw in strict mode (and are no-ops in sloppy mode). Custom presets passed via customPresets are NOT frozen on input - your own preset literals stay mutable in your code. The engine takes a deep clone at expansion time, so any post-construction tweaks you make are not observed.

Presets are the primitive resilience bundles. Scenario profiles are the layer above - one named entry that composes presets, seed, debug, and rule slices into a single identifier you reach for from many tests. See the scenario profiles concept for the full surface, including the runtime override block applied at the inject site.

import { presets } from '@chaos-maker/core';
await injectChaos(page, {
...presets.unstableApi,
seed: 42,
});

Still supported for migration. The seed belongs at the root config level, so it can be added to any preset before injection. Prefer the declarative presets: field for new code.

When a preset’s rules all hit the same API surface, register the shared targeting on the top-level matchers registry and reference it from each rule with matcher: 'name'. Named matcher resolution runs after preset expansion, so rules brought in by a preset can reference top-level matchers without duplicating matcher fields.