ptywright 0.3.0 → 0.5.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 +76 -31
- package/dist/agent.mjs +2 -2
- package/dist/bin/ptywright.mjs +1 -1
- package/dist/{cli-CfvlbRoZ.mjs → cli-PnG6UR43.mjs} +2390 -2309
- package/dist/cli.mjs +1 -1
- package/dist/config-bGg636EW.mjs +52 -0
- package/dist/config.mjs +2 -0
- package/dist/env-DPYHo-zH.mjs +36 -0
- package/dist/index.mjs +1 -1
- package/dist/manifest_files-DW80c1H7.mjs +77 -0
- package/dist/mcp.mjs +1 -1
- package/dist/pty-cassette.mjs +1 -1
- package/dist/{runner-zi0nItvB.mjs → runner-C1gPRyCM.mjs} +2002 -1038
- package/dist/{runner-zApMYWZx.mjs → runner-wW_DCBX7.mjs} +1576 -1422
- package/dist/script.mjs +1 -1
- package/dist/{server-BC3yo-dq.mjs → server-DMnnXjWv.mjs} +2643 -2527
- package/dist/session.mjs +1 -1
- package/dist/{terminal_session-DopC7Xg6.mjs → terminal_session-DJKr-O3X.mjs} +349 -328
- package/package.json +3 -1
- package/skills/ptywright-testing/SKILL.md +113 -79
- package/skills/ptywright-testing/agents/openai.yaml +4 -0
- package/skills/ptywright-testing/references/agent-regression.md +132 -0
- package/skills/ptywright-testing/references/ci-and-debugging.md +95 -0
- package/skills/ptywright-testing/references/mcp-tools.md +91 -0
- package/skills/ptywright-testing/references/raw-pty-cassettes.md +82 -0
- package/skills/ptywright-testing/references/script-runner.md +80 -0
- package/dist/{pty_like-Cpkh_O9B.mjs → pty_like-BjeBibSL.mjs} +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as main } from "./cli-
|
|
1
|
+
import { t as main } from "./cli-PnG6UR43.mjs";
|
|
2
2
|
export { main };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
//#region src/config.ts
|
|
5
|
+
const CONFIG_FILE_NAMES = [
|
|
6
|
+
"ptywright.config.ts",
|
|
7
|
+
"ptywright.config.mts",
|
|
8
|
+
"ptywright.config.cts",
|
|
9
|
+
"ptywright.config.js",
|
|
10
|
+
"ptywright.config.mjs",
|
|
11
|
+
"ptywright.config.cjs"
|
|
12
|
+
];
|
|
13
|
+
function defineConfig(config) {
|
|
14
|
+
return config;
|
|
15
|
+
}
|
|
16
|
+
async function loadPtywrightConfig(options = {}) {
|
|
17
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
18
|
+
const configPath = resolveConfigPath({
|
|
19
|
+
cwd,
|
|
20
|
+
configPath: options.configPath
|
|
21
|
+
});
|
|
22
|
+
if (!configPath) return { rootDir: cwd };
|
|
23
|
+
const mod = await import(`${pathToFileURL(configPath).href}?t=${Date.now()}`);
|
|
24
|
+
return {
|
|
25
|
+
...normalizePtywrightConfig(mod.default ?? mod.config, configPath),
|
|
26
|
+
configPath,
|
|
27
|
+
rootDir: dirname(configPath)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function resolveConfigPath(options) {
|
|
31
|
+
if (options.configPath) {
|
|
32
|
+
const explicitPath = isAbsolute(options.configPath) ? options.configPath : resolve(options.cwd, options.configPath);
|
|
33
|
+
if (!existsSync(explicitPath)) throw new Error(`ptywright config not found: ${options.configPath}`);
|
|
34
|
+
return explicitPath;
|
|
35
|
+
}
|
|
36
|
+
let current = options.cwd;
|
|
37
|
+
while (true) {
|
|
38
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
39
|
+
const candidate = resolve(current, fileName);
|
|
40
|
+
if (existsSync(candidate)) return candidate;
|
|
41
|
+
}
|
|
42
|
+
const parent = dirname(current);
|
|
43
|
+
if (parent === current) return;
|
|
44
|
+
current = parent;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function normalizePtywrightConfig(input, configPath) {
|
|
48
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error(`invalid ptywright config: expected object in ${configPath}`);
|
|
49
|
+
return input;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { loadPtywrightConfig as n, defineConfig as t };
|
package/dist/config.mjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
2
|
+
//#region src/common/path.ts
|
|
3
|
+
function samePath(left, right) {
|
|
4
|
+
return resolve(process.cwd(), left) === resolve(process.cwd(), right);
|
|
5
|
+
}
|
|
6
|
+
function portablePath(path, rootDir) {
|
|
7
|
+
const rel = relative(rootDir, path);
|
|
8
|
+
if (rel && !rel.startsWith("..") && !isAbsolute(rel)) return rel;
|
|
9
|
+
return path;
|
|
10
|
+
}
|
|
11
|
+
function portableCliPath(path) {
|
|
12
|
+
return portablePath(resolve(process.cwd(), path), process.cwd());
|
|
13
|
+
}
|
|
14
|
+
function normalizePath(path) {
|
|
15
|
+
return path.replace(/\\/g, "/");
|
|
16
|
+
}
|
|
17
|
+
function relativeHref(fromFile, toFile) {
|
|
18
|
+
const normalized = normalizePath(relative(dirname(fromFile), toFile));
|
|
19
|
+
return normalized.startsWith(".") ? normalized : `./${normalized}`;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/common/env.ts
|
|
23
|
+
function envTruthy(value) {
|
|
24
|
+
if (!value?.trim()) return false;
|
|
25
|
+
const normalized = value.trim().toLowerCase();
|
|
26
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
27
|
+
}
|
|
28
|
+
function mergeProcessEnv(base, override) {
|
|
29
|
+
const env = {};
|
|
30
|
+
for (const [key, value] of Object.entries(process.env)) if (typeof value === "string") env[key] = value;
|
|
31
|
+
for (const [key, value] of Object.entries(base)) env[key] = value;
|
|
32
|
+
if (override) for (const [key, value] of Object.entries(override)) env[key] = value;
|
|
33
|
+
return env;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { portablePath as a, portableCliPath as i, mergeProcessEnv as n, relativeHref as o, normalizePath as r, samePath as s, envTruthy as t };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createPtywrightServer } from "./server-
|
|
1
|
+
import { t as createPtywrightServer } from "./server-DMnnXjWv.mjs";
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
const { server, sessions } = createPtywrightServer();
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { a as portablePath } from "./env-DPYHo-zH.mjs";
|
|
2
|
+
import { readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
//#region src/common/compare.ts
|
|
6
|
+
function sameStringList(left, right) {
|
|
7
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
8
|
+
}
|
|
9
|
+
function sameArgv(left, right) {
|
|
10
|
+
return sameStringList(left, right);
|
|
11
|
+
}
|
|
12
|
+
function diffCommandMaps(args) {
|
|
13
|
+
const failures = [];
|
|
14
|
+
const actualNames = Object.keys(args.actual).sort();
|
|
15
|
+
const expectedNames = Object.keys(args.expected).sort();
|
|
16
|
+
if (!sameStringList(actualNames, expectedNames)) failures.push(args.onNameMismatch(expectedNames));
|
|
17
|
+
for (const [name, command] of Object.entries(args.expected)) {
|
|
18
|
+
const actualCommand = args.actual[name];
|
|
19
|
+
if (!actualCommand) continue;
|
|
20
|
+
if (!sameArgv(actualCommand.argv, command.argv)) failures.push(args.onArgvMismatch(name, command.argv));
|
|
21
|
+
}
|
|
22
|
+
return failures;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/common/zod.ts
|
|
26
|
+
function formatZodIssues(error) {
|
|
27
|
+
return error.issues.map((issue) => {
|
|
28
|
+
return `${issue.path.length ? issue.path.join(".") : "<root>"}: ${issue.message}`;
|
|
29
|
+
}).join("; ");
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/common/manifest_files.ts
|
|
33
|
+
function collectManifestFiles(files, rootDir) {
|
|
34
|
+
const out = [];
|
|
35
|
+
const seen = /* @__PURE__ */ new Set();
|
|
36
|
+
const rootAbs = resolve(process.cwd(), rootDir);
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
if (!file.path || seen.has(file.path)) continue;
|
|
39
|
+
seen.add(file.path);
|
|
40
|
+
try {
|
|
41
|
+
out.push(readManifestFile(file, rootAbs, { portableRoot: true }));
|
|
42
|
+
} catch {}
|
|
43
|
+
}
|
|
44
|
+
return out.sort((a, b) => a.path.localeCompare(b.path));
|
|
45
|
+
}
|
|
46
|
+
function validateManifestFiles(args) {
|
|
47
|
+
const failures = [];
|
|
48
|
+
const baseDir = args.manifestPath ? dirname(resolve(process.cwd(), args.manifestPath)) : resolve(process.cwd(), args.rootDir);
|
|
49
|
+
for (const file of args.files) {
|
|
50
|
+
let current = null;
|
|
51
|
+
try {
|
|
52
|
+
current = readManifestFile(file, baseDir);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
failures.push(`${file.path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (current.bytes !== file.bytes) failures.push(`${file.path}: bytes ${current.bytes} !== ${file.bytes}`);
|
|
58
|
+
if (current.sha256 !== file.sha256) failures.push(`${file.path}: sha256 ${current.sha256} !== ${file.sha256}`);
|
|
59
|
+
}
|
|
60
|
+
if (failures.length > 0) throw new Error(`invalid ${args.label} manifest files: ${failures.join("; ")}`);
|
|
61
|
+
}
|
|
62
|
+
function readManifestFile(file, baseDir, options = {}) {
|
|
63
|
+
if (!file.path) throw new Error("missing file path");
|
|
64
|
+
const absPath = isAbsolute(file.path) ? file.path : resolve(options.portableRoot ? process.cwd() : baseDir, file.path);
|
|
65
|
+
if (!statSync(absPath).isFile()) throw new Error("not a file");
|
|
66
|
+
const bytes = readFileSync(absPath);
|
|
67
|
+
return {
|
|
68
|
+
path: options.portableRoot ? portablePath(absPath, baseDir) : file.path,
|
|
69
|
+
kind: file.kind,
|
|
70
|
+
role: file.role,
|
|
71
|
+
ok: file.ok,
|
|
72
|
+
bytes: bytes.byteLength,
|
|
73
|
+
sha256: createHash("sha256").update(bytes).digest("hex")
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { sameArgv as a, diffCommandMaps as i, validateManifestFiles as n, formatZodIssues as r, collectManifestFiles as t };
|
package/dist/mcp.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createPtywrightServer } from "./server-
|
|
1
|
+
import { t as createPtywrightServer } from "./server-DMnnXjWv.mjs";
|
|
2
2
|
export { createPtywrightServer };
|
package/dist/pty-cassette.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as dataToBytes, _ as ptyCassetteSchema, a as inspectPtyCassette, b as byteLength, c as createPtyCassetteReplay, d as PTY_CASSETTE_SCHEMA_URL, f as normalizePtyCassette, g as ptyCassetteResizeEventSchema, h as ptyCassetteExitEventSchema, i as formatPtyCassetteInspectLines, l as readPtyCassettePath, m as ptyCassetteEventSchema, n as PtyCassetteRecorder, o as inspectPtyCassettePath, p as ptyCassetteDataEventSchema, r as createPtyCassetteRecorder, s as PtyCassetteReplay, t as wrapPtyLike, u as writePtyCassettePath, v as validatePtyCassette, x as dataToBase64, y as base64ToBytes } from "./pty_like-
|
|
1
|
+
import { S as dataToBytes, _ as ptyCassetteSchema, a as inspectPtyCassette, b as byteLength, c as createPtyCassetteReplay, d as PTY_CASSETTE_SCHEMA_URL, f as normalizePtyCassette, g as ptyCassetteResizeEventSchema, h as ptyCassetteExitEventSchema, i as formatPtyCassetteInspectLines, l as readPtyCassettePath, m as ptyCassetteEventSchema, n as PtyCassetteRecorder, o as inspectPtyCassettePath, p as ptyCassetteDataEventSchema, r as createPtyCassetteRecorder, s as PtyCassetteReplay, t as wrapPtyLike, u as writePtyCassettePath, v as validatePtyCassette, x as dataToBase64, y as base64ToBytes } from "./pty_like-BjeBibSL.mjs";
|
|
2
2
|
//#region src/pty-cassette/bun_terminal.ts
|
|
3
3
|
function wrapBunTerminalOptions(options, recorder) {
|
|
4
4
|
const onData = options.data;
|