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 }], },});When to use presets
Section titled “When to use presets”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.
Built-in catalog
Section titled “Built-in catalog”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 name | Kebab aliases | Transports | Intent |
|---|---|---|---|
slowNetwork | slow-api | network | Every request is delayed by 2000ms. Smoke-test loading states. |
flakyConnection | flaky-api, api-flaky | network | Rare aborts (5%) and latency (10% @ 3000ms) on every request. |
offlineMode | offline-mode | network | Block all requests like an offline browser. |
unstableApi | high-latency | network | 10% 500s and 20% latency (1000ms) scoped to /api/. |
mobileThreeG | mobile-3g | network | All requests get 1500ms latency plus 2% aborts. Approximates 3G round-trip; does not throttle bytes. |
checkoutDegraded | checkout-degraded | network | Payment instability scoped to /checkout and /api/payments - 30% latency at 800ms, occasional 503/500. |
degradedUi | ui | Disable buttons (20%) and hide links (10%). | |
unreliableWebSocket | websocket-instability | websocket | 10% drops, 500ms inbound delays, 5% truncations. |
unreliableEventStream | realtime-lag | sse | 5% drops, 200ms delays, 2% close-after-2s on every stream. |
Suggested assertions
Section titled “Suggested assertions”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/checkoutand/api/paymentsis 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/checkoutand/api/payments) under a fixedseed, then callgetChaosLog()and assert at least one event whosedetail.urlmatches/checkoutor/api/payments(any ofnetwork:latency,network:failure).unreliableWebSocket- chaos log should contain at least onewebsocket:delayevent withapplied: true.unreliableEventStream- chaos log should contain at least onesse:delayorsse:closeevent.
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.
Custom presets
Section titled “Custom presets”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.
Builder helper
Section titled “Builder helper”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.
Validation errors
Section titled “Validation errors”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, ordebug- strict-key rejection. - Empty or whitespace-only preset name (in either
presets[]orcustomPresetskeys). - 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
groupsand the user’sgroups. Workaround: copy the preset locally viacustomPresetsand rename the colliding group.
Mutability
Section titled “Mutability”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.
Profiles vs presets
Section titled “Profiles vs presets”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.
Legacy spread
Section titled “Legacy spread”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.
Sharing targeting across preset rules
Section titled “Sharing targeting across preset rules”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.