@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.
Files changed (59) hide show
  1. package/README.md +482 -0
  2. package/bin/gherkle-runner.js +111 -0
  3. package/dist/__tests__/agent-executor-selection.test.d.ts +15 -0
  4. package/dist/__tests__/agent-executor-selection.test.d.ts.map +1 -0
  5. package/dist/__tests__/agent-executor-selection.test.js +192 -0
  6. package/dist/__tests__/agent-executor-selection.test.js.map +1 -0
  7. package/dist/__tests__/envelope-mapper.test.d.ts +17 -0
  8. package/dist/__tests__/envelope-mapper.test.d.ts.map +1 -0
  9. package/dist/__tests__/envelope-mapper.test.js +217 -0
  10. package/dist/__tests__/envelope-mapper.test.js.map +1 -0
  11. package/dist/__tests__/gherkin-parser.test.d.ts +2 -0
  12. package/dist/__tests__/gherkin-parser.test.d.ts.map +1 -0
  13. package/dist/__tests__/gherkin-parser.test.js +375 -0
  14. package/dist/__tests__/gherkin-parser.test.js.map +1 -0
  15. package/dist/__tests__/integration-fork.test.d.ts +16 -0
  16. package/dist/__tests__/integration-fork.test.d.ts.map +1 -0
  17. package/dist/__tests__/integration-fork.test.js +141 -0
  18. package/dist/__tests__/integration-fork.test.js.map +1 -0
  19. package/dist/__tests__/tmpdir-materialization.test.d.ts +18 -0
  20. package/dist/__tests__/tmpdir-materialization.test.d.ts.map +1 -0
  21. package/dist/__tests__/tmpdir-materialization.test.js +177 -0
  22. package/dist/__tests__/tmpdir-materialization.test.js.map +1 -0
  23. package/dist/agent.d.ts +71 -0
  24. package/dist/agent.d.ts.map +1 -0
  25. package/dist/agent.js +312 -0
  26. package/dist/agent.js.map +1 -0
  27. package/dist/config.d.ts +31 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +165 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/frameworks/cucumber-subprocess.d.ts +129 -0
  32. package/dist/frameworks/cucumber-subprocess.d.ts.map +1 -0
  33. package/dist/frameworks/cucumber-subprocess.js +469 -0
  34. package/dist/frameworks/cucumber-subprocess.js.map +1 -0
  35. package/dist/frameworks/playwright.d.ts +22 -0
  36. package/dist/frameworks/playwright.d.ts.map +1 -0
  37. package/dist/frameworks/playwright.js +234 -0
  38. package/dist/frameworks/playwright.js.map +1 -0
  39. package/dist/gherkin-parser.d.ts +22 -0
  40. package/dist/gherkin-parser.d.ts.map +1 -0
  41. package/dist/gherkin-parser.js +148 -0
  42. package/dist/gherkin-parser.js.map +1 -0
  43. package/dist/index.d.ts +10 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +31 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/step-registry.d.ts +30 -0
  48. package/dist/step-registry.d.ts.map +1 -0
  49. package/dist/step-registry.js +160 -0
  50. package/dist/step-registry.js.map +1 -0
  51. package/dist/types.d.ts +117 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +6 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/workers/cucumber-worker.d.ts +29 -0
  56. package/dist/workers/cucumber-worker.d.ts.map +1 -0
  57. package/dist/workers/cucumber-worker.js +191 -0
  58. package/dist/workers/cucumber-worker.js.map +1 -0
  59. package/package.json +74 -0
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for CucumberSubprocessExecutor.prepareTmpdir — the on-disk layout
4
+ * the forked Cucumber.js worker reads.
5
+ *
6
+ * Tmpdir layout under verification:
7
+ * <tmpdir>/
8
+ * features/<feature_id>.feature
9
+ * steps/<filename>
10
+ * support/world.{js|ts}
11
+ * cucumber.cjs
12
+ * .use-ts (only when any step-def is TypeScript)
13
+ *
14
+ * The runtime call site is private to executeAll(); this test calls
15
+ * prepareTmpdir directly and asserts the filesystem state. Each test cleans
16
+ * up the directory it created.
17
+ */
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
30
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
31
+ }) : function(o, v) {
32
+ o["default"] = v;
33
+ });
34
+ var __importStar = (this && this.__importStar) || (function () {
35
+ var ownKeys = function(o) {
36
+ ownKeys = Object.getOwnPropertyNames || function (o) {
37
+ var ar = [];
38
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
39
+ return ar;
40
+ };
41
+ return ownKeys(o);
42
+ };
43
+ return function (mod) {
44
+ if (mod && mod.__esModule) return mod;
45
+ var result = {};
46
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
47
+ __setModuleDefault(result, mod);
48
+ return result;
49
+ };
50
+ })();
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ const vitest_1 = require("vitest");
53
+ const fs = __importStar(require("node:fs/promises"));
54
+ const path = __importStar(require("node:path"));
55
+ const cucumber_subprocess_1 = require("../frameworks/cucumber-subprocess");
56
+ const cleanupPaths = [];
57
+ (0, vitest_1.afterEach)(async () => {
58
+ while (cleanupPaths.length) {
59
+ const p = cleanupPaths.pop();
60
+ try {
61
+ await fs.rm(p, { recursive: true, force: true });
62
+ }
63
+ catch {
64
+ /* best-effort */
65
+ }
66
+ }
67
+ });
68
+ function track(p) {
69
+ cleanupPaths.push(p);
70
+ return p;
71
+ }
72
+ const featureFactory = (id, name = 'demo') => ({
73
+ id,
74
+ name: `features/${name}.feature`,
75
+ path: `features/${name}.feature`,
76
+ content: `Feature: ${name}\n Scenario: it works\n Given a thing\n`,
77
+ });
78
+ const stepDefFactory = (featureId, filename, language = 'javascript') => ({
79
+ featureId,
80
+ filename,
81
+ content: `// step defs for ${featureId}\n`,
82
+ language,
83
+ });
84
+ (0, vitest_1.describe)('CucumberSubprocessExecutor.prepareTmpdir', () => {
85
+ (0, vitest_1.it)('creates features/, steps/, support/ directories and cucumber.cjs', async () => {
86
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
87
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a')], [stepDefFactory('feat-a', 'steps.js')]));
88
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'features'))).resolves.toBeUndefined();
89
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'steps'))).resolves.toBeUndefined();
90
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'support'))).resolves.toBeUndefined();
91
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'cucumber.cjs'))).resolves.toBeUndefined();
92
+ });
93
+ (0, vitest_1.it)('writes each feature at features/<feature_id>.feature (NOT the DB path)', async () => {
94
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
95
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('uuid-1234')], [stepDefFactory('uuid-1234', 'steps.js')]));
96
+ // Stored by feature_id, NOT by the DB-side path. This is what lets the
97
+ // envelope mapper recover feature_id from pickle.uri.
98
+ const featurePath = path.join(tmpdir, 'features', 'uuid-1234.feature');
99
+ const content = await fs.readFile(featurePath, 'utf8');
100
+ (0, vitest_1.expect)(content).toContain('Feature: demo');
101
+ });
102
+ (0, vitest_1.it)('renames colliding step-def filenames with feature_id suffix', async () => {
103
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
104
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a'), featureFactory('feat-b')], [
105
+ stepDefFactory('feat-a', 'steps.js'),
106
+ // Same filename — must be renamed, not silently overwritten.
107
+ stepDefFactory('feat-b', 'steps.js'),
108
+ ]));
109
+ const stepsDir = await fs.readdir(path.join(tmpdir, 'steps'));
110
+ (0, vitest_1.expect)(stepsDir).toContain('steps.js');
111
+ (0, vitest_1.expect)(stepsDir).toContain('steps-feat-b.js');
112
+ (0, vitest_1.expect)(stepsDir).toHaveLength(2);
113
+ });
114
+ (0, vitest_1.it)('emits world.js + NO .use-ts marker when all step-defs are JavaScript', async () => {
115
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
116
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a')], [stepDefFactory('feat-a', 'steps.js', 'javascript')]));
117
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'support', 'world.js'))).resolves.toBeUndefined();
118
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'support', 'world.ts'))).rejects.toThrow();
119
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, '.use-ts'))).rejects.toThrow();
120
+ });
121
+ (0, vitest_1.it)('emits world.ts + .use-ts marker when ANY step-def is TypeScript', async () => {
122
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
123
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a'), featureFactory('feat-b')], [
124
+ // Mixed: one JS, one TS → still triggers TS path (ts-node handles both)
125
+ stepDefFactory('feat-a', 'a.js', 'javascript'),
126
+ stepDefFactory('feat-b', 'b.ts', 'typescript'),
127
+ ]));
128
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'support', 'world.ts'))).resolves.toBeUndefined();
129
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, 'support', 'world.js'))).rejects.toThrow();
130
+ await (0, vitest_1.expect)(fs.access(path.join(tmpdir, '.use-ts'))).resolves.toBeUndefined();
131
+ });
132
+ (0, vitest_1.it)('cucumber.cjs require glob matches chosen language extension', async () => {
133
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
134
+ const jsTmp = track(await exec.prepareTmpdir([featureFactory('feat-a')], [stepDefFactory('feat-a', 'steps.js', 'javascript')]));
135
+ const jsConfig = await fs.readFile(path.join(jsTmp, 'cucumber.cjs'), 'utf8');
136
+ (0, vitest_1.expect)(jsConfig).toContain("'steps/**/*.js'");
137
+ (0, vitest_1.expect)(jsConfig).toContain("requireModule: []");
138
+ const tsTmp = track(await exec.prepareTmpdir([featureFactory('feat-b')], [stepDefFactory('feat-b', 'steps.ts', 'typescript')]));
139
+ const tsConfig = await fs.readFile(path.join(tsTmp, 'cucumber.cjs'), 'utf8');
140
+ (0, vitest_1.expect)(tsConfig).toContain("'steps/**/*.ts'");
141
+ (0, vitest_1.expect)(tsConfig).toContain("requireModule: ['ts-node/register/transpile-only']");
142
+ });
143
+ (0, vitest_1.it)('world.ts includes ICustomWorld interface export (matches AI prompt import)', async () => {
144
+ // The AI prompt at apps/web/.../route.ts emits:
145
+ // import { ICustomWorld } from '../support/world'
146
+ // The generated world.ts must export ICustomWorld for that import to resolve.
147
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
148
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a')], [stepDefFactory('feat-a', 'steps.ts', 'typescript')]));
149
+ const world = await fs.readFile(path.join(tmpdir, 'support', 'world.ts'), 'utf8');
150
+ (0, vitest_1.expect)(world).toContain('export interface ICustomWorld');
151
+ (0, vitest_1.expect)(world).toContain('AfterAll'); // browser close — codex finding #2 regression guard
152
+ });
153
+ (0, vitest_1.it)('world.js (JS variant) also registers AfterAll for browser close', async () => {
154
+ // Regression guard for codex P1 #2: without AfterAll the chromium browser
155
+ // stays alive, the worker never exits, and the parent hangs.
156
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
157
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a')], [stepDefFactory('feat-a', 'steps.js', 'javascript')]));
158
+ const world = await fs.readFile(path.join(tmpdir, 'support', 'world.js'), 'utf8');
159
+ (0, vitest_1.expect)(world).toContain('AfterAll');
160
+ (0, vitest_1.expect)(world).toContain('browser.close()');
161
+ });
162
+ (0, vitest_1.it)('writes step-def content verbatim', async () => {
163
+ const exec = new cucumber_subprocess_1.CucumberSubprocessExecutor();
164
+ const customCode = `const { Given } = require('@cucumber/cucumber');\nGiven('a thing', () => {});\n`;
165
+ const tmpdir = track(await exec.prepareTmpdir([featureFactory('feat-a')], [
166
+ {
167
+ featureId: 'feat-a',
168
+ filename: 'auth.steps.js',
169
+ content: customCode,
170
+ language: 'javascript',
171
+ },
172
+ ]));
173
+ const written = await fs.readFile(path.join(tmpdir, 'steps', 'auth.steps.js'), 'utf8');
174
+ (0, vitest_1.expect)(written).toBe(customCode);
175
+ });
176
+ });
177
+ //# sourceMappingURL=tmpdir-materialization.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmpdir-materialization.test.js","sourceRoot":"","sources":["../../src/__tests__/tmpdir-materialization.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * GherkleAgent - Main agent class for connecting to Gherkle and executing tests
3
+ */
4
+ import { AgentConfig } from './config';
5
+ export declare class GherkleAgent {
6
+ private config;
7
+ private ws;
8
+ private runnerId;
9
+ private status;
10
+ private currentRunId;
11
+ private currentCucumberExecutor;
12
+ private heartbeatInterval;
13
+ private reconnectTimeout;
14
+ private shouldReconnect;
15
+ constructor(config: AgentConfig);
16
+ /**
17
+ * Start the agent and connect to Gherkle
18
+ */
19
+ start(): Promise<void>;
20
+ /**
21
+ * Stop the agent and disconnect
22
+ */
23
+ stop(): Promise<void>;
24
+ /**
25
+ * Connect to Gherkle WebSocket server
26
+ */
27
+ private connect;
28
+ /**
29
+ * Handle incoming messages from Gherkle
30
+ */
31
+ private handleMessage;
32
+ /**
33
+ * Send a message to Gherkle
34
+ */
35
+ private send;
36
+ /**
37
+ * Start heartbeat interval
38
+ */
39
+ private startHeartbeat;
40
+ /**
41
+ * Stop heartbeat interval
42
+ */
43
+ private stopHeartbeat;
44
+ /**
45
+ * Execute a test run.
46
+ *
47
+ * Two paths:
48
+ * - stepDefinitions non-empty → CucumberSubprocessExecutor (default).
49
+ * The server has already gathered AI-generated step-def code; the
50
+ * runner ships it into a forked Cucumber.js process. No local
51
+ * dependencies on the runner machine beyond what @gherkle/runner
52
+ * itself bundles.
53
+ * - stepDefinitions empty AND testConfig.stepDefinitionsPath set →
54
+ * legacy PlaywrightExecutor (BYO: user keeps step defs on disk).
55
+ * - Otherwise → error the run with a clear message. The server already
56
+ * hard-fails dispatch in this case (D9); this is defense in depth.
57
+ */
58
+ private executeRun;
59
+ /**
60
+ * Cancel an in-progress run. SIGTERMs the Cucumber subprocess (with a 5s
61
+ * SIGKILL fallback) so the run terminates promptly. The executeRun()
62
+ * promise then resolves naturally: its 'exit' handler returns the
63
+ * partial scenarios it had accumulated, and run:completed flows as usual.
64
+ */
65
+ private cancelRun;
66
+ /**
67
+ * Get the appropriate executor for the framework
68
+ */
69
+ private getExecutor;
70
+ }
71
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAgBvC,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,YAAY,CAAuB;IAG3C,OAAO,CAAC,uBAAuB,CAA2C;IAC1E,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,eAAe,CAAQ;gBAEnB,MAAM,EAAE,WAAW;IAI/B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;OAEG;YACW,OAAO;IA4CrB;;OAEG;YACW,aAAa;IA+B3B;;OAEG;IACH,OAAO,CAAC,IAAI;IAMZ;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;;;;;;;;;;;;OAaG;YACW,UAAU;IA6IxB;;;;;OAKG;YACW,SAAS;IASvB;;OAEG;IACH,OAAO,CAAC,WAAW;CASpB"}
package/dist/agent.js ADDED
@@ -0,0 +1,312 @@
1
+ "use strict";
2
+ /**
3
+ * GherkleAgent - Main agent class for connecting to Gherkle and executing tests
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.GherkleAgent = void 0;
10
+ const ws_1 = __importDefault(require("ws"));
11
+ const playwright_1 = require("./frameworks/playwright");
12
+ const cucumber_subprocess_1 = require("./frameworks/cucumber-subprocess");
13
+ const HEARTBEAT_INTERVAL = 30000; // 30 seconds
14
+ const RECONNECT_DELAY = 5000; // 5 seconds
15
+ class GherkleAgent {
16
+ config;
17
+ ws = null;
18
+ runnerId = null;
19
+ status = 'offline';
20
+ currentRunId = null;
21
+ // Held only while a cucumber-subprocess run is in flight so a 'cancel'
22
+ // ServerMessage can kill the child cleanly.
23
+ currentCucumberExecutor = null;
24
+ heartbeatInterval = null;
25
+ reconnectTimeout = null;
26
+ shouldReconnect = true;
27
+ constructor(config) {
28
+ this.config = config;
29
+ }
30
+ /**
31
+ * Start the agent and connect to Gherkle
32
+ */
33
+ async start() {
34
+ console.log(`šŸš€ Starting Gherkle Runner: ${this.config.name}`);
35
+ console.log(` Connecting to: ${this.config.apiUrl}`);
36
+ await this.connect();
37
+ }
38
+ /**
39
+ * Stop the agent and disconnect
40
+ */
41
+ async stop() {
42
+ console.log('šŸ›‘ Stopping Gherkle Runner...');
43
+ this.shouldReconnect = false;
44
+ if (this.heartbeatInterval) {
45
+ clearInterval(this.heartbeatInterval);
46
+ this.heartbeatInterval = null;
47
+ }
48
+ if (this.reconnectTimeout) {
49
+ clearTimeout(this.reconnectTimeout);
50
+ this.reconnectTimeout = null;
51
+ }
52
+ if (this.ws) {
53
+ this.ws.close();
54
+ this.ws = null;
55
+ }
56
+ this.status = 'offline';
57
+ }
58
+ /**
59
+ * Connect to Gherkle WebSocket server
60
+ */
61
+ async connect() {
62
+ const wsUrl = this.config.apiUrl
63
+ .replace('https://', 'wss://')
64
+ .replace('http://', 'ws://');
65
+ const url = `${wsUrl}/api/runners/ws`;
66
+ // Send the runner token in the Authorization header, not the URL query
67
+ // string — query strings leak into proxy logs, traces, and browser history.
68
+ this.ws = new ws_1.default(url, {
69
+ headers: { Authorization: `Bearer ${this.config.token}` },
70
+ });
71
+ this.ws.on('open', () => {
72
+ console.log('āœ… Connected to Gherkle');
73
+ this.status = 'online';
74
+ this.startHeartbeat();
75
+ });
76
+ this.ws.on('message', (data) => {
77
+ try {
78
+ const message = JSON.parse(data.toString());
79
+ this.handleMessage(message);
80
+ }
81
+ catch (err) {
82
+ console.error('Failed to parse message:', err);
83
+ }
84
+ });
85
+ this.ws.on('close', () => {
86
+ console.log('šŸ”Œ Disconnected from Gherkle');
87
+ this.status = 'offline';
88
+ this.stopHeartbeat();
89
+ if (this.shouldReconnect) {
90
+ console.log(` Reconnecting in ${RECONNECT_DELAY / 1000}s...`);
91
+ this.reconnectTimeout = setTimeout(() => this.connect(), RECONNECT_DELAY);
92
+ }
93
+ });
94
+ this.ws.on('error', (err) => {
95
+ console.error('āŒ WebSocket error:', err.message);
96
+ this.status = 'error';
97
+ });
98
+ }
99
+ /**
100
+ * Handle incoming messages from Gherkle
101
+ */
102
+ async handleMessage(message) {
103
+ switch (message.type) {
104
+ case 'connected':
105
+ this.runnerId = message.runnerId;
106
+ console.log(` Runner ID: ${this.runnerId}`);
107
+ break;
108
+ case 'ack':
109
+ // Heartbeat acknowledged
110
+ break;
111
+ case 'execute':
112
+ await this.executeRun(message.runId, message.features, message.stepDefinitions ?? [], message.env ?? {}, message.config);
113
+ break;
114
+ case 'cancel':
115
+ await this.cancelRun(message.runId);
116
+ break;
117
+ case 'error':
118
+ console.error('Server error:', message.message);
119
+ break;
120
+ }
121
+ }
122
+ /**
123
+ * Send a message to Gherkle
124
+ */
125
+ send(message) {
126
+ if (this.ws && this.ws.readyState === ws_1.default.OPEN) {
127
+ this.ws.send(JSON.stringify(message));
128
+ }
129
+ }
130
+ /**
131
+ * Start heartbeat interval
132
+ */
133
+ startHeartbeat() {
134
+ this.heartbeatInterval = setInterval(() => {
135
+ this.send({
136
+ type: 'heartbeat',
137
+ status: this.status,
138
+ currentRun: this.currentRunId || undefined,
139
+ });
140
+ }, HEARTBEAT_INTERVAL);
141
+ }
142
+ /**
143
+ * Stop heartbeat interval
144
+ */
145
+ stopHeartbeat() {
146
+ if (this.heartbeatInterval) {
147
+ clearInterval(this.heartbeatInterval);
148
+ this.heartbeatInterval = null;
149
+ }
150
+ }
151
+ /**
152
+ * Execute a test run.
153
+ *
154
+ * Two paths:
155
+ * - stepDefinitions non-empty → CucumberSubprocessExecutor (default).
156
+ * The server has already gathered AI-generated step-def code; the
157
+ * runner ships it into a forked Cucumber.js process. No local
158
+ * dependencies on the runner machine beyond what @gherkle/runner
159
+ * itself bundles.
160
+ * - stepDefinitions empty AND testConfig.stepDefinitionsPath set →
161
+ * legacy PlaywrightExecutor (BYO: user keeps step defs on disk).
162
+ * - Otherwise → error the run with a clear message. The server already
163
+ * hard-fails dispatch in this case (D9); this is defense in depth.
164
+ */
165
+ async executeRun(runId, features, stepDefinitions, env, testConfig) {
166
+ // Defensive busy-guard. The server-side dispatch is the proper place
167
+ // to enforce one-run-at-a-time per runner (TODOS P1: per-runner busy
168
+ // reservation in pollAndDispatch). Until that lands, if a second
169
+ // 'execute' arrives mid-run, return an error rather than silently
170
+ // clobbering currentRunId + the in-flight executor handle.
171
+ if (this.currentRunId !== null) {
172
+ console.warn(`āš ļø Refusing concurrent run ${runId}: runner is busy with ${this.currentRunId}`);
173
+ this.send({
174
+ type: 'error',
175
+ runId,
176
+ message: `Runner busy with run ${this.currentRunId}; dispatched without busy-check (TODOS P1).`,
177
+ });
178
+ this.send({
179
+ type: 'run:completed',
180
+ runId,
181
+ summary: { total: 0, passed: 0, failed: 0, skipped: 0, durationMs: 0 },
182
+ });
183
+ return;
184
+ }
185
+ console.log(`\n🧪 Starting test run: ${runId}`);
186
+ console.log(` Features: ${features.length}`);
187
+ console.log(` Framework: ${testConfig.framework}`);
188
+ console.log(` Step-defs: ${stepDefinitions.length} (${stepDefinitions.length > 0 ? 'cucumber-subprocess' : 'BYO playwright'})`);
189
+ this.status = 'busy';
190
+ this.currentRunId = runId;
191
+ this.send({ type: 'run:started', runId });
192
+ const summary = {
193
+ total: 0,
194
+ passed: 0,
195
+ failed: 0,
196
+ skipped: 0,
197
+ durationMs: 0,
198
+ };
199
+ const startTime = Date.now();
200
+ const onScenarioStart = (scenarioId, scenarioName, featureName) => {
201
+ this.send({
202
+ type: 'scenario:started',
203
+ runId,
204
+ scenarioId,
205
+ scenarioName,
206
+ featureName,
207
+ });
208
+ };
209
+ const onStepComplete = (scenarioId, step) => {
210
+ this.send({ type: 'step:completed', runId, scenarioId, step });
211
+ };
212
+ const onScenarioComplete = (scenarioId, status, durationMs, error) => {
213
+ summary.total++;
214
+ if (status === 'passed')
215
+ summary.passed++;
216
+ else if (status === 'failed')
217
+ summary.failed++;
218
+ else if (status === 'skipped')
219
+ summary.skipped++;
220
+ this.send({ type: 'scenario:completed', runId, scenarioId, status, durationMs, error });
221
+ };
222
+ try {
223
+ if (stepDefinitions.length > 0) {
224
+ const executor = new cucumber_subprocess_1.CucumberSubprocessExecutor();
225
+ this.currentCucumberExecutor = executor;
226
+ const results = await executor.executeAll(features, stepDefinitions, env, {
227
+ onScenarioStart,
228
+ onStepComplete,
229
+ onScenarioComplete,
230
+ });
231
+ this.currentCucumberExecutor = null;
232
+ for (const result of results) {
233
+ if (result.artifacts) {
234
+ for (const artifact of result.artifacts) {
235
+ this.send({ type: 'artifact:upload', runId, scenarioId: result.scenarioId, artifact });
236
+ }
237
+ }
238
+ }
239
+ }
240
+ else if (testConfig.stepDefinitionsPath) {
241
+ // BYO fallback: user has step-def code on the runner's local disk.
242
+ const executor = this.getExecutor(testConfig.framework);
243
+ for (const feature of features) {
244
+ const results = await executor.execute(feature, testConfig, {
245
+ onScenarioStart: (scenarioId, scenarioName) => onScenarioStart(scenarioId, scenarioName, feature.name),
246
+ onStepComplete,
247
+ onScenarioComplete,
248
+ });
249
+ for (const result of results) {
250
+ if (result.artifacts) {
251
+ for (const artifact of result.artifacts) {
252
+ this.send({ type: 'artifact:upload', runId, scenarioId: result.scenarioId, artifact });
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ else {
259
+ throw new Error('No step definitions: run carried no generated step-defs and no local stepDefinitionsPath is configured.');
260
+ }
261
+ summary.durationMs = Date.now() - startTime;
262
+ console.log(`\nāœ… Test run complete: ${runId}`);
263
+ console.log(` Passed: ${summary.passed}/${summary.total}`);
264
+ console.log(` Duration: ${summary.durationMs}ms`);
265
+ }
266
+ catch (err) {
267
+ const error = err;
268
+ console.error(`\nāŒ Test run failed: ${runId}`, error.message);
269
+ this.send({
270
+ type: 'error',
271
+ runId,
272
+ message: error.message,
273
+ });
274
+ summary.durationMs = Date.now() - startTime;
275
+ }
276
+ finally {
277
+ this.currentCucumberExecutor = null;
278
+ }
279
+ this.send({ type: 'run:completed', runId, summary });
280
+ this.status = 'online';
281
+ this.currentRunId = null;
282
+ }
283
+ /**
284
+ * Cancel an in-progress run. SIGTERMs the Cucumber subprocess (with a 5s
285
+ * SIGKILL fallback) so the run terminates promptly. The executeRun()
286
+ * promise then resolves naturally: its 'exit' handler returns the
287
+ * partial scenarios it had accumulated, and run:completed flows as usual.
288
+ */
289
+ async cancelRun(runId) {
290
+ if (this.currentRunId !== runId)
291
+ return;
292
+ console.log(`🚫 Canceling run: ${runId}`);
293
+ if (this.currentCucumberExecutor) {
294
+ this.currentCucumberExecutor.cancel();
295
+ }
296
+ // Status/currentRunId reset in executeRun's finally block.
297
+ }
298
+ /**
299
+ * Get the appropriate executor for the framework
300
+ */
301
+ getExecutor(framework) {
302
+ switch (framework) {
303
+ case 'playwright':
304
+ return new playwright_1.PlaywrightExecutor(this.config);
305
+ // TODO: Add Cypress, Cucumber executors
306
+ default:
307
+ throw new Error(`Unsupported framework: ${framework}`);
308
+ }
309
+ }
310
+ }
311
+ exports.GherkleAgent = GherkleAgent;
312
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Configuration loading and validation for @gherkle/runner
3
+ */
4
+ import { Framework } from './types';
5
+ export interface AgentConfig {
6
+ token: string;
7
+ apiUrl: string;
8
+ name: string;
9
+ labels: string[];
10
+ framework: Framework;
11
+ featuresPath: string;
12
+ stepDefinitionsPath: string;
13
+ supportPath: string;
14
+ browsers: string[];
15
+ headless: boolean;
16
+ testTimeout: number;
17
+ stepTimeout: number;
18
+ screenshots: 'always' | 'on-failure' | 'never';
19
+ video: 'always' | 'on-failure' | 'never';
20
+ baseUrl?: string;
21
+ env: Record<string, string>;
22
+ }
23
+ /**
24
+ * Load configuration from file and environment
25
+ */
26
+ export declare function loadConfig(cliOptions?: Partial<AgentConfig>): AgentConfig;
27
+ /**
28
+ * Generate a sample config file
29
+ */
30
+ export declare function generateSampleConfig(): string;
31
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,MAAM,WAAW,WAAW;IAE1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IAGf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IAGjB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IAGpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAGlB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,WAAW,EAAE,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;IAC/C,KAAK,EAAE,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;IAGzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AA2BD;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CA4D7E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAqC7C"}