playwright-e2e-mcp 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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +497 -0
  3. package/dist/http.d.ts +27 -0
  4. package/dist/http.js +156 -0
  5. package/dist/http.js.map +1 -0
  6. package/dist/index.d.ts +12 -0
  7. package/dist/index.js +56 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/server.d.ts +23 -0
  10. package/dist/server.js +225 -0
  11. package/dist/server.js.map +1 -0
  12. package/dist/tools/compare-visual-state.d.ts +77 -0
  13. package/dist/tools/compare-visual-state.js +223 -0
  14. package/dist/tools/compare-visual-state.js.map +1 -0
  15. package/dist/tools/diagnose-flaky.d.ts +87 -0
  16. package/dist/tools/diagnose-flaky.js +258 -0
  17. package/dist/tools/diagnose-flaky.js.map +1 -0
  18. package/dist/tools/generate-e2e-test.d.ts +51 -0
  19. package/dist/tools/generate-e2e-test.js +274 -0
  20. package/dist/tools/generate-e2e-test.js.map +1 -0
  21. package/dist/tools/get-failure.d.ts +26 -0
  22. package/dist/tools/get-failure.js +220 -0
  23. package/dist/tools/get-failure.js.map +1 -0
  24. package/dist/tools/inspect-page.d.ts +57 -0
  25. package/dist/tools/inspect-page.js +124 -0
  26. package/dist/tools/inspect-page.js.map +1 -0
  27. package/dist/tools/list-tests.d.ts +35 -0
  28. package/dist/tools/list-tests.js +88 -0
  29. package/dist/tools/list-tests.js.map +1 -0
  30. package/dist/tools/run-test.d.ts +70 -0
  31. package/dist/tools/run-test.js +169 -0
  32. package/dist/tools/run-test.js.map +1 -0
  33. package/dist/tools/shared.d.ts +86 -0
  34. package/dist/tools/shared.js +490 -0
  35. package/dist/tools/shared.js.map +1 -0
  36. package/dist/tools/validate-selector.d.ts +32 -0
  37. package/dist/tools/validate-selector.js +93 -0
  38. package/dist/tools/validate-selector.js.map +1 -0
  39. package/dist/types/index.d.ts +344 -0
  40. package/dist/types/index.js +51 -0
  41. package/dist/types/index.js.map +1 -0
  42. package/dist/utils/change-analyzer.d.ts +46 -0
  43. package/dist/utils/change-analyzer.js +290 -0
  44. package/dist/utils/change-analyzer.js.map +1 -0
  45. package/dist/utils/image-diff.d.ts +61 -0
  46. package/dist/utils/image-diff.js +373 -0
  47. package/dist/utils/image-diff.js.map +1 -0
  48. package/dist/utils/logger.d.ts +21 -0
  49. package/dist/utils/logger.js +132 -0
  50. package/dist/utils/logger.js.map +1 -0
  51. package/dist/utils/path-utils.d.ts +55 -0
  52. package/dist/utils/path-utils.js +211 -0
  53. package/dist/utils/path-utils.js.map +1 -0
  54. package/dist/utils/playwright-runner.d.ts +63 -0
  55. package/dist/utils/playwright-runner.js +594 -0
  56. package/dist/utils/playwright-runner.js.map +1 -0
  57. package/dist/utils/project-detector.d.ts +43 -0
  58. package/dist/utils/project-detector.js +255 -0
  59. package/dist/utils/project-detector.js.map +1 -0
  60. package/dist/utils/report-parser.d.ts +60 -0
  61. package/dist/utils/report-parser.js +501 -0
  62. package/dist/utils/report-parser.js.map +1 -0
  63. package/dist/utils/trace-reader.d.ts +109 -0
  64. package/dist/utils/trace-reader.js +608 -0
  65. package/dist/utils/trace-reader.js.map +1 -0
  66. package/examples/sample-test.spec.ts +49 -0
  67. package/package.json +66 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Cross-platform path handling.
3
+ *
4
+ * All path logic here is *lexical* (string based, no fs access) so that
5
+ * Windows paths behave correctly when unit tests run on macOS/Linux and
6
+ * vice versa. Backslashes are normalized everywhere, drive letters and
7
+ * UNC prefixes are preserved, and user-supplied paths are sandboxed to
8
+ * the project root to block "../../etc/passwd" style escapes.
9
+ */
10
+ import { randomBytes } from 'node:crypto';
11
+ import os from 'node:os';
12
+ import path from 'node:path';
13
+ import { PlaywrightMcpError } from '../types/index.js';
14
+ const DRIVE_RE = /^[a-zA-Z]:\//;
15
+ /** Schemes like http:// — two+ chars so "C://" (drive) is not caught. */
16
+ const URL_RE = /^[a-zA-Z][a-zA-Z0-9+.-]+:\/\//;
17
+ const TEST_FILE_RE = /\.(spec|test)\.(ts|mts|cts|js|mjs|cjs|tsx|jsx)$/i;
18
+ /** Replace backslashes with slashes, collapsing duplicate separators. */
19
+ export function normalizeSeparators(p) {
20
+ const slashed = p.replace(/\\/g, '/');
21
+ const isUnc = slashed.startsWith('//');
22
+ const collapsed = slashed.replace(/\/{2,}/g, '/');
23
+ if (isUnc && !DRIVE_RE.test(collapsed))
24
+ return `/${collapsed}`;
25
+ return collapsed;
26
+ }
27
+ /** True when the path is Windows-style (drive letter or UNC). */
28
+ export function isWindowsPath(p) {
29
+ const s = normalizeSeparators(p);
30
+ return DRIVE_RE.test(s) || s.startsWith('//');
31
+ }
32
+ function isCaseInsensitive(p) {
33
+ const s = normalizeSeparators(p);
34
+ return DRIVE_RE.test(s) || s.startsWith('//');
35
+ }
36
+ /** True for absolute paths on either platform (/, C:/ or //unc). */
37
+ export function isAbsolutePath(p) {
38
+ const s = normalizeSeparators(p);
39
+ return s.startsWith('/') || DRIVE_RE.test(s);
40
+ }
41
+ /**
42
+ * Normalize separators and collapse `.` / `..` segments lexically.
43
+ * Leading `..` on relative paths is preserved; escapes above an absolute
44
+ * root (/, C:/, //server) are dropped.
45
+ */
46
+ export function normalizePath(p) {
47
+ const s = normalizeSeparators(p);
48
+ let root = '';
49
+ let rest = s;
50
+ if (DRIVE_RE.test(s)) {
51
+ root = s.slice(0, 3); // "C:/"
52
+ rest = s.slice(3);
53
+ }
54
+ else if (s.startsWith('//')) {
55
+ root = '//';
56
+ rest = s.slice(2);
57
+ }
58
+ else if (s.startsWith('/')) {
59
+ root = '/';
60
+ rest = s.slice(1);
61
+ }
62
+ const out = [];
63
+ for (const segment of rest.split('/')) {
64
+ if (segment === '' || segment === '.')
65
+ continue;
66
+ if (segment === '..') {
67
+ const top = out[out.length - 1];
68
+ if (out.length > 0 && top !== '..') {
69
+ out.pop();
70
+ }
71
+ else if (root === '') {
72
+ out.push('..');
73
+ }
74
+ continue;
75
+ }
76
+ out.push(segment);
77
+ }
78
+ return root + out.join('/');
79
+ }
80
+ /** Resolve `target` against `base` (both normalized lexically). */
81
+ export function resolvePath(base, target) {
82
+ const normalizedTarget = normalizePath(target);
83
+ if (isAbsolutePath(normalizedTarget))
84
+ return normalizedTarget;
85
+ const normalizedBase = normalizePath(base);
86
+ if (normalizedBase === '')
87
+ return normalizedPathJoin(normalizedTarget);
88
+ return normalizePath(`${normalizedBase}/${normalizedTarget}`);
89
+ }
90
+ function normalizedPathJoin(p) {
91
+ return p === '' ? '.' : p;
92
+ }
93
+ /** Lexical containment check (case-insensitive for drive/UNC paths). */
94
+ export function isPathInside(child, parent) {
95
+ const c = normalizePath(child);
96
+ const p = normalizePath(parent);
97
+ if (c === '' || p === '')
98
+ return false;
99
+ const insensitive = isCaseInsensitive(c) || isCaseInsensitive(p);
100
+ const cc = insensitive ? c.toLowerCase() : c;
101
+ const pp = insensitive ? p.toLowerCase() : p;
102
+ if (cc === pp)
103
+ return true;
104
+ const prefix = pp.endsWith('/') ? pp : `${pp}/`;
105
+ return cc.startsWith(prefix);
106
+ }
107
+ /** Expand a leading `~` to the user's home directory. */
108
+ export function expandHome(p) {
109
+ if (p === '~')
110
+ return os.homedir();
111
+ if (p.startsWith('~/') || p.startsWith('~\\')) {
112
+ return os.homedir() + p.slice(1);
113
+ }
114
+ return p;
115
+ }
116
+ /**
117
+ * Sandbox a user-supplied path to the project root.
118
+ *
119
+ * Accepts relative or absolute inputs, expands `~`, normalizes
120
+ * separators, then verifies the result stays inside `projectRoot`.
121
+ * Throws PlaywrightMcpError(INVALID_PATH) for traversal escapes,
122
+ * absolute paths outside the root, URLs, null bytes, and empty values.
123
+ *
124
+ * @returns Normalized absolute path with forward slashes.
125
+ */
126
+ export function sanitizeUserPath(input, projectRoot) {
127
+ if (typeof input !== 'string') {
128
+ throw new PlaywrightMcpError('Path must be a string', 'INVALID_PATH', {
129
+ hint: 'Pass a path relative to the project root, e.g. "tests/login.spec.ts".',
130
+ });
131
+ }
132
+ const raw = input.trim();
133
+ if (raw === '') {
134
+ throw new PlaywrightMcpError('Path must not be empty', 'INVALID_PATH', {
135
+ hint: 'Pass a path relative to the project root, e.g. "tests/login.spec.ts".',
136
+ });
137
+ }
138
+ if (raw.includes('\0')) {
139
+ throw new PlaywrightMcpError('Path contains a null byte', 'INVALID_PATH', {
140
+ hint: 'Remove null bytes from the path.',
141
+ });
142
+ }
143
+ if (URL_RE.test(raw)) {
144
+ throw new PlaywrightMcpError(`"${raw}" looks like a URL, not a filesystem path`, 'INVALID_PATH', {
145
+ hint: 'Pass a local path relative to the project root.',
146
+ });
147
+ }
148
+ const root = normalizePath(projectRoot);
149
+ if (!isAbsolutePath(root)) {
150
+ throw new PlaywrightMcpError(`Project root must be absolute, got "${projectRoot}"`, 'INVALID_PATH');
151
+ }
152
+ const expanded = normalizePath(expandHome(raw));
153
+ const resolved = resolvePath(root, expanded);
154
+ if (!isPathInside(resolved, root)) {
155
+ throw new PlaywrightMcpError(`Path "${raw}" resolves outside the project root`, 'INVALID_PATH', {
156
+ hint: `Only paths inside ${root} are allowed. Directory traversal (..), absolute paths outside the project, and symlinks out of the project are rejected.`,
157
+ details: `resolved=${resolved}`,
158
+ });
159
+ }
160
+ return resolved;
161
+ }
162
+ /** Convert a normalized path to the host platform's native form. */
163
+ export function toNativePath(p) {
164
+ const normalized = normalizePath(p);
165
+ return process.platform === 'win32' ? path.win32.normalize(normalized) : path.posix.normalize(normalized);
166
+ }
167
+ /** Always-forward-slash form (used in messages and tool output). */
168
+ export function toPosixPath(p) {
169
+ return normalizePath(p);
170
+ }
171
+ /** Path of `p` relative to `root`, posix style; absolute if not inside. */
172
+ export function relativeToRoot(root, p) {
173
+ const r = normalizePath(root);
174
+ const c = normalizePath(p);
175
+ if (!isPathInside(c, r))
176
+ return c;
177
+ if (c === r)
178
+ return '';
179
+ const base = r.endsWith('/') ? r : `${r}/`;
180
+ return c.slice(base.length);
181
+ }
182
+ /** Build an absolute path under the project root. */
183
+ export function joinProjectPath(root, ...segments) {
184
+ return resolvePath(root, segments.join('/'));
185
+ }
186
+ /** A unique path inside the OS temp dir (used for JSON reports). */
187
+ export function tempFilePath(prefix, extension = '.json') {
188
+ const unique = `${Date.now().toString(36)}-${randomBytes(6).toString('hex')}`;
189
+ return normalizePath(path.join(os.tmpdir(), `${prefix}-${unique}${extension}`));
190
+ }
191
+ /** True when a filename looks like a Playwright test/spec file. */
192
+ export function isTestFile(p) {
193
+ return TEST_FILE_RE.test(normalizeSeparators(p));
194
+ }
195
+ /**
196
+ * Validate a free-form CLI argument list: rejects NUL bytes and
197
+ * shell-looking metacharacters that could smuggle extra commands.
198
+ */
199
+ export function sanitizeCliArg(arg) {
200
+ const raw = typeof arg === 'string' ? arg.trim() : '';
201
+ if (raw === '') {
202
+ throw new PlaywrightMcpError('Argument must not be empty', 'INVALID_PATH');
203
+ }
204
+ if (/[\0;&|><`$]/.test(raw)) {
205
+ throw new PlaywrightMcpError(`Argument "${raw}" contains forbidden shell characters`, 'INVALID_PATH', {
206
+ hint: 'Arguments are executed directly (no shell); remove ; & | > < ` $ characters.',
207
+ });
208
+ }
209
+ return raw;
210
+ }
211
+ //# sourceMappingURL=path-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Core Playwright execution logic.
3
+ *
4
+ * Runs the project's local Playwright CLI as a child process (never a
5
+ * shell), streams and caps its output, enforces a hard wall-clock
6
+ * timeout with process-*group* cleanup, collects the JSON report, and
7
+ * converts every failure mode — missing install, dead dev server,
8
+ * syntax error, browser crash, full disk, client disconnect — into a
9
+ * structured result.
10
+ */
11
+ import type { ListTestsOptions, ListTestsResult, RunTestOptions, RunTestResult } from '../types/index.js';
12
+ /**
13
+ * Locate the project's local Playwright CLI (playwright/cli.js), which
14
+ * we invoke directly with `node` — no shell, no npx, cross-platform.
15
+ */
16
+ export declare function resolvePlaywrightCli(projectRoot: string): Promise<string | null>;
17
+ export interface RunProcessOptions {
18
+ cwd: string;
19
+ env: NodeJS.ProcessEnv;
20
+ timeoutMs: number;
21
+ signal?: AbortSignal;
22
+ }
23
+ export interface ProcessOutcome {
24
+ code: number | null;
25
+ signalName: NodeJS.Signals | null;
26
+ stdout: string;
27
+ stderr: string;
28
+ timedOut: boolean;
29
+ aborted: boolean;
30
+ spawnError: {
31
+ code: string;
32
+ message: string;
33
+ } | null;
34
+ }
35
+ /**
36
+ * Spawn a process with output capping, tree-kill timeout and abort.
37
+ * Children are tracked so shutdown/disconnect can never orphan them.
38
+ */
39
+ export declare function runProcess(command: string, args: string[], options: RunProcessOptions): Promise<ProcessOutcome>;
40
+ /**
41
+ * Force-kill every child still running (and its tree). Called on
42
+ * shutdown and when the MCP client disconnects so no browser or test
43
+ * worker outlives the server.
44
+ */
45
+ export declare function killActiveChildren(): number;
46
+ /**
47
+ * Execute Playwright tests and return a structured result. Throws
48
+ * PlaywrightMcpError only for precondition failures (no Playwright
49
+ * installed, bad paths); test failures come back as data.
50
+ */
51
+ export declare function runTests(options: RunTestOptions): Promise<RunTestResult>;
52
+ /** List tests via `playwright test --list`, falling back to file scan. */
53
+ export declare function listTests(options: ListTestsOptions): Promise<ListTestsResult>;
54
+ export interface ServerProbe {
55
+ reachable: boolean;
56
+ status?: number;
57
+ error?: string;
58
+ }
59
+ /**
60
+ * Quick reachability check for the app under test, used to tell the
61
+ * user "start your dev server" instead of surfacing ECONNREFUSED.
62
+ */
63
+ export declare function probeServer(url: string, timeoutMs?: number): Promise<ServerProbe>;