@testivai/witness-webdriverio 0.1.1

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
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 TestivAI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # @testivai/witness-webdriverio
2
+
3
+ WebdriverIO adapter for [TestivAI Witness](https://github.com/mcbuddy/testivai-oss) — local-first visual regression testing with pixel + DOM comparison. No account required.
4
+
5
+ Pairs with `@testivai/witness` (the local CLI + diff engine + HTML report) and shares the `.testivai/baselines/` layout used by `@testivai/witness-playwright`. Switching between Playwright and WebdriverIO produces the same baselines, the same report, and the same approval workflow.
6
+
7
+ ## Why an adapter and not the `testivai run` sidecar?
8
+
9
+ The framework-agnostic `testivai run` mode launches your test process and attaches to Chrome via CDP. That works but is brittle: framework-specific Chrome launch flags, target selection across iframes, signal handling. This adapter sidesteps all of that by using WebdriverIO's native `browser.takeScreenshot()` + `browser.execute()`. No port polling, no race conditions.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install -D @testivai/witness @testivai/witness-webdriverio
15
+ ```
16
+
17
+ `webdriverio@>=8` is a peer dependency (you should already have it).
18
+
19
+ ## Quick start
20
+
21
+ ### 1. Tell TestivAI to run in local mode
22
+
23
+ Create `.testivai/config.json` at your project root:
24
+
25
+ ```json
26
+ {
27
+ "mode": "local",
28
+ "threshold": 0.1,
29
+ "reportDir": "visual-report",
30
+ "autoOpen": false
31
+ }
32
+ ```
33
+
34
+ This file is the local-mode marker. Without it, the adapter logs a warning and skips report generation (cloud mode upload is not yet implemented for WDIO).
35
+
36
+ ### 2. Register the service in `wdio.conf.ts`
37
+
38
+ ```ts
39
+ import { TestivaiService } from '@testivai/witness-webdriverio/service';
40
+
41
+ export const config = {
42
+ // ...
43
+ services: [
44
+ [TestivaiService, { quiet: false }],
45
+ ],
46
+ };
47
+ ```
48
+
49
+ The service runs after all tests complete. It reads `.testivai/temp/` (where `witness()` wrote captures), diffs against `.testivai/baselines/`, and produces `visual-report/` with `index.html` + `results.json`.
50
+
51
+ ### 3. Capture inside your tests
52
+
53
+ ```ts
54
+ import { testivai } from '@testivai/witness-webdriverio';
55
+
56
+ describe('Homepage', () => {
57
+ it('looks correct', async () => {
58
+ await browser.url('https://example.com');
59
+ await testivai.witness(browser, 'homepage');
60
+ });
61
+
62
+ it('checkout flow first step', async () => {
63
+ await browser.url('https://example.com/checkout');
64
+ await testivai.witness(browser, 'checkout-step-1');
65
+ });
66
+ });
67
+ ```
68
+
69
+ ### 4. Run
70
+
71
+ ```bash
72
+ npx wdio run wdio.conf.ts
73
+ ```
74
+
75
+ - **First run**: baselines are written to `.testivai/baselines/<name>/`. Commit them with `git add .testivai/baselines`.
76
+ - **Later runs**: screenshots are diffed and a self-contained HTML report is written to `./visual-report/`.
77
+
78
+ ## Approving changes
79
+
80
+ When the report shows changed snapshots:
81
+
82
+ ```bash
83
+ # Review them in visual-report/index.html
84
+ open visual-report/index.html
85
+
86
+ # Approve a single snapshot
87
+ npx testivai approve "homepage"
88
+
89
+ # Approve everything that changed
90
+ npx testivai approve --all
91
+ ```
92
+
93
+ Approve writes the temp capture over the baseline and backs the previous baseline up to `.testivai/baselines/<name>/.previous/`. `npx testivai approve --undo "homepage"` reverts.
94
+
95
+ ## DOM noise hint
96
+
97
+ When pixels differ but the page DOM is structurally identical, the report flags the change as "likely render noise" (anti-aliasing, font hinting, sub-pixel layout). When the DOM is also different, the report shows added / removed / attribute-change counts so you can decide whether the change is intentional. Same signal as the Playwright adapter — both write `dom.html` alongside the screenshot.
98
+
99
+ DOM capture happens automatically. To skip it for a single snapshot:
100
+
101
+ ```ts
102
+ await testivai.witness(browser, 'no-dom', { skipDom: true });
103
+ ```
104
+
105
+ ## API
106
+
107
+ ### `testivai.witness(browser, name, options?)`
108
+
109
+ Captures a screenshot + DOM and writes them as a temp snapshot.
110
+
111
+ | Param | Type | Description |
112
+ |---|---|---|
113
+ | `browser` | WebdriverIO browser | Must expose `takeScreenshot()` and (for DOM) `execute()`. |
114
+ | `name` | string | Snapshot name. Becomes `.testivai/temp/<name>/` and the key in the report. |
115
+ | `options.skipDom` | boolean | Skip DOM capture for this snapshot. |
116
+
117
+ ### `TestivaiService`
118
+
119
+ Class registered as a WDIO service. Implements `onComplete`.
120
+
121
+ | Option | Type | Default | Description |
122
+ |---|---|---|---|
123
+ | `projectRoot` | string | `process.cwd()` | Project root for the test run. |
124
+ | `reportDir` | string | local config (`visual-report`) | Override the report directory. |
125
+ | `threshold` | number | local config (`0.1`) | Diff threshold (0–1). |
126
+ | `autoOpen` | boolean | `false` | Auto-open the report in a browser. |
127
+ | `quiet` | boolean | `false` | Suppress all logging except errors. |
128
+
129
+ ## Status
130
+
131
+ - **Local mode**: stable
132
+ - **Cloud mode** (upload to TestivAI hosted): not yet implemented in this adapter — coming in a later iteration. The Playwright adapter has both lanes today; the WDIO adapter will follow once local is broadly used.
133
+
134
+ ## Links
135
+
136
+ - Repo: https://github.com/mcbuddy/testivai-oss
137
+ - Plan: see `docs/OSS_PLAN_V3.md` in `mcbuddy/testivai-monorepo`
138
+ - Issues: https://github.com/mcbuddy/testivai-oss/issues
139
+
140
+ ## License
141
+
142
+ MIT
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @testivai/witness-webdriverio
3
+ *
4
+ * WebdriverIO adapter for the TestivAI Witness OSS toolkit. Pairs with
5
+ * `@testivai/witness` (the local CLI + diff engine) and shares the same
6
+ * `.testivai/baselines/` layout as `@testivai/witness-playwright`.
7
+ *
8
+ * import { testivai } from '@testivai/witness-webdriverio';
9
+ * import { TestivaiService } from '@testivai/witness-webdriverio/service';
10
+ */
11
+ import { witness } from './witness';
12
+ export { witness } from './witness';
13
+ export { TestivaiService, default as DefaultTestivaiService } from './service';
14
+ export type { WitnessBrowser, WitnessOptions, TestivaiServiceOptions } from './types';
15
+ /**
16
+ * Convenience namespace mirroring @testivai/witness-playwright's API:
17
+ *
18
+ * await testivai.witness(browser, 'homepage');
19
+ */
20
+ export declare const testivai: {
21
+ witness: typeof witness;
22
+ };
23
+ export declare const VERSION: string;
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * @testivai/witness-webdriverio
4
+ *
5
+ * WebdriverIO adapter for the TestivAI Witness OSS toolkit. Pairs with
6
+ * `@testivai/witness` (the local CLI + diff engine) and shares the same
7
+ * `.testivai/baselines/` layout as `@testivai/witness-playwright`.
8
+ *
9
+ * import { testivai } from '@testivai/witness-webdriverio';
10
+ * import { TestivaiService } from '@testivai/witness-webdriverio/service';
11
+ */
12
+ var __importDefault = (this && this.__importDefault) || function (mod) {
13
+ return (mod && mod.__esModule) ? mod : { "default": mod };
14
+ };
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.VERSION = exports.testivai = exports.DefaultTestivaiService = exports.TestivaiService = exports.witness = void 0;
17
+ const witness_1 = require("./witness");
18
+ var witness_2 = require("./witness");
19
+ Object.defineProperty(exports, "witness", { enumerable: true, get: function () { return witness_2.witness; } });
20
+ var service_1 = require("./service");
21
+ Object.defineProperty(exports, "TestivaiService", { enumerable: true, get: function () { return service_1.TestivaiService; } });
22
+ Object.defineProperty(exports, "DefaultTestivaiService", { enumerable: true, get: function () { return __importDefault(service_1).default; } });
23
+ /**
24
+ * Convenience namespace mirroring @testivai/witness-playwright's API:
25
+ *
26
+ * await testivai.witness(browser, 'homepage');
27
+ */
28
+ exports.testivai = {
29
+ witness: witness_1.witness,
30
+ };
31
+ exports.VERSION = require('../package.json').version;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @testivai/witness-webdriverio — WDIO service
3
+ *
4
+ * Registered in wdio.conf.ts so the report is generated automatically
5
+ * after the test suite finishes:
6
+ *
7
+ * import { TestivaiService } from '@testivai/witness-webdriverio/service';
8
+ *
9
+ * export const config = {
10
+ * services: [[TestivaiService, { quiet: false }]],
11
+ * // ...
12
+ * };
13
+ *
14
+ * The service does ONE thing in `onComplete`: detect local mode, then
15
+ * call `generateReport()` from @testivai/witness/report. There is no
16
+ * cloud upload path in this iteration — the OSS goal is standalone-
17
+ * complete local mode. If a future cloud upload is added, it slots in
18
+ * here without changing the witness() capture function.
19
+ */
20
+ import type { TestivaiServiceOptions } from './types';
21
+ export declare class TestivaiService {
22
+ private readonly options;
23
+ constructor(serviceOptions?: TestivaiServiceOptions);
24
+ /**
25
+ * WebdriverIO calls onComplete after all worker processes finish.
26
+ * Signature is intentionally loose — we only consume the parts we need
27
+ * and remain forward-compatible with WDIO 8 and 9.
28
+ */
29
+ onComplete(_exitCode?: number, _config?: unknown, _capabilities?: unknown, _results?: unknown): Promise<void>;
30
+ }
31
+ /**
32
+ * Default export so consumers can use the WDIO services-by-class form
33
+ * directly: `services: [TestivaiService]`. The class form is also
34
+ * compatible with the tuple form for passing options.
35
+ */
36
+ export default TestivaiService;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /**
3
+ * @testivai/witness-webdriverio — WDIO service
4
+ *
5
+ * Registered in wdio.conf.ts so the report is generated automatically
6
+ * after the test suite finishes:
7
+ *
8
+ * import { TestivaiService } from '@testivai/witness-webdriverio/service';
9
+ *
10
+ * export const config = {
11
+ * services: [[TestivaiService, { quiet: false }]],
12
+ * // ...
13
+ * };
14
+ *
15
+ * The service does ONE thing in `onComplete`: detect local mode, then
16
+ * call `generateReport()` from @testivai/witness/report. There is no
17
+ * cloud upload path in this iteration — the OSS goal is standalone-
18
+ * complete local mode. If a future cloud upload is added, it slots in
19
+ * here without changing the witness() capture function.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.TestivaiService = void 0;
23
+ const witness_1 = require("@testivai/witness");
24
+ class TestivaiService {
25
+ constructor(serviceOptions = {}) {
26
+ this.options = serviceOptions;
27
+ }
28
+ /**
29
+ * WebdriverIO calls onComplete after all worker processes finish.
30
+ * Signature is intentionally loose — we only consume the parts we need
31
+ * and remain forward-compatible with WDIO 8 and 9.
32
+ */
33
+ async onComplete(_exitCode, _config, _capabilities, _results) {
34
+ const projectRoot = this.options.projectRoot ?? process.cwd();
35
+ const log = (msg) => {
36
+ if (!this.options.quiet) {
37
+ // eslint-disable-next-line no-console
38
+ console.log(`[testivai] ${msg}`);
39
+ }
40
+ };
41
+ if (!(0, witness_1.isLocalMode)(projectRoot)) {
42
+ log('Cloud mode is not yet supported by @testivai/witness-webdriverio — skipping report generation. ' +
43
+ 'To enable local mode, create .testivai/config.json with {"mode":"local"}.');
44
+ return;
45
+ }
46
+ try {
47
+ const reportData = (0, witness_1.generateReport)({
48
+ projectRoot,
49
+ reportDir: this.options.reportDir,
50
+ threshold: this.options.threshold,
51
+ autoOpen: this.options.autoOpen ?? false,
52
+ });
53
+ const { summary } = reportData;
54
+ log(`Visual report: total=${summary.total} passed=${summary.passed} ` +
55
+ `changed=${summary.changed} new=${summary.newSnapshots}`);
56
+ if (summary.changed > 0 || summary.newSnapshots > 0) {
57
+ log('To approve: npx testivai approve --all');
58
+ }
59
+ }
60
+ catch (err) {
61
+ // Reporting failure must not crash the WDIO run after all tests
62
+ // already passed. Log and exit cleanly.
63
+ // eslint-disable-next-line no-console
64
+ console.error('[testivai] Failed to generate visual report:', err);
65
+ }
66
+ }
67
+ }
68
+ exports.TestivaiService = TestivaiService;
69
+ /**
70
+ * Default export so consumers can use the WDIO services-by-class form
71
+ * directly: `services: [TestivaiService]`. The class form is also
72
+ * compatible with the tuple form for passing options.
73
+ */
74
+ exports.default = TestivaiService;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Public types for @testivai/witness-webdriverio.
3
+ */
4
+ /**
5
+ * Minimal subset of the WebdriverIO `browser` object the witness function
6
+ * relies on. Defining a structural type here means consumers can pass any
7
+ * WDIO-shaped object (sync or async, real or mocked) without us pulling
8
+ * `webdriverio`'s heavy global type into our public surface.
9
+ */
10
+ export interface WitnessBrowser {
11
+ /**
12
+ * Capture a full-page screenshot of the active session. Returns a base64
13
+ * PNG, matching the WebdriverIO `browser.takeScreenshot()` return shape.
14
+ */
15
+ takeScreenshot(): Promise<string>;
16
+ /**
17
+ * Execute a script in the page context. We only use the no-arg form.
18
+ * Type kept loose to accept WDIO 8/9 signature variants.
19
+ */
20
+ execute<T = unknown>(script: string | ((...args: any[]) => T), ...args: any[]): Promise<T>;
21
+ }
22
+ /**
23
+ * Options for a single witness() call. All optional.
24
+ */
25
+ export interface WitnessOptions {
26
+ /**
27
+ * Skip DOM capture even if the adapter would normally write dom.html
28
+ * alongside the screenshot. Use for pages where DOM serialization is
29
+ * known to be expensive or unstable.
30
+ */
31
+ skipDom?: boolean;
32
+ }
33
+ /**
34
+ * Configuration passed to the WDIO service.
35
+ *
36
+ * Local mode is detected automatically from `.testivai/config.json` —
37
+ * these options exist only to override the defaults that
38
+ * generateReport() picks up from that file.
39
+ */
40
+ export interface TestivaiServiceOptions {
41
+ /** Project root for the test run. Defaults to `process.cwd()`. */
42
+ projectRoot?: string;
43
+ /** Override the report directory. Defaults to local config (`visual-report`). */
44
+ reportDir?: string;
45
+ /** Override the diff threshold (0–1). Defaults to local config (0.1). */
46
+ threshold?: number;
47
+ /** Auto-open the rendered report in a browser. Defaults to local config. */
48
+ autoOpen?: boolean;
49
+ /** Suppress all adapter logging except errors. */
50
+ quiet?: boolean;
51
+ }
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * Public types for @testivai/witness-webdriverio.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @testivai/witness-webdriverio — capture function
3
+ *
4
+ * The user-facing call inside a WebdriverIO test:
5
+ *
6
+ * import { testivai } from '@testivai/witness-webdriverio';
7
+ * await testivai.witness(browser, 'homepage');
8
+ *
9
+ * Captures a full-page screenshot via `browser.takeScreenshot()` and the
10
+ * page DOM via `browser.execute(() => document.documentElement.outerHTML)`,
11
+ * then writes both into `.testivai/temp/<name>/` using the same
12
+ * BaselineStore layout as @testivai/witness-playwright. The TestivaiService
13
+ * (registered in wdio.conf.ts) runs `compareAll` + `generateReport` after
14
+ * all tests finish.
15
+ *
16
+ * Architectural choice: we rely on WebdriverIO's native `takeScreenshot`
17
+ * and `execute` APIs rather than opening a CDP session. This is the whole
18
+ * point of the per-framework adapter — using the framework's stable public
19
+ * API instead of fighting Chrome-launch coordination.
20
+ */
21
+ import type { WitnessBrowser, WitnessOptions } from './types';
22
+ /**
23
+ * Capture a screenshot + DOM and write them as a temp snapshot.
24
+ *
25
+ * @param browser WebdriverIO browser-like object (must expose
26
+ * `takeScreenshot()` and `execute()`).
27
+ * @param name Snapshot name. Becomes the directory under
28
+ * `.testivai/temp/<name>/` and the key in the rendered report.
29
+ * @param options Per-call overrides.
30
+ */
31
+ export declare function witness(browser: WitnessBrowser, name: string, options?: WitnessOptions): Promise<void>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * @testivai/witness-webdriverio — capture function
4
+ *
5
+ * The user-facing call inside a WebdriverIO test:
6
+ *
7
+ * import { testivai } from '@testivai/witness-webdriverio';
8
+ * await testivai.witness(browser, 'homepage');
9
+ *
10
+ * Captures a full-page screenshot via `browser.takeScreenshot()` and the
11
+ * page DOM via `browser.execute(() => document.documentElement.outerHTML)`,
12
+ * then writes both into `.testivai/temp/<name>/` using the same
13
+ * BaselineStore layout as @testivai/witness-playwright. The TestivaiService
14
+ * (registered in wdio.conf.ts) runs `compareAll` + `generateReport` after
15
+ * all tests finish.
16
+ *
17
+ * Architectural choice: we rely on WebdriverIO's native `takeScreenshot`
18
+ * and `execute` APIs rather than opening a CDP session. This is the whole
19
+ * point of the per-framework adapter — using the framework's stable public
20
+ * API instead of fighting Chrome-launch coordination.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.witness = witness;
24
+ const witness_1 = require("@testivai/witness");
25
+ /**
26
+ * Capture a screenshot + DOM and write them as a temp snapshot.
27
+ *
28
+ * @param browser WebdriverIO browser-like object (must expose
29
+ * `takeScreenshot()` and `execute()`).
30
+ * @param name Snapshot name. Becomes the directory under
31
+ * `.testivai/temp/<name>/` and the key in the rendered report.
32
+ * @param options Per-call overrides.
33
+ */
34
+ async function witness(browser, name, options = {}) {
35
+ if (!name || typeof name !== 'string') {
36
+ throw new Error('testivai.witness: snapshot name is required and must be a non-empty string');
37
+ }
38
+ if (!browser || typeof browser.takeScreenshot !== 'function') {
39
+ throw new Error('testivai.witness: browser argument must expose takeScreenshot()');
40
+ }
41
+ // 1. Capture screenshot (base64 PNG → Buffer)
42
+ const base64 = await browser.takeScreenshot();
43
+ if (typeof base64 !== 'string' || base64.length === 0) {
44
+ throw new Error(`testivai.witness("${name}"): browser.takeScreenshot() returned an empty value`);
45
+ }
46
+ const screenshot = Buffer.from(base64, 'base64');
47
+ // 2. Capture DOM (best-effort — never break the screenshot path)
48
+ let dom;
49
+ if (!options.skipDom && typeof browser.execute === 'function') {
50
+ try {
51
+ const result = await browser.execute(
52
+ // Inline string form for maximum WDIO sync/async compatibility.
53
+ // The function-form across WDIO 8/9 has subtle typing differences;
54
+ // the string form is stable.
55
+ 'return document.documentElement.outerHTML;');
56
+ if (typeof result === 'string' && result.length > 0) {
57
+ dom = result;
58
+ }
59
+ }
60
+ catch {
61
+ // Suppressed by design. DOM capture failure means the noise hint
62
+ // is unavailable for this snapshot; pixel diff still works.
63
+ }
64
+ }
65
+ // 3. Write to .testivai/temp/<name>/
66
+ const store = new witness_1.BaselineStore(process.cwd());
67
+ store.writeTemp(name, screenshot, dom);
68
+ }
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@testivai/witness-webdriverio",
3
+ "version": "0.1.1",
4
+ "description": "WebdriverIO adapter for TestivAI Witness — local-first visual regression with pixel + DOM comparison",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./service": {
13
+ "types": "./dist/service.d.ts",
14
+ "default": "./dist/service.js"
15
+ }
16
+ },
17
+ "keywords": [
18
+ "webdriverio",
19
+ "wdio",
20
+ "wdio-service",
21
+ "visual-regression",
22
+ "testing",
23
+ "testivai"
24
+ ],
25
+ "author": "TestivAI",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/mcbuddy/testivai-oss.git",
30
+ "directory": "packages/webdriverio"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/mcbuddy/testivai-oss/issues"
34
+ },
35
+ "homepage": "https://github.com/mcbuddy/testivai-oss/tree/main/packages/webdriverio#readme",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "README.md",
42
+ "LICENSE"
43
+ ],
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ },
47
+ "peerDependencies": {
48
+ "webdriverio": ">=8.0.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "webdriverio": {
52
+ "optional": false
53
+ }
54
+ },
55
+ "dependencies": {
56
+ "@testivai/witness": "1.0.3"
57
+ },
58
+ "devDependencies": {
59
+ "@types/jest": "^29.0.0",
60
+ "@types/node": "^20.0.0",
61
+ "jest": "^29.0.0",
62
+ "ts-jest": "^29.2.5",
63
+ "typescript": "^5.0.0",
64
+ "webdriverio": "^9.0.0"
65
+ },
66
+ "scripts": {
67
+ "build": "tsc",
68
+ "clean": "rm -rf dist",
69
+ "dev": "tsc --watch",
70
+ "test": "jest",
71
+ "test:unit": "jest",
72
+ "test:watch": "jest --watch",
73
+ "test:coverage": "jest --coverage"
74
+ }
75
+ }