@gherkle/runner 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/README.md +482 -0
- package/bin/gherkle-runner.js +111 -0
- package/dist/__tests__/agent-executor-selection.test.d.ts +15 -0
- package/dist/__tests__/agent-executor-selection.test.d.ts.map +1 -0
- package/dist/__tests__/agent-executor-selection.test.js +192 -0
- package/dist/__tests__/agent-executor-selection.test.js.map +1 -0
- package/dist/__tests__/envelope-mapper.test.d.ts +17 -0
- package/dist/__tests__/envelope-mapper.test.d.ts.map +1 -0
- package/dist/__tests__/envelope-mapper.test.js +217 -0
- package/dist/__tests__/envelope-mapper.test.js.map +1 -0
- package/dist/__tests__/gherkin-parser.test.d.ts +2 -0
- package/dist/__tests__/gherkin-parser.test.d.ts.map +1 -0
- package/dist/__tests__/gherkin-parser.test.js +375 -0
- package/dist/__tests__/gherkin-parser.test.js.map +1 -0
- package/dist/__tests__/integration-fork.test.d.ts +16 -0
- package/dist/__tests__/integration-fork.test.d.ts.map +1 -0
- package/dist/__tests__/integration-fork.test.js +141 -0
- package/dist/__tests__/integration-fork.test.js.map +1 -0
- package/dist/__tests__/tmpdir-materialization.test.d.ts +18 -0
- package/dist/__tests__/tmpdir-materialization.test.d.ts.map +1 -0
- package/dist/__tests__/tmpdir-materialization.test.js +177 -0
- package/dist/__tests__/tmpdir-materialization.test.js.map +1 -0
- package/dist/agent.d.ts +71 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +312 -0
- package/dist/agent.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +165 -0
- package/dist/config.js.map +1 -0
- package/dist/frameworks/cucumber-subprocess.d.ts +129 -0
- package/dist/frameworks/cucumber-subprocess.d.ts.map +1 -0
- package/dist/frameworks/cucumber-subprocess.js +469 -0
- package/dist/frameworks/cucumber-subprocess.js.map +1 -0
- package/dist/frameworks/playwright.d.ts +22 -0
- package/dist/frameworks/playwright.d.ts.map +1 -0
- package/dist/frameworks/playwright.js +234 -0
- package/dist/frameworks/playwright.js.map +1 -0
- package/dist/gherkin-parser.d.ts +22 -0
- package/dist/gherkin-parser.d.ts.map +1 -0
- package/dist/gherkin-parser.js +148 -0
- package/dist/gherkin-parser.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/step-registry.d.ts +30 -0
- package/dist/step-registry.d.ts.map +1 -0
- package/dist/step-registry.js +160 -0
- package/dist/step-registry.js.map +1 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/workers/cucumber-worker.d.ts +29 -0
- package/dist/workers/cucumber-worker.d.ts.map +1 -0
- package/dist/workers/cucumber-worker.js +191 -0
- package/dist/workers/cucumber-worker.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CucumberSubprocessExecutor — runs AI-generated step defs via a forked
|
|
4
|
+
* @cucumber/cucumber child process and maps its envelope stream into the
|
|
5
|
+
* runner's existing scenario/step/run events.
|
|
6
|
+
*
|
|
7
|
+
* Why a subprocess (not in-process)?
|
|
8
|
+
* 1. Cancel: SIGTERM the child cleanly; cannot kill an in-process loop.
|
|
9
|
+
* 2. Isolation: user-supplied AI-generated code can crash or leak module
|
|
10
|
+
* state. A long-lived runner cannot afford either.
|
|
11
|
+
* 3. Module cache: Cucumber.js registers hooks at module load. Two
|
|
12
|
+
* consecutive runs in the same process would double-register.
|
|
13
|
+
*
|
|
14
|
+
* Tmpdir layout written by prepareTmpdir():
|
|
15
|
+
*
|
|
16
|
+
* <tmpdir>/
|
|
17
|
+
* features/<feature_id>.feature
|
|
18
|
+
* steps/<suggested_filename>
|
|
19
|
+
* support/world.<js|ts>
|
|
20
|
+
* cucumber.cjs
|
|
21
|
+
* .use-ts (only when language === 'typescript')
|
|
22
|
+
*
|
|
23
|
+
* The path layout matters: the AI prompt emits
|
|
24
|
+
* import { ICustomWorld } from '../support/world'
|
|
25
|
+
* relative to a step-def file. With step-defs at steps/* and the World at
|
|
26
|
+
* support/world.*, that import resolves cleanly with no source rewriting.
|
|
27
|
+
*
|
|
28
|
+
* Envelope → runner event mapping:
|
|
29
|
+
*
|
|
30
|
+
* envelope.testCase → record testCaseId → pickleId
|
|
31
|
+
* envelope.pickle → record pickleId → { name, uri }
|
|
32
|
+
* envelope.testCaseStarted → onScenarioStart(pickleId, name)
|
|
33
|
+
* envelope.testStepFinished → onStepComplete(pickleId, StepResult)
|
|
34
|
+
* envelope.testCaseFinished → onScenarioComplete(pickleId, status, durationMs, error?)
|
|
35
|
+
*
|
|
36
|
+
* Cancel:
|
|
37
|
+
* - SIGTERM, then SIGKILL after 5s if the child is still alive.
|
|
38
|
+
* - Cleanup (rm -rf tmpdir) runs on child 'exit', so it fires for
|
|
39
|
+
* completion, cancellation, AND crash.
|
|
40
|
+
*
|
|
41
|
+
* Lifecycle state machine (the cross-process flow that bit us in review):
|
|
42
|
+
*
|
|
43
|
+
* parent (agent.ts) child (cucumber-worker)
|
|
44
|
+
* ─────────────────── ─────────────────────────
|
|
45
|
+
* prepareTmpdir()
|
|
46
|
+
* fork(worker, [tmpdir]) ───────► boot, require @cucumber/cucumber
|
|
47
|
+
* load tmpdir/cucumber.cjs
|
|
48
|
+
* runCucumber({onMessage})
|
|
49
|
+
* │
|
|
50
|
+
* envelope ◄─────────┤
|
|
51
|
+
* envelope ◄─────────┤
|
|
52
|
+
* envelope ◄─────────┤
|
|
53
|
+
* ... │
|
|
54
|
+
* envelope ◄─────────┘ runCucumber resolves
|
|
55
|
+
* {kind:'done', success} ◄── process.send({...}, () => exit)
|
|
56
|
+
* │
|
|
57
|
+
* child.on('exit', code, signal) ◄──────────── child exits
|
|
58
|
+
* │
|
|
59
|
+
* ├─ killTimer cleared
|
|
60
|
+
* ├─ cleanupTmpdir() (best-effort)
|
|
61
|
+
* ├─ if __fatal stashed → reject(fatal)
|
|
62
|
+
* ├─ if signal SIGTERM/SIGKILL → resolve(partial) ← cancel path
|
|
63
|
+
* └─ else → resolve(all scenarios)
|
|
64
|
+
*
|
|
65
|
+
* cancel() called any time before exit:
|
|
66
|
+
* SIGTERM → killTimer schedules SIGKILL(+5s) → exit fires above
|
|
67
|
+
*/
|
|
68
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
69
|
+
if (k2 === undefined) k2 = k;
|
|
70
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
71
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
72
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
73
|
+
}
|
|
74
|
+
Object.defineProperty(o, k2, desc);
|
|
75
|
+
}) : (function(o, m, k, k2) {
|
|
76
|
+
if (k2 === undefined) k2 = k;
|
|
77
|
+
o[k2] = m[k];
|
|
78
|
+
}));
|
|
79
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
80
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
81
|
+
}) : function(o, v) {
|
|
82
|
+
o["default"] = v;
|
|
83
|
+
});
|
|
84
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
85
|
+
var ownKeys = function(o) {
|
|
86
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
87
|
+
var ar = [];
|
|
88
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
89
|
+
return ar;
|
|
90
|
+
};
|
|
91
|
+
return ownKeys(o);
|
|
92
|
+
};
|
|
93
|
+
return function (mod) {
|
|
94
|
+
if (mod && mod.__esModule) return mod;
|
|
95
|
+
var result = {};
|
|
96
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
97
|
+
__setModuleDefault(result, mod);
|
|
98
|
+
return result;
|
|
99
|
+
};
|
|
100
|
+
})();
|
|
101
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102
|
+
exports.CucumberSubprocessExecutor = void 0;
|
|
103
|
+
exports.createEnvelopeMapper = createEnvelopeMapper;
|
|
104
|
+
const node_child_process_1 = require("node:child_process");
|
|
105
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
106
|
+
const os = __importStar(require("node:os"));
|
|
107
|
+
const path = __importStar(require("node:path"));
|
|
108
|
+
const SIGKILL_GRACE_MS = 5000;
|
|
109
|
+
class CucumberSubprocessExecutor {
|
|
110
|
+
child = null;
|
|
111
|
+
tmpdir = null;
|
|
112
|
+
killTimer = null;
|
|
113
|
+
// Tests inject a stub worker via this option to exercise the fork +
|
|
114
|
+
// IPC + cancel lifecycle without depending on @cucumber/cucumber, chromium,
|
|
115
|
+
// or the actual generated step-defs. Default resolves to the real worker.
|
|
116
|
+
workerPathOverride;
|
|
117
|
+
constructor(opts = {}) {
|
|
118
|
+
this.workerPathOverride = opts.workerPath;
|
|
119
|
+
}
|
|
120
|
+
async executeAll(features, stepDefinitions, env, callbacks) {
|
|
121
|
+
this.tmpdir = await this.prepareTmpdir(features, stepDefinitions);
|
|
122
|
+
// The server keys its scenario→feature lookup on the original DB path
|
|
123
|
+
// (FeatureContent.name). Inside the temp project we materialize features
|
|
124
|
+
// at features/<feature_id>.feature, so pickle.uri is NOT the DB path.
|
|
125
|
+
// Translate back here so scenario:started.featureName matches what the
|
|
126
|
+
// server's featureNameToId map expects.
|
|
127
|
+
const featureIdToOriginalName = new Map(features.map((f) => [f.id, f.name]));
|
|
128
|
+
const mapper = createEnvelopeMapper(featureIdToOriginalName, callbacks);
|
|
129
|
+
return await new Promise((resolve, reject) => {
|
|
130
|
+
const workerPath = this.workerPathOverride ?? require.resolve('../workers/cucumber-worker.js');
|
|
131
|
+
const child = (0, node_child_process_1.fork)(workerPath, [this.tmpdir], {
|
|
132
|
+
env: { ...process.env, ...env },
|
|
133
|
+
// 'ipc' is implicit with fork(); explicit silent=false keeps the
|
|
134
|
+
// child's stdout/stderr inheriting the runner's terminal.
|
|
135
|
+
silent: false,
|
|
136
|
+
});
|
|
137
|
+
this.child = child;
|
|
138
|
+
child.on('message', (raw) => {
|
|
139
|
+
const msg = raw;
|
|
140
|
+
if (msg.kind === 'fatal') {
|
|
141
|
+
// Defer rejection to 'exit' so cleanup still runs uniformly.
|
|
142
|
+
// Stash the message on the child for the exit handler.
|
|
143
|
+
child.__fatal = msg.message;
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (msg.kind === 'done') {
|
|
147
|
+
// No-op: 'exit' fires immediately after IPC drains.
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
mapper.handle(msg.envelope);
|
|
151
|
+
});
|
|
152
|
+
child.on('exit', (code, signal) => {
|
|
153
|
+
if (this.killTimer) {
|
|
154
|
+
clearTimeout(this.killTimer);
|
|
155
|
+
this.killTimer = null;
|
|
156
|
+
}
|
|
157
|
+
this.cleanupTmpdir().finally(() => {
|
|
158
|
+
this.child = null;
|
|
159
|
+
const fatal = child.__fatal;
|
|
160
|
+
if (fatal) {
|
|
161
|
+
reject(new Error(fatal));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (signal === 'SIGTERM' || signal === 'SIGKILL') {
|
|
165
|
+
// Cancelled. Return what we have — the runner emits a partial
|
|
166
|
+
// run rather than failing the whole thing as an error.
|
|
167
|
+
resolve(mapper.getScenarios());
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Non-zero exit without a fatal IPC message and without a kill
|
|
171
|
+
// signal generally means Cucumber found failing scenarios — that
|
|
172
|
+
// is NOT an executor error, it's a normal failed run. We return
|
|
173
|
+
// the accumulated scenarios; the run-level pass/fail derives from
|
|
174
|
+
// them in the parent.
|
|
175
|
+
void code;
|
|
176
|
+
resolve(mapper.getScenarios());
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
child.on('error', (err) => {
|
|
180
|
+
reject(err);
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Cancel an in-flight run. Idempotent; safe to call after the child has
|
|
186
|
+
* already exited.
|
|
187
|
+
*/
|
|
188
|
+
cancel() {
|
|
189
|
+
if (!this.child || this.child.exitCode !== null)
|
|
190
|
+
return;
|
|
191
|
+
try {
|
|
192
|
+
this.child.kill('SIGTERM');
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// child already dead — fine
|
|
196
|
+
}
|
|
197
|
+
this.killTimer = setTimeout(() => {
|
|
198
|
+
if (this.child && this.child.exitCode === null) {
|
|
199
|
+
try {
|
|
200
|
+
this.child.kill('SIGKILL');
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// already dead
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}, SIGKILL_GRACE_MS);
|
|
207
|
+
}
|
|
208
|
+
// ---- tmpdir materialization -----------------------------------------
|
|
209
|
+
// Public so the unit tests can exercise the on-disk layout directly
|
|
210
|
+
// without spinning up a fork. The runtime call site is this.prepareTmpdir()
|
|
211
|
+
// inside executeAll() above.
|
|
212
|
+
async prepareTmpdir(features, stepDefinitions) {
|
|
213
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'gherkle-run-'));
|
|
214
|
+
await fs.mkdir(path.join(root, 'features'), { recursive: true });
|
|
215
|
+
await fs.mkdir(path.join(root, 'steps'), { recursive: true });
|
|
216
|
+
await fs.mkdir(path.join(root, 'support'), { recursive: true });
|
|
217
|
+
// Determine language for the run. If ANY step-def is TypeScript we
|
|
218
|
+
// load ts-node — JS files transpile through it as no-ops.
|
|
219
|
+
const anyTs = stepDefinitions.some((d) => d.language === 'typescript');
|
|
220
|
+
const worldExt = anyTs ? 'ts' : 'js';
|
|
221
|
+
for (const feat of features) {
|
|
222
|
+
// Feature uri == feature_id.feature lets the envelope-stream consumer
|
|
223
|
+
// recover feature_id without an extra lookup table.
|
|
224
|
+
await fs.writeFile(path.join(root, 'features', `${feat.id}.feature`), feat.content, 'utf8');
|
|
225
|
+
}
|
|
226
|
+
// De-collide filenames across step-def files. The dispatcher already
|
|
227
|
+
// prefixes suggested filenames with feature_id when ambiguous, but
|
|
228
|
+
// double-check here — collisions silently overwrite otherwise.
|
|
229
|
+
const seen = new Set();
|
|
230
|
+
for (const def of stepDefinitions) {
|
|
231
|
+
let filename = def.filename;
|
|
232
|
+
if (seen.has(filename)) {
|
|
233
|
+
const ext = path.extname(filename) || (def.language === 'typescript' ? '.ts' : '.js');
|
|
234
|
+
const base = path.basename(filename, ext);
|
|
235
|
+
filename = `${base}-${def.featureId}${ext}`;
|
|
236
|
+
}
|
|
237
|
+
seen.add(filename);
|
|
238
|
+
await fs.writeFile(path.join(root, 'steps', filename), def.content, 'utf8');
|
|
239
|
+
}
|
|
240
|
+
await fs.writeFile(path.join(root, 'support', `world.${worldExt}`), this.worldShim(worldExt), 'utf8');
|
|
241
|
+
await fs.writeFile(path.join(root, 'cucumber.cjs'), this.cucumberConfig(anyTs), 'utf8');
|
|
242
|
+
if (anyTs) {
|
|
243
|
+
await fs.writeFile(path.join(root, '.use-ts'), '', 'utf8');
|
|
244
|
+
}
|
|
245
|
+
return root;
|
|
246
|
+
}
|
|
247
|
+
async cleanupTmpdir() {
|
|
248
|
+
if (!this.tmpdir)
|
|
249
|
+
return;
|
|
250
|
+
try {
|
|
251
|
+
await fs.rm(this.tmpdir, { recursive: true, force: true });
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// Best-effort. The OS will clean /tmp eventually.
|
|
255
|
+
}
|
|
256
|
+
this.tmpdir = null;
|
|
257
|
+
}
|
|
258
|
+
// ---- generated support files ----------------------------------------
|
|
259
|
+
/**
|
|
260
|
+
* A minimal World that exposes `this.page`, `this.context`, and `this.env`
|
|
261
|
+
* to step definitions. AI-generated code expects these via the
|
|
262
|
+
* `ICustomWorld` import. The TS variant exports `ICustomWorld` as a type
|
|
263
|
+
* alias so the prompt's `import { ICustomWorld } from '../support/world'`
|
|
264
|
+
* compiles; the JS variant just exports the constructor.
|
|
265
|
+
*
|
|
266
|
+
* Browser is launched per scenario (cheap with chromium) so a crashing
|
|
267
|
+
* step does not poison subsequent scenarios.
|
|
268
|
+
*/
|
|
269
|
+
worldShim(ext) {
|
|
270
|
+
if (ext === 'ts') {
|
|
271
|
+
return `import { setWorldConstructor, Before, After, AfterAll, World } from '@cucumber/cucumber';
|
|
272
|
+
import { chromium, type Browser, type BrowserContext, type Page } from 'playwright-core';
|
|
273
|
+
|
|
274
|
+
export interface ICustomWorld extends World {
|
|
275
|
+
page: Page;
|
|
276
|
+
context: BrowserContext;
|
|
277
|
+
env: NodeJS.ProcessEnv;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
class GherkleWorld extends World implements Partial<ICustomWorld> {
|
|
281
|
+
page!: Page;
|
|
282
|
+
context!: BrowserContext;
|
|
283
|
+
env: NodeJS.ProcessEnv = process.env;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
setWorldConstructor(GherkleWorld);
|
|
287
|
+
|
|
288
|
+
let browser: Browser | undefined;
|
|
289
|
+
|
|
290
|
+
Before(async function (this: GherkleWorld) {
|
|
291
|
+
if (!browser) browser = await chromium.launch({ headless: process.env.HEADLESS !== 'false' });
|
|
292
|
+
this.context = await browser.newContext({ baseURL: process.env.BASE_URL });
|
|
293
|
+
this.page = await this.context.newPage();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
After(async function (this: GherkleWorld) {
|
|
297
|
+
await this.context?.close().catch(() => {});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Close the shared browser when the test run ends. Without this the chromium
|
|
301
|
+
// process keeps the IPC channel open and the worker never exits — the parent
|
|
302
|
+
// would hang on the 'exit' event and tmpdir cleanup would not run.
|
|
303
|
+
AfterAll(async function () {
|
|
304
|
+
if (browser) {
|
|
305
|
+
try { await browser.close(); } catch { /* already gone */ }
|
|
306
|
+
browser = undefined;
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
`;
|
|
310
|
+
}
|
|
311
|
+
return `const { setWorldConstructor, Before, After, AfterAll, World } = require('@cucumber/cucumber');
|
|
312
|
+
const { chromium } = require('playwright-core');
|
|
313
|
+
|
|
314
|
+
class GherkleWorld extends World {
|
|
315
|
+
constructor(options) {
|
|
316
|
+
super(options);
|
|
317
|
+
this.env = process.env;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
setWorldConstructor(GherkleWorld);
|
|
322
|
+
|
|
323
|
+
let browser;
|
|
324
|
+
|
|
325
|
+
Before(async function () {
|
|
326
|
+
if (!browser) browser = await chromium.launch({ headless: process.env.HEADLESS !== 'false' });
|
|
327
|
+
this.context = await browser.newContext({ baseURL: process.env.BASE_URL });
|
|
328
|
+
this.page = await this.context.newPage();
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
After(async function () {
|
|
332
|
+
if (this.context) {
|
|
333
|
+
try { await this.context.close(); } catch (_e) { /* ignore */ }
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// Close the shared browser at end-of-run. Without this the chromium process
|
|
338
|
+
// keeps the IPC channel open and the worker never exits.
|
|
339
|
+
AfterAll(async function () {
|
|
340
|
+
if (browser) {
|
|
341
|
+
try { await browser.close(); } catch (_e) { /* already gone */ }
|
|
342
|
+
browser = undefined;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
`;
|
|
346
|
+
}
|
|
347
|
+
cucumberConfig(useTs) {
|
|
348
|
+
return `// Generated by @gherkle/runner. Do not edit.
|
|
349
|
+
module.exports = {
|
|
350
|
+
default: {
|
|
351
|
+
paths: ['features/**/*.feature'],
|
|
352
|
+
require: ['steps/**/*.${useTs ? 'ts' : 'js'}', 'support/**/*.${useTs ? 'ts' : 'js'}'],
|
|
353
|
+
requireModule: ${useTs ? "['ts-node/register/transpile-only']" : '[]'},
|
|
354
|
+
format: ['summary'],
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
exports.CucumberSubprocessExecutor = CucumberSubprocessExecutor;
|
|
361
|
+
function createEnvelopeMapper(featureIdToOriginalName, callbacks) {
|
|
362
|
+
const pickles = new Map();
|
|
363
|
+
const testCaseToPickle = new Map();
|
|
364
|
+
const startedToTestCase = new Map();
|
|
365
|
+
const scenarios = new Map();
|
|
366
|
+
return {
|
|
367
|
+
handle(raw) {
|
|
368
|
+
const env = raw;
|
|
369
|
+
if (!env)
|
|
370
|
+
return;
|
|
371
|
+
if (env.pickle) {
|
|
372
|
+
pickles.set(env.pickle.id, {
|
|
373
|
+
name: env.pickle.name,
|
|
374
|
+
uri: env.pickle.uri,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
if (env.testCase) {
|
|
378
|
+
testCaseToPickle.set(env.testCase.id, env.testCase.pickleId);
|
|
379
|
+
}
|
|
380
|
+
if (env.testCaseStarted) {
|
|
381
|
+
const tcId = env.testCaseStarted.testCaseId;
|
|
382
|
+
startedToTestCase.set(env.testCaseStarted.id, tcId);
|
|
383
|
+
const pickleId = testCaseToPickle.get(tcId);
|
|
384
|
+
const pickle = pickleId ? pickles.get(pickleId) : undefined;
|
|
385
|
+
if (pickleId && pickle) {
|
|
386
|
+
const featureId = featureIdFromUri(pickle.uri);
|
|
387
|
+
const originalName = featureIdToOriginalName.get(featureId) ?? pickle.uri;
|
|
388
|
+
scenarios.set(pickleId, {
|
|
389
|
+
scenarioId: pickleId,
|
|
390
|
+
scenarioName: pickle.name,
|
|
391
|
+
featureId,
|
|
392
|
+
status: 'running',
|
|
393
|
+
durationMs: 0,
|
|
394
|
+
steps: [],
|
|
395
|
+
});
|
|
396
|
+
callbacks.onScenarioStart(pickleId, pickle.name, originalName);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (env.testStepFinished) {
|
|
400
|
+
const tcId = startedToTestCase.get(env.testStepFinished.testCaseStartedId);
|
|
401
|
+
const pickleId = tcId ? testCaseToPickle.get(tcId) : undefined;
|
|
402
|
+
const scenario = pickleId ? scenarios.get(pickleId) : undefined;
|
|
403
|
+
if (pickleId && scenario) {
|
|
404
|
+
const result = env.testStepFinished.testStepResult ?? {};
|
|
405
|
+
const stepResult = {
|
|
406
|
+
keyword: 'Given',
|
|
407
|
+
text: '',
|
|
408
|
+
status: stepStatusToTestStatus(result.status),
|
|
409
|
+
durationMs: nanosToMillis(result.duration),
|
|
410
|
+
error: result.message,
|
|
411
|
+
};
|
|
412
|
+
scenario.steps.push(stepResult);
|
|
413
|
+
callbacks.onStepComplete(pickleId, stepResult);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (env.testCaseFinished) {
|
|
417
|
+
const tcId = startedToTestCase.get(env.testCaseFinished.testCaseStartedId);
|
|
418
|
+
const pickleId = tcId ? testCaseToPickle.get(tcId) : undefined;
|
|
419
|
+
const scenario = pickleId ? scenarios.get(pickleId) : undefined;
|
|
420
|
+
if (pickleId && scenario) {
|
|
421
|
+
const anyFailed = scenario.steps.some((s) => s.status === 'failed');
|
|
422
|
+
const allSkipped = scenario.steps.length > 0 &&
|
|
423
|
+
scenario.steps.every((s) => s.status === 'skipped');
|
|
424
|
+
const status = anyFailed
|
|
425
|
+
? 'failed'
|
|
426
|
+
: allSkipped
|
|
427
|
+
? 'skipped'
|
|
428
|
+
: 'passed';
|
|
429
|
+
scenario.status = status;
|
|
430
|
+
scenario.durationMs = scenario.steps.reduce((sum, s) => sum + (s.durationMs || 0), 0);
|
|
431
|
+
const firstError = scenario.steps.find((s) => s.error)?.error;
|
|
432
|
+
if (firstError)
|
|
433
|
+
scenario.error = { message: firstError };
|
|
434
|
+
callbacks.onScenarioComplete(pickleId, status, scenario.durationMs, firstError);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
getScenarios() {
|
|
439
|
+
return [...scenarios.values()];
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
function stepStatusToTestStatus(s) {
|
|
444
|
+
switch (s) {
|
|
445
|
+
case 'PASSED':
|
|
446
|
+
return 'passed';
|
|
447
|
+
case 'SKIPPED':
|
|
448
|
+
return 'skipped';
|
|
449
|
+
// UNDEFINED (no matching step), PENDING, AMBIGUOUS, FAILED → failed.
|
|
450
|
+
default:
|
|
451
|
+
return 'failed';
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
// ---- helpers ---------------------------------------------------------
|
|
455
|
+
function featureIdFromUri(uri) {
|
|
456
|
+
// We materialize features at features/<feature_id>.feature. The pickle.uri
|
|
457
|
+
// is the path Cucumber resolved (relative to cwd). Strip dir + extension.
|
|
458
|
+
const base = path.basename(uri);
|
|
459
|
+
return base.replace(/\.feature$/, '');
|
|
460
|
+
}
|
|
461
|
+
function nanosToMillis(duration) {
|
|
462
|
+
if (!duration || typeof duration !== 'object')
|
|
463
|
+
return 0;
|
|
464
|
+
const d = duration;
|
|
465
|
+
const secs = typeof d.seconds === 'number' ? d.seconds : 0;
|
|
466
|
+
const nanos = typeof d.nanos === 'number' ? d.nanos : 0;
|
|
467
|
+
return Math.round(secs * 1000 + nanos / 1_000_000);
|
|
468
|
+
}
|
|
469
|
+
//# sourceMappingURL=cucumber-subprocess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cucumber-subprocess.js","sourceRoot":"","sources":["../../src/frameworks/cucumber-subprocess.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkWH,oDAwFC;AAxbD,2DAAwD;AACxD,qDAAuC;AACvC,4CAA8B;AAC9B,gDAAkC;AAwBlC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,MAAa,0BAA0B;IAC7B,KAAK,GAAwB,IAAI,CAAC;IAClC,MAAM,GAAkB,IAAI,CAAC;IAC7B,SAAS,GAA0B,IAAI,CAAC;IAChD,oEAAoE;IACpE,4EAA4E;IAC5E,0EAA0E;IACzD,kBAAkB,CAAU;IAE7C,YAAY,OAAgC,EAAE;QAC5C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,UAAU,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,UAAU,CACd,QAA0B,EAC1B,eAAmC,EACnC,GAA2B,EAC3B,SAAoC;QAEpC,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAElE,sEAAsE;QACtE,yEAAyE;QACzE,sEAAsE;QACtE,uEAAuE;QACvE,wCAAwC;QACxC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE7E,MAAM,MAAM,GAAG,oBAAoB,CAAC,uBAAuB,EAAE,SAAS,CAAC,CAAC;QAExE,OAAO,MAAM,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7D,MAAM,UAAU,GACd,IAAI,CAAC,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;YAC9E,MAAM,KAAK,GAAG,IAAA,yBAAI,EAAC,UAAU,EAAE,CAAC,IAAI,CAAC,MAAO,CAAC,EAAE;gBAC7C,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE;gBAC/B,iEAAiE;gBACjE,0DAA0D;gBAC1D,MAAM,EAAE,KAAK;aACd,CAAC,CAAC;YACH,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YAEnB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,EAAE;gBACnC,MAAM,GAAG,GAAG,GAG0B,CAAC;gBAEvC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBACzB,6DAA6D;oBAC7D,uDAAuD;oBACtD,KAAa,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;oBACrC,OAAO;gBACT,CAAC;gBACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACxB,oDAAoD;oBACpD,OAAO;gBACT,CAAC;gBACD,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;gBAChC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACnB,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACxB,CAAC;gBACD,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;oBAChC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;oBAClB,MAAM,KAAK,GAAI,KAAa,CAAC,OAA6B,CAAC;oBAC3D,IAAI,KAAK,EAAE,CAAC;wBACV,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;wBACzB,OAAO;oBACT,CAAC;oBACD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;wBACjD,8DAA8D;wBAC9D,uDAAuD;wBACvD,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;wBAC/B,OAAO;oBACT,CAAC;oBACD,+DAA+D;oBAC/D,iEAAiE;oBACjE,gEAAgE;oBAChE,kEAAkE;oBAClE,sBAAsB;oBACtB,KAAK,IAAI,CAAC;oBACV,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;gBACjC,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACxB,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO;QACxD,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,4BAA4B;QAC9B,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC/B,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC/C,IAAI,CAAC;oBACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACP,eAAe;gBACjB,CAAC;YACH,CAAC;QACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACvB,CAAC;IAED,wEAAwE;IACxE,oEAAoE;IACpE,4EAA4E;IAC5E,6BAA6B;IAE7B,KAAK,CAAC,aAAa,CACjB,QAA0B,EAC1B,eAAmC;QAEnC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QACtE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEhE,mEAAmE;QACnE,0DAA0D;QAC1D,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAErC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,sEAAsE;YACtE,oDAAoD;YACpD,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,EAAE,UAAU,CAAC,EACjD,IAAI,CAAC,OAAO,EACZ,MAAM,CACP,CAAC;QACJ,CAAC;QAED,qEAAqE;QACrE,mEAAmE;QACnE,+DAA+D;QAC/D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;YAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBACtF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBAC1C,QAAQ,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;YAC9C,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC,EAC/C,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EACxB,MAAM,CACP,CAAC;QAEF,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAC/B,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAC1B,MAAM,CACP,CAAC;QAEF,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,aAAa;QACzB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,wEAAwE;IAExE;;;;;;;;;OASG;IACK,SAAS,CAAC,GAAgB;QAChC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCZ,CAAC;QACE,CAAC;QACD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCV,CAAC;IACA,CAAC;IAEO,cAAc,CAAC,KAAc;QACnC,OAAO;;;;4BAIiB,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,oBAAoB,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;qBACjE,KAAK,CAAC,CAAC,CAAC,qCAAqC,CAAC,CAAC,CAAC,IAAI;;;;CAIxE,CAAC;IACA,CAAC;CACF;AApSD,gEAoSC;AA+BD,SAAgB,oBAAoB,CAClC,uBAA4C,EAC5C,SAAoC;IAEpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAyC,CAAC;IACjE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEpD,OAAO;QACL,MAAM,CAAC,GAAY;YACjB,MAAM,GAAG,GAAG,GAAsC,CAAC;YACnD,IAAI,CAAC,GAAG;gBAAE,OAAO;YAEjB,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE;oBACzB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI;oBACrB,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG;iBACpB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACjB,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC/D,CAAC;YACD,IAAI,GAAG,CAAC,eAAe,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC;gBAC5C,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;gBACpD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC5D,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;oBACvB,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAC/C,MAAM,YAAY,GAAG,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC;oBAC1E,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE;wBACtB,UAAU,EAAE,QAAQ;wBACpB,YAAY,EAAE,MAAM,CAAC,IAAI;wBACzB,SAAS;wBACT,MAAM,EAAE,SAAS;wBACjB,UAAU,EAAE,CAAC;wBACb,KAAK,EAAE,EAAE;qBACV,CAAC,CAAC;oBACH,SAAS,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;YACD,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;gBAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;oBACzB,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,cAAc,IAAI,EAAE,CAAC;oBACzD,MAAM,UAAU,GAAe;wBAC7B,OAAO,EAAE,OAAO;wBAChB,IAAI,EAAE,EAAE;wBACR,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC;wBAC7C,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC;wBAC1C,KAAK,EAAE,MAAM,CAAC,OAAO;qBACtB,CAAC;oBACF,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBAChC,SAAS,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC;YACD,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;gBAC3E,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;oBACzB,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;oBACpE,MAAM,UAAU,GACd,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;wBACzB,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;oBACtD,MAAM,MAAM,GAAe,SAAS;wBAClC,CAAC,CAAC,QAAQ;wBACV,CAAC,CAAC,UAAU;4BACV,CAAC,CAAC,SAAS;4BACX,CAAC,CAAC,QAAQ,CAAC;oBACf,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;oBACzB,QAAQ,CAAC,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CACzC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,EACrC,CAAC,CACF,CAAC;oBACF,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;oBAC9D,IAAI,UAAU;wBAAE,QAAQ,CAAC,KAAK,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;oBACzD,SAAS,CAAC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC;QACH,CAAC;QACD,YAAY;YACV,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QACjC,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,CAAS;IACvC,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;QACnB,qEAAqE;QACrE;YACE,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC;AAED,yEAAyE;AAEzE,SAAS,gBAAgB,CAAC,GAAW;IACnC,2EAA2E;IAC3E,0EAA0E;IAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,aAAa,CAAC,QAAiB;IACtC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,QAAgD,CAAC;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,SAAS,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AgentConfig } from "../config";
|
|
2
|
+
import { FeatureContent, TestConfig, ScenarioResult, StepResult, TestStatus } from "../types";
|
|
3
|
+
interface ExecutorCallbacks {
|
|
4
|
+
onScenarioStart: (scenarioId: string, scenarioName: string) => void;
|
|
5
|
+
onStepComplete: (scenarioId: string, step: StepResult) => void;
|
|
6
|
+
onScenarioComplete: (scenarioId: string, status: TestStatus, durationMs: number, error?: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare class PlaywrightExecutor {
|
|
9
|
+
private config;
|
|
10
|
+
private registry;
|
|
11
|
+
private browser;
|
|
12
|
+
constructor(config: AgentConfig);
|
|
13
|
+
execute(feature: FeatureContent, testConfig: TestConfig, callbacks: ExecutorCallbacks): Promise<ScenarioResult[]>;
|
|
14
|
+
private launchBrowser;
|
|
15
|
+
private getBrowserLauncher;
|
|
16
|
+
private executeScenario;
|
|
17
|
+
private executeStep;
|
|
18
|
+
private createStepTimeout;
|
|
19
|
+
private captureScreenshot;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=playwright.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../src/frameworks/playwright.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EACL,cAAc,EACd,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EAEX,MAAM,UAAU,CAAC;AAQlB,UAAU,iBAAiB;IACzB,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/D,kBAAkB,EAAE,CAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,KACX,IAAI,CAAC;CACX;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,OAAO,CAAwB;gBAE3B,MAAM,EAAE,WAAW;IAKzB,OAAO,CACX,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,iBAAiB,GAC3B,OAAO,CAAC,cAAc,EAAE,CAAC;YAmCd,aAAa;IAM3B,OAAO,CAAC,kBAAkB;YAWZ,eAAe;YAqGf,WAAW;IAiDzB,OAAO,CAAC,iBAAiB;YAQX,iBAAiB;CA6BhC"}
|