Puppeteer
Puppeteer uses page.evaluateOnNewDocument() so network and WebSocket chaos are installed before app scripts run. Launch headless Chromium with headless: true.
npm install @chaos-maker/core @chaos-maker/puppeteerThe fastest start is a named preset - drop a scenario into the config and run:
import puppeteer from 'puppeteer';import { injectChaos } from '@chaos-maker/puppeteer';
const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();
await injectChaos(page, { presets: ['mobile-3g', 'checkout-degraded'], seed: 42 });await page.goto('http://localhost:3000/checkout');await page.waitForSelector('[data-testid="checkout-form"]');
await browser.close();See the Presets catalog for the full list. When several tests should share the same named scenario, wrap it into a scenario profile - the one built-in demo profile composes both presets above into a single name:
await injectChaos(page, { profile: 'mobile-checkout', seed: 42 });Pass profileOverrides alongside profile to tune one parameter for this call without forking the profile. When you need precise control, drop down to explicit rules:
import puppeteer from 'puppeteer';import { injectChaos, getChaosLog, removeChaos } from '@chaos-maker/puppeteer';
const browser = await puppeteer.launch({ headless: true });const page = await browser.newPage();
await injectChaos(page, { seed: 42, network: { failures: [{ urlPattern: '/api/orders', statusCode: 503, probability: 1 }], },});
await page.goto('http://localhost:3000/orders');await page.waitForSelector('[data-testid="error-state"]');
const log = await getChaosLog(page);if (!log.some((event) => event.type === 'network:failure' && event.applied)) { throw new Error('Expected chaos to apply');}
await removeChaos(page);await browser.close();Log the replay seed in the failure path:
import { formatSeedReproduction, getChaosSeed } from '@chaos-maker/puppeteer';
try { await page.waitForSelector('[data-testid="error-state"]');} catch (error) { console.error(formatSeedReproduction(await getChaosSeed(page))); throw error;}UI chaos timing
Section titled “UI chaos timing”DOM assaults need document.body. For UI chaos, load the bundle before navigation, then start the UI config after page.goto().
await injectChaos(page, {});await page.goto('http://localhost:3000/settings');await page.evaluate((config) => (window as any).chaosUtils.start(config), { seed: 42, ui: { assaults: [{ selector: 'button.save', action: 'disable', probability: 1 }] },});