playwright-zed-language-server 0.0.0-stage → 0.2.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
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Radek Bednarik
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 CHANGED
@@ -1,3 +1,25 @@
1
- # Temporary Holding Version
1
+ # playwright-zed-language-server
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Language server behind the [Playwright for Zed](https://github.com/radekBednarik/playwright-zed)
4
+ extension. The Zed extension installs this package from npm at runtime; you do not need to
5
+ install it yourself.
6
+
7
+ It detects Playwright workspaces, discovers tests through `playwright test --list`, and runs
8
+ tests with the `@playwright/test` package installed in your project, reporting results back to
9
+ the editor over the Language Server Protocol.
10
+
11
+ Usage: `playwright-zed-language-server --stdio`.
12
+
13
+ This is an independent community project, not affiliated with, endorsed by, or maintained by
14
+ Microsoft or the Playwright team. "Playwright" is a trademark of Microsoft Corporation. The
15
+ package contains no Playwright code and does not bundle Playwright.
16
+
17
+ **Work in progress.** This is the first slice of the extension (detection, run at cursor,
18
+ run file, re-run last). Expect breaking changes between minor versions; the extension pins the
19
+ exact server version it was built against.
20
+
21
+ **Built with AI assistance.** The server, like the rest of the extension, is developed with
22
+ AI assistance throughout, using GitHub Spec Kit driven by Claude Code with the Claude models
23
+ Fable and Opus, with maintainer review and recorded verification for every feature.
24
+
25
+ License: MIT.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // Entry point published to npm. Loads the compiled server from dist/.
4
+ require('../dist/server.js');
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ALL_COMMANDS = exports.COMMAND_ENABLE_DISCOVERY = exports.COMMAND_RERUN_LAST = exports.COMMAND_RUN_FILE = exports.COMMAND_RUN_AT_CURSOR = void 0;
37
+ exports.resolveTestLocation = resolveTestLocation;
38
+ exports.buildRunArgs = buildRunArgs;
39
+ exports.countSelectedTests = countSelectedTests;
40
+ const path = __importStar(require("node:path"));
41
+ exports.COMMAND_RUN_AT_CURSOR = 'playwright.runAtCursor';
42
+ exports.COMMAND_RUN_FILE = 'playwright.runFile';
43
+ exports.COMMAND_RERUN_LAST = 'playwright.rerunLast';
44
+ exports.COMMAND_ENABLE_DISCOVERY = 'playwright.enableDiscovery';
45
+ exports.ALL_COMMANDS = [exports.COMMAND_RUN_AT_CURSOR, exports.COMMAND_RUN_FILE, exports.COMMAND_RERUN_LAST, exports.COMMAND_ENABLE_DISCOVERY];
46
+ /**
47
+ * Resolves what the cursor points at (data-model "TestLocation").
48
+ *
49
+ * 1. A test's span starts at its title line and ends on the line before the next test or
50
+ * describe title line in the same file; the last test's span extends to end of file.
51
+ * Cursor inside a span, or on the title line, means kind `test`.
52
+ * 2. Else, cursor exactly on a describe title line means kind `describe`.
53
+ * 3. Else kind `file`.
54
+ *
55
+ * `cursorLine` is 1-based.
56
+ */
57
+ function resolveTestLocation(tests, file, cursorLine) {
58
+ const inFile = tests.filter((t) => t.file === file);
59
+ const testLines = Array.from(new Set(inFile.map((t) => t.line))).sort((a, b) => a - b);
60
+ const describeLines = new Set(inFile.flatMap((t) => t.describeLines));
61
+ let enclosingTestLine = null;
62
+ for (const line of testLines) {
63
+ if (line <= cursorLine)
64
+ enclosingTestLine = line;
65
+ else
66
+ break;
67
+ }
68
+ if (enclosingTestLine !== null) {
69
+ // A describe title strictly between the test line and the cursor ends the test's span.
70
+ let boundaryCrossed = false;
71
+ for (const d of describeLines) {
72
+ if (d > enclosingTestLine && d <= cursorLine) {
73
+ boundaryCrossed = true;
74
+ break;
75
+ }
76
+ }
77
+ if (!boundaryCrossed)
78
+ return { kind: 'test', file, line: enclosingTestLine };
79
+ }
80
+ if (describeLines.has(cursorLine))
81
+ return { kind: 'describe', file, line: cursorLine };
82
+ return { kind: 'file', file, line: null };
83
+ }
84
+ /** CLI arguments for a run, per contracts/playwright-cli.md. */
85
+ function buildRunArgs(location, config) {
86
+ let target = path.relative(config.configDir, location.file);
87
+ if (location.kind !== 'file' && location.line !== null)
88
+ target = `${target}:${location.line}`;
89
+ return ['test', target, '-c', config.configPath, '--reporter=list,json'];
90
+ }
91
+ /** Number of discovered tests a location selects, used for progress messages. */
92
+ function countSelectedTests(tests, location) {
93
+ const inFile = tests.filter((t) => t.file === location.file);
94
+ if (location.kind === 'file')
95
+ return inFile.length;
96
+ if (location.kind === 'test')
97
+ return inFile.filter((t) => t.line === location.line).length;
98
+ return inFile.filter((t) => t.describeLines.includes(location.line)).length;
99
+ }
100
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseListReport = parseListReport;
37
+ exports.runList = runList;
38
+ const path = __importStar(require("node:path"));
39
+ const spawn_1 = require("./spawn");
40
+ /** Flattens Playwright's `--list --reporter=json` output into discovered tests. */
41
+ function parseListReport(json) {
42
+ const report = (json ?? {});
43
+ const rootDir = report.config?.rootDir ?? '';
44
+ const testDirs = Array.from(new Set((report.config?.projects ?? []).map((p) => p.testDir).filter((d) => !!d)));
45
+ const tests = [];
46
+ const walk = (suite, describeTitles, describeLines) => {
47
+ const isDescribe = suite.line > 0;
48
+ const titles = isDescribe ? [...describeTitles, suite.title] : describeTitles;
49
+ const lines = isDescribe ? [...describeLines, suite.line] : describeLines;
50
+ for (const spec of suite.specs ?? []) {
51
+ tests.push({
52
+ file: path.resolve(rootDir, spec.file),
53
+ line: spec.line,
54
+ column: spec.column,
55
+ title: spec.title,
56
+ titlePath: [...titles, spec.title],
57
+ describeLines: lines,
58
+ projects: (spec.tests ?? []).map((t) => t.projectName ?? '').filter((n) => n !== ''),
59
+ });
60
+ }
61
+ for (const child of suite.suites ?? [])
62
+ walk(child, titles, lines);
63
+ };
64
+ for (const suite of report.suites ?? [])
65
+ walk(suite, [], []);
66
+ tests.sort((a, b) => (a.file === b.file ? a.line - b.line || a.column - b.column : a.file.localeCompare(b.file)));
67
+ return { rootDir, testDirs, tests };
68
+ }
69
+ let listCounter = 0;
70
+ /** Runs discovery for one config and stores the result on it. Returns the CLI error text, if any. */
71
+ async function runList(config, spawnFn = spawn_1.runPlaywright) {
72
+ config.discoveryState = 'running';
73
+ config.discoveryError = undefined;
74
+ const id = String(++listCounter);
75
+ const handle = spawnFn({
76
+ cli: config.playwrightCli,
77
+ args: ['test', '--list', '--reporter=json', '-c', config.configPath],
78
+ cwd: config.configDir,
79
+ env: { CI: '1' },
80
+ reportFile: (0, spawn_1.reportFilePath)('list', id),
81
+ });
82
+ const outcome = await handle.promise;
83
+ if (outcome.spawnError || outcome.report === null) {
84
+ const detail = outcome.spawnError ?? (outcome.stderr.trim() || outcome.stdout.trim() || `exit code ${outcome.code}`);
85
+ config.discoveryState = 'error';
86
+ config.discoveryError = `${outcome.command}\n${detail}`;
87
+ return config.discoveryError;
88
+ }
89
+ const parsed = parseListReport(outcome.report);
90
+ config.rootDir = parsed.rootDir;
91
+ config.testDirs = parsed.testDirs;
92
+ config.tests = parsed.tests;
93
+ config.discoveryState = 'idle';
94
+ return null;
95
+ }
96
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Reporter = exports.DISCOVERY_NOT_NOW = exports.DISCOVERY_RUN = exports.DIAGNOSTIC_SOURCE = void 0;
4
+ const node_1 = require("vscode-languageserver/node");
5
+ const node_url_1 = require("node:url");
6
+ exports.DIAGNOSTIC_SOURCE = 'playwright';
7
+ exports.DISCOVERY_RUN = 'Run discovery';
8
+ exports.DISCOVERY_NOT_NOW = 'Not now';
9
+ /** Thin wrappers over the LSP channels Zed renders (progress, messages, diagnostics, log). */
10
+ class Reporter {
11
+ connection;
12
+ constructor(connection) {
13
+ this.connection = connection;
14
+ }
15
+ /**
16
+ * Starts a `$/progress` sequence whose token is the run request id, as the contract states.
17
+ * Returns false when the client refuses to create the token; progress is then skipped.
18
+ */
19
+ async progressBegin(token, testCount, file) {
20
+ try {
21
+ await this.connection.sendRequest(node_1.WorkDoneProgressCreateRequest.type, { token });
22
+ }
23
+ catch {
24
+ return false;
25
+ }
26
+ void this.connection.sendProgress(node_1.WorkDoneProgress.type, token, {
27
+ kind: 'begin',
28
+ title: 'Playwright',
29
+ message: `Running ${testCount} test(s) in ${file}`,
30
+ });
31
+ return true;
32
+ }
33
+ progressEnd(token, active, summary) {
34
+ if (!active)
35
+ return;
36
+ void this.connection.sendProgress(node_1.WorkDoneProgress.type, token, { kind: 'report', message: summary });
37
+ void this.connection.sendProgress(node_1.WorkDoneProgress.type, token, { kind: 'end', message: summary });
38
+ }
39
+ /**
40
+ * Asks, once per workspace per session, whether discovery may run (feature 002). Resolves to
41
+ * the chosen action title, or null when the client answers without a selection. Rejects when
42
+ * the client cannot show the request. Zed never answers a dismissed prompt, so callers must
43
+ * not await this on the discovery path.
44
+ */
45
+ askDiscovery(folderName, folderPath) {
46
+ const message = `Playwright for Zed found a Playwright configuration in ${folderName} (${folderPath}). ` +
47
+ 'Run test discovery? Discovery executes this workspace\'s Playwright configuration and test files with your user account. ' +
48
+ 'You can enable it later with "Playwright: Enable test discovery" from the code actions menu.';
49
+ return this.connection.window
50
+ .showWarningMessage(message, { title: exports.DISCOVERY_RUN }, { title: exports.DISCOVERY_NOT_NOW })
51
+ .then((choice) => (choice ? choice.title : null));
52
+ }
53
+ /** Sends the `window/showMessage` notification (the library helpers would send a request). */
54
+ showMessage(type, message) {
55
+ void this.connection.sendNotification(node_1.ShowMessageNotification.type, { type, message });
56
+ }
57
+ showInfo(message) {
58
+ this.showMessage(node_1.MessageType.Info, message);
59
+ }
60
+ showWarning(message) {
61
+ this.showMessage(node_1.MessageType.Warning, message);
62
+ }
63
+ showError(message) {
64
+ this.showMessage(node_1.MessageType.Error, message);
65
+ }
66
+ /** Publishes one Error diagnostic per failure, grouped by file. */
67
+ publishFailures(failures) {
68
+ const byFile = new Map();
69
+ for (const failure of failures) {
70
+ const line = Math.max(0, failure.line - 1);
71
+ const character = Math.max(0, failure.column - 1);
72
+ const diagnostic = {
73
+ range: { start: { line, character }, end: { line, character: character + 1 } },
74
+ severity: node_1.DiagnosticSeverity.Error,
75
+ source: exports.DIAGNOSTIC_SOURCE,
76
+ message: `${failure.title}: ${failure.message}`,
77
+ };
78
+ const list = byFile.get(failure.file) ?? [];
79
+ list.push(diagnostic);
80
+ byFile.set(failure.file, list);
81
+ }
82
+ for (const [file, diagnostics] of byFile) {
83
+ void this.connection.sendDiagnostics({ uri: (0, node_url_1.pathToFileURL)(file).toString(), diagnostics });
84
+ }
85
+ return Array.from(byFile.keys());
86
+ }
87
+ clearDiagnostics(files) {
88
+ for (const file of files) {
89
+ void this.connection.sendDiagnostics({ uri: (0, node_url_1.pathToFileURL)(file).toString(), diagnostics: [] });
90
+ }
91
+ }
92
+ clearDiagnosticsForUri(uri) {
93
+ void this.connection.sendDiagnostics({ uri, diagnostics: [] });
94
+ }
95
+ log(line) {
96
+ this.connection.console.log(line);
97
+ }
98
+ info(line) {
99
+ this.connection.console.info(line);
100
+ }
101
+ async refreshCodeLenses() {
102
+ try {
103
+ await this.connection.sendRequest(node_1.CodeLensRefreshRequest.type);
104
+ }
105
+ catch {
106
+ // client without refresh support
107
+ }
108
+ }
109
+ }
110
+ exports.Reporter = Reporter;
111
+ //# sourceMappingURL=reporting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporting.js","sourceRoot":"","sources":["../src/reporting.ts"],"names":[],"mappings":"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"}
package/dist/runner.js ADDED
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.RunManager = void 0;
37
+ exports.stripAnsi = stripAnsi;
38
+ exports.parseRunReport = parseRunReport;
39
+ exports.mapExitCode = mapExitCode;
40
+ exports.summarize = summarize;
41
+ exports.emptyCounts = emptyCounts;
42
+ const path = __importStar(require("node:path"));
43
+ const spawn_1 = require("./spawn");
44
+ const commands_1 = require("./commands");
45
+ const ANSI = /\u001b\[[0-9;]*[A-Za-z]/g;
46
+ function stripAnsi(text) {
47
+ return text.replace(ANSI, '');
48
+ }
49
+ /** Extracts counts and failures from a `--reporter=json` run report. */
50
+ function parseRunReport(json) {
51
+ const report = (json ?? {});
52
+ const rootDir = report.config?.rootDir ?? '';
53
+ const counts = {
54
+ expected: report.stats?.expected ?? 0,
55
+ unexpected: report.stats?.unexpected ?? 0,
56
+ skipped: report.stats?.skipped ?? 0,
57
+ flaky: report.stats?.flaky ?? 0,
58
+ };
59
+ const failures = [];
60
+ const walk = (suite) => {
61
+ for (const spec of suite.specs ?? []) {
62
+ if (spec.ok !== false)
63
+ continue;
64
+ const result = (spec.tests ?? [])
65
+ .flatMap((t) => t.results ?? [])
66
+ .find((r) => r.error) ?? (spec.tests ?? []).flatMap((t) => t.results ?? []).at(-1);
67
+ const rawMessage = result?.error?.message ?? 'Test failed without an error message';
68
+ const fullMessage = stripAnsi(rawMessage).trim();
69
+ const loc = result?.error?.location;
70
+ failures.push({
71
+ file: loc?.file ?? path.resolve(rootDir, spec.file),
72
+ line: loc?.line ?? spec.line,
73
+ column: loc?.column ?? spec.column,
74
+ title: spec.title,
75
+ message: fullMessage.split('\n')[0] ?? fullMessage,
76
+ fullMessage,
77
+ });
78
+ }
79
+ for (const child of suite.suites ?? [])
80
+ walk(child);
81
+ };
82
+ for (const suite of report.suites ?? [])
83
+ walk(suite);
84
+ const durationMs = typeof report.stats?.duration === 'number' ? report.stats.duration : null;
85
+ return { counts, failures, durationMs };
86
+ }
87
+ /** 0 passed, 1 with a report failed, anything else is a run error. */
88
+ function mapExitCode(code, hasReport) {
89
+ if (code === 0)
90
+ return 'passed';
91
+ if (code === 1 && hasReport)
92
+ return 'failed';
93
+ return 'error';
94
+ }
95
+ /** `3 passed, 0 failed, 1 skipped (1.2s)`; the duration is Playwright's own measurement. */
96
+ function summarize(counts, durationMs = null) {
97
+ const base = `${counts.expected} passed, ${counts.unexpected} failed, ${counts.skipped} skipped`;
98
+ return durationMs === null ? base : `${base} (${(durationMs / 1000).toFixed(1)}s)`;
99
+ }
100
+ function emptyCounts() {
101
+ return { expected: 0, unexpected: 0, skipped: 0, flaky: 0 };
102
+ }
103
+ /** One running Playwright process per workspace; a new request cancels the running one. */
104
+ class RunManager {
105
+ spawnFn;
106
+ active = null;
107
+ counter = 0;
108
+ constructor(spawnFn = spawn_1.runPlaywright) {
109
+ this.spawnFn = spawnFn;
110
+ }
111
+ nextId() {
112
+ return String(++this.counter);
113
+ }
114
+ get running() {
115
+ return this.active?.request ?? null;
116
+ }
117
+ /** Cancels the active run, if any, and returns its request. */
118
+ cancelActive() {
119
+ if (!this.active)
120
+ return null;
121
+ const { request, handle } = this.active;
122
+ handle.cancel();
123
+ return request;
124
+ }
125
+ async start(request) {
126
+ this.cancelActive();
127
+ const config = request.config;
128
+ const handle = this.spawnFn({
129
+ cli: config.playwrightCli,
130
+ args: (0, commands_1.buildRunArgs)(request.location, config),
131
+ cwd: config.configDir,
132
+ env: { FORCE_COLOR: '0' },
133
+ reportFile: (0, spawn_1.reportFilePath)('run', request.id),
134
+ });
135
+ const entry = { request, handle };
136
+ this.active = entry;
137
+ const outcome = await handle.promise;
138
+ if (this.active === entry)
139
+ this.active = null;
140
+ const rawOutput = `${outcome.stdout}${outcome.stderr ? `\n${outcome.stderr}` : ''}`;
141
+ const base = { request, rawOutput, command: outcome.command, failures: [], counts: emptyCounts(), durationMs: null };
142
+ if (outcome.cancelled)
143
+ return { ...base, status: 'cancelled' };
144
+ if (outcome.spawnError)
145
+ return { ...base, status: 'error', errorMessage: outcome.spawnError };
146
+ const status = mapExitCode(outcome.code, outcome.report !== null);
147
+ if (status === 'error') {
148
+ const detail = outcome.stderr.trim() || outcome.stdout.trim() || `exit code ${outcome.code}`;
149
+ return { ...base, status, errorMessage: stripAnsi(detail) };
150
+ }
151
+ const parsed = parseRunReport(outcome.report);
152
+ return { ...base, status, counts: parsed.counts, failures: parsed.failures, durationMs: parsed.durationMs };
153
+ }
154
+ }
155
+ exports.RunManager = RunManager;
156
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}