@chaos-maker/playwright 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
Binary file
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # @chaos-maker/playwright
2
+
3
+ Playwright adapter for [`@chaos-maker/core`](../core/). One-line chaos injection in E2E tests.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @chaos-maker/core @chaos-maker/playwright
9
+ ```
10
+
11
+ Both packages are required — `@chaos-maker/playwright` loads the core UMD bundle into the browser page.
12
+
13
+ ## Usage
14
+
15
+ ### Direct API
16
+
17
+ ```ts
18
+ import { test, expect } from '@playwright/test';
19
+ import { injectChaos, removeChaos, getChaosLog } from '@chaos-maker/playwright';
20
+
21
+ test('shows error when API fails', async ({ page }) => {
22
+ await injectChaos(page, {
23
+ network: {
24
+ failures: [{ urlPattern: '/api/data', statusCode: 503, probability: 1.0 }]
25
+ }
26
+ });
27
+
28
+ await page.goto('/dashboard');
29
+ await expect(page.getByText('Something went wrong')).toBeVisible();
30
+
31
+ // Check what chaos was applied
32
+ const log = await getChaosLog(page);
33
+ expect(log.some(e => e.type === 'network:failure' && e.applied)).toBe(true);
34
+ });
35
+ ```
36
+
37
+ ### Test Fixture
38
+
39
+ For automatic cleanup, use the built-in fixture:
40
+
41
+ ```ts
42
+ import { test, expect } from '@chaos-maker/playwright/fixture';
43
+
44
+ test('handles slow network', async ({ page, chaos }) => {
45
+ await chaos.inject({
46
+ network: {
47
+ latencies: [{ urlPattern: '/api/', delayMs: 3000, probability: 1.0 }]
48
+ }
49
+ });
50
+
51
+ await page.goto('/');
52
+ await expect(page.getByText('Loading')).toBeVisible();
53
+
54
+ const log = await chaos.getLog();
55
+ expect(log.some(e => e.type === 'network:latency' && e.applied)).toBe(true);
56
+ });
57
+ // chaos.remove() is called automatically after each test
58
+ ```
59
+
60
+ ### With Presets
61
+
62
+ ```ts
63
+ import { test, expect } from '@playwright/test';
64
+ import { presets } from '@chaos-maker/core';
65
+ import { injectChaos } from '@chaos-maker/playwright';
66
+
67
+ test('app works offline', async ({ page }) => {
68
+ await injectChaos(page, presets.offlineMode);
69
+ await page.goto('/');
70
+ await expect(page.getByText('No connection')).toBeVisible();
71
+ });
72
+ ```
73
+
74
+ ### With Config Builder
75
+
76
+ ```ts
77
+ import { test } from '@playwright/test';
78
+ import { ChaosConfigBuilder } from '@chaos-maker/core';
79
+ import { injectChaos } from '@chaos-maker/playwright';
80
+
81
+ const config = new ChaosConfigBuilder()
82
+ .failRequests('/api/checkout', 500, 0.5)
83
+ .addLatency('/api/', 2000, 1.0)
84
+ .build();
85
+
86
+ test('checkout handles combined chaos', async ({ page }) => {
87
+ await injectChaos(page, config);
88
+ await page.goto('/checkout');
89
+ // ...
90
+ });
91
+ ```
92
+
93
+ ## API
94
+
95
+ ### `injectChaos(page, config)`
96
+
97
+ Inject chaos into a Playwright page. **Call before `page.goto()`** to ensure all network requests are intercepted from the start.
98
+
99
+ - `page` — Playwright `Page` instance
100
+ - `config` — `ChaosConfig` object (see [@chaos-maker/core](../core/) for full config reference)
101
+
102
+ ### `removeChaos(page)`
103
+
104
+ Stop chaos and restore original `fetch`/`XHR`/DOM behavior.
105
+
106
+ ### `getChaosLog(page)`
107
+
108
+ Retrieve the chaos event log from the page. Returns `ChaosEvent[]` — every chaos check emitted since injection, with `applied: true/false`.
109
+
110
+ ### Fixture: `chaos`
111
+
112
+ Available when importing `test` from `@chaos-maker/playwright/fixture`:
113
+
114
+ - `chaos.inject(config)` — same as `injectChaos(page, config)`
115
+ - `chaos.remove()` — same as `removeChaos(page)` (also called automatically after each test)
116
+ - `chaos.getLog()` — same as `getChaosLog(page)`
117
+
118
+ ## License
119
+
120
+ [MIT](../../LICENSE)
@@ -0,0 +1,45 @@
1
+ // src/index.ts
2
+ import { resolve, dirname } from "path";
3
+ import { createRequire } from "module";
4
+ import { fileURLToPath } from "url";
5
+ var cachedUmdPath = null;
6
+ function getCoreUmdPath() {
7
+ if (cachedUmdPath) return cachedUmdPath;
8
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
9
+ const req = createRequire(resolve(currentDir, "package.json"));
10
+ const coreEntry = req.resolve("@chaos-maker/core");
11
+ const coreDistDir = dirname(coreEntry);
12
+ cachedUmdPath = resolve(coreDistDir, "chaos-maker.umd.js");
13
+ return cachedUmdPath;
14
+ }
15
+ async function injectChaos(page, config) {
16
+ const umdPath = getCoreUmdPath();
17
+ await page.addInitScript((cfg) => {
18
+ const win = globalThis;
19
+ win.__CHAOS_CONFIG__ = cfg;
20
+ }, config);
21
+ await page.addInitScript({ path: umdPath });
22
+ }
23
+ async function removeChaos(page) {
24
+ await page.evaluate(() => {
25
+ const win = globalThis;
26
+ if (win.chaosUtils) {
27
+ win.chaosUtils.stop();
28
+ }
29
+ });
30
+ }
31
+ async function getChaosLog(page) {
32
+ return page.evaluate(() => {
33
+ const win = globalThis;
34
+ if (win.chaosUtils) {
35
+ return win.chaosUtils.getLog();
36
+ }
37
+ return [];
38
+ });
39
+ }
40
+
41
+ export {
42
+ injectChaos,
43
+ removeChaos,
44
+ getChaosLog
45
+ };
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/fixture.ts
21
+ var fixture_exports = {};
22
+ __export(fixture_exports, {
23
+ expect: () => import_test2.expect,
24
+ test: () => test
25
+ });
26
+ module.exports = __toCommonJS(fixture_exports);
27
+ var import_test = require("@playwright/test");
28
+
29
+ // src/index.ts
30
+ var import_path = require("path");
31
+ var import_module = require("module");
32
+ var import_url = require("url");
33
+ var import_meta = {};
34
+ var cachedUmdPath = null;
35
+ function getCoreUmdPath() {
36
+ if (cachedUmdPath) return cachedUmdPath;
37
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
38
+ const req = (0, import_module.createRequire)((0, import_path.resolve)(currentDir, "package.json"));
39
+ const coreEntry = req.resolve("@chaos-maker/core");
40
+ const coreDistDir = (0, import_path.dirname)(coreEntry);
41
+ cachedUmdPath = (0, import_path.resolve)(coreDistDir, "chaos-maker.umd.js");
42
+ return cachedUmdPath;
43
+ }
44
+ async function injectChaos(page, config) {
45
+ const umdPath = getCoreUmdPath();
46
+ await page.addInitScript((cfg) => {
47
+ const win = globalThis;
48
+ win.__CHAOS_CONFIG__ = cfg;
49
+ }, config);
50
+ await page.addInitScript({ path: umdPath });
51
+ }
52
+ async function removeChaos(page) {
53
+ await page.evaluate(() => {
54
+ const win = globalThis;
55
+ if (win.chaosUtils) {
56
+ win.chaosUtils.stop();
57
+ }
58
+ });
59
+ }
60
+ async function getChaosLog(page) {
61
+ return page.evaluate(() => {
62
+ const win = globalThis;
63
+ if (win.chaosUtils) {
64
+ return win.chaosUtils.getLog();
65
+ }
66
+ return [];
67
+ });
68
+ }
69
+
70
+ // src/fixture.ts
71
+ var import_test2 = require("@playwright/test");
72
+ var test = import_test.test.extend({
73
+ chaos: async ({ page }, use) => {
74
+ const fixture = {
75
+ inject: (config) => injectChaos(page, config),
76
+ remove: () => removeChaos(page),
77
+ getLog: () => getChaosLog(page)
78
+ };
79
+ await use(fixture);
80
+ await removeChaos(page);
81
+ }
82
+ });
83
+ // Annotate the CommonJS export names for ESM import in node:
84
+ 0 && (module.exports = {
85
+ expect,
86
+ test
87
+ });
@@ -0,0 +1,34 @@
1
+ import * as _playwright_test from '@playwright/test';
2
+ export { expect } from '@playwright/test';
3
+ import { ChaosConfig, ChaosEvent } from '@chaos-maker/core';
4
+ export { ChaosConfig, ChaosEvent } from '@chaos-maker/core';
5
+
6
+ interface ChaosFixture {
7
+ inject: (config: ChaosConfig) => Promise<void>;
8
+ remove: () => Promise<void>;
9
+ getLog: () => Promise<ChaosEvent[]>;
10
+ }
11
+ /**
12
+ * Extended Playwright test with a `chaos` fixture.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { test, expect } from '@chaos-maker/playwright/fixture';
17
+ *
18
+ * test('handles API failure', async ({ page, chaos }) => {
19
+ * await chaos.inject({
20
+ * network: {
21
+ * failures: [{ urlPattern: '/api', statusCode: 503, probability: 1.0 }]
22
+ * }
23
+ * });
24
+ * await page.goto('/');
25
+ * const log = await chaos.getLog();
26
+ * expect(log.some(e => e.type === 'network:failure' && e.applied)).toBe(true);
27
+ * });
28
+ * ```
29
+ */
30
+ declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
31
+ chaos: ChaosFixture;
32
+ }, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
33
+
34
+ export { type ChaosFixture, test };
@@ -0,0 +1,34 @@
1
+ import * as _playwright_test from '@playwright/test';
2
+ export { expect } from '@playwright/test';
3
+ import { ChaosConfig, ChaosEvent } from '@chaos-maker/core';
4
+ export { ChaosConfig, ChaosEvent } from '@chaos-maker/core';
5
+
6
+ interface ChaosFixture {
7
+ inject: (config: ChaosConfig) => Promise<void>;
8
+ remove: () => Promise<void>;
9
+ getLog: () => Promise<ChaosEvent[]>;
10
+ }
11
+ /**
12
+ * Extended Playwright test with a `chaos` fixture.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { test, expect } from '@chaos-maker/playwright/fixture';
17
+ *
18
+ * test('handles API failure', async ({ page, chaos }) => {
19
+ * await chaos.inject({
20
+ * network: {
21
+ * failures: [{ urlPattern: '/api', statusCode: 503, probability: 1.0 }]
22
+ * }
23
+ * });
24
+ * await page.goto('/');
25
+ * const log = await chaos.getLog();
26
+ * expect(log.some(e => e.type === 'network:failure' && e.applied)).toBe(true);
27
+ * });
28
+ * ```
29
+ */
30
+ declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & {
31
+ chaos: ChaosFixture;
32
+ }, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions>;
33
+
34
+ export { type ChaosFixture, test };
@@ -0,0 +1,24 @@
1
+ import {
2
+ getChaosLog,
3
+ injectChaos,
4
+ removeChaos
5
+ } from "./chunk-BZSMGQHL.js";
6
+
7
+ // src/fixture.ts
8
+ import { test as base } from "@playwright/test";
9
+ import { expect } from "@playwright/test";
10
+ var test = base.extend({
11
+ chaos: async ({ page }, use) => {
12
+ const fixture = {
13
+ inject: (config) => injectChaos(page, config),
14
+ remove: () => removeChaos(page),
15
+ getLog: () => getChaosLog(page)
16
+ };
17
+ await use(fixture);
18
+ await removeChaos(page);
19
+ }
20
+ });
21
+ export {
22
+ expect,
23
+ test
24
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ getChaosLog: () => getChaosLog,
24
+ injectChaos: () => injectChaos,
25
+ removeChaos: () => removeChaos
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ var import_path = require("path");
29
+ var import_module = require("module");
30
+ var import_url = require("url");
31
+ var import_meta = {};
32
+ var cachedUmdPath = null;
33
+ function getCoreUmdPath() {
34
+ if (cachedUmdPath) return cachedUmdPath;
35
+ const currentDir = typeof __dirname !== "undefined" ? __dirname : (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
36
+ const req = (0, import_module.createRequire)((0, import_path.resolve)(currentDir, "package.json"));
37
+ const coreEntry = req.resolve("@chaos-maker/core");
38
+ const coreDistDir = (0, import_path.dirname)(coreEntry);
39
+ cachedUmdPath = (0, import_path.resolve)(coreDistDir, "chaos-maker.umd.js");
40
+ return cachedUmdPath;
41
+ }
42
+ async function injectChaos(page, config) {
43
+ const umdPath = getCoreUmdPath();
44
+ await page.addInitScript((cfg) => {
45
+ const win = globalThis;
46
+ win.__CHAOS_CONFIG__ = cfg;
47
+ }, config);
48
+ await page.addInitScript({ path: umdPath });
49
+ }
50
+ async function removeChaos(page) {
51
+ await page.evaluate(() => {
52
+ const win = globalThis;
53
+ if (win.chaosUtils) {
54
+ win.chaosUtils.stop();
55
+ }
56
+ });
57
+ }
58
+ async function getChaosLog(page) {
59
+ return page.evaluate(() => {
60
+ const win = globalThis;
61
+ if (win.chaosUtils) {
62
+ return win.chaosUtils.getLog();
63
+ }
64
+ return [];
65
+ });
66
+ }
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ getChaosLog,
70
+ injectChaos,
71
+ removeChaos
72
+ });
@@ -0,0 +1,34 @@
1
+ import { Page } from '@playwright/test';
2
+ import { ChaosEvent, ChaosConfig } from '@chaos-maker/core';
3
+ export { ChaosConfig, ChaosEvent } from '@chaos-maker/core';
4
+
5
+ /**
6
+ * Inject chaos into a Playwright page. Call before `page.goto()` to ensure
7
+ * all network requests are intercepted from the start.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { injectChaos } from '@chaos-maker/playwright';
12
+ *
13
+ * test('handles API failure', async ({ page }) => {
14
+ * await injectChaos(page, {
15
+ * network: {
16
+ * failures: [{ urlPattern: '/api', statusCode: 503, probability: 1.0 }]
17
+ * }
18
+ * });
19
+ * await page.goto('/');
20
+ * });
21
+ * ```
22
+ */
23
+ declare function injectChaos(page: Page, config: ChaosConfig): Promise<void>;
24
+ /**
25
+ * Remove chaos from a Playwright page. Restores original fetch/XHR/DOM behavior.
26
+ */
27
+ declare function removeChaos(page: Page): Promise<void>;
28
+ /**
29
+ * Retrieve the chaos event log from a Playwright page.
30
+ * Returns all events emitted since chaos was injected.
31
+ */
32
+ declare function getChaosLog(page: Page): Promise<ChaosEvent[]>;
33
+
34
+ export { getChaosLog, injectChaos, removeChaos };
@@ -0,0 +1,34 @@
1
+ import { Page } from '@playwright/test';
2
+ import { ChaosEvent, ChaosConfig } from '@chaos-maker/core';
3
+ export { ChaosConfig, ChaosEvent } from '@chaos-maker/core';
4
+
5
+ /**
6
+ * Inject chaos into a Playwright page. Call before `page.goto()` to ensure
7
+ * all network requests are intercepted from the start.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { injectChaos } from '@chaos-maker/playwright';
12
+ *
13
+ * test('handles API failure', async ({ page }) => {
14
+ * await injectChaos(page, {
15
+ * network: {
16
+ * failures: [{ urlPattern: '/api', statusCode: 503, probability: 1.0 }]
17
+ * }
18
+ * });
19
+ * await page.goto('/');
20
+ * });
21
+ * ```
22
+ */
23
+ declare function injectChaos(page: Page, config: ChaosConfig): Promise<void>;
24
+ /**
25
+ * Remove chaos from a Playwright page. Restores original fetch/XHR/DOM behavior.
26
+ */
27
+ declare function removeChaos(page: Page): Promise<void>;
28
+ /**
29
+ * Retrieve the chaos event log from a Playwright page.
30
+ * Returns all events emitted since chaos was injected.
31
+ */
32
+ declare function getChaosLog(page: Page): Promise<ChaosEvent[]>;
33
+
34
+ export { getChaosLog, injectChaos, removeChaos };
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import {
2
+ getChaosLog,
3
+ injectChaos,
4
+ removeChaos
5
+ } from "./chunk-BZSMGQHL.js";
6
+ export {
7
+ getChaosLog,
8
+ injectChaos,
9
+ removeChaos
10
+ };
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@chaos-maker/playwright",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Playwright adapter for @chaos-maker/core — one-line chaos injection in E2E tests",
6
+ "keywords": [
7
+ "chaos-engineering",
8
+ "playwright",
9
+ "testing",
10
+ "e2e-testing",
11
+ "resilience"
12
+ ],
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/jvjithin/chaos-maker.git",
17
+ "directory": "packages/playwright"
18
+ },
19
+ "homepage": "https://github.com/jvjithin/chaos-maker",
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "main": "./dist/index.cjs",
24
+ "module": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "import": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "require": {
33
+ "types": "./dist/index.d.ts",
34
+ "default": "./dist/index.cjs"
35
+ }
36
+ },
37
+ "./fixture": {
38
+ "import": {
39
+ "types": "./dist/fixture.d.ts",
40
+ "default": "./dist/fixture.js"
41
+ },
42
+ "require": {
43
+ "types": "./dist/fixture.d.ts",
44
+ "default": "./dist/fixture.cjs"
45
+ }
46
+ }
47
+ },
48
+ "files": [
49
+ "dist"
50
+ ],
51
+ "dependencies": {
52
+ "@chaos-maker/core": "0.1.0"
53
+ },
54
+ "peerDependencies": {
55
+ "@playwright/test": ">=1.40.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "@playwright/test": {
59
+ "optional": false
60
+ }
61
+ },
62
+ "devDependencies": {
63
+ "@playwright/test": "^1.45.0",
64
+ "tsup": "^8.0.0",
65
+ "typescript": "^5.4.5",
66
+ "vitest": "^1.6.0"
67
+ },
68
+ "scripts": {
69
+ "build": "tsup",
70
+ "test": "vitest"
71
+ }
72
+ }