🚀 Auto-deploy: BotVPS atualizado em 02/05/2026 15:37:40

This commit is contained in:
2026-05-02 15:37:40 +00:00
parent 1c1fac3735
commit 912763b3f1
613 changed files with 169969 additions and 60 deletions

171
node_modules/playwright-core/lib/tools/trace/SKILL.md generated vendored Normal file
View File

@@ -0,0 +1,171 @@
---
name: playwright-trace
description: Inspect Playwright trace files from the command line — list actions, view requests, console, errors, snapshots and screenshots.
allowed-tools: Bash(npx:*)
---
# Playwright Trace CLI
Inspect `.zip` trace files produced by Playwright tests without opening a browser.
## Workflow
1. Start with `trace open <trace.zip>` to extract the trace and see its metadata.
2. Use `trace actions` to see all actions with their action IDs.
3. Use `trace action <action-id>` to drill into a specific action — see parameters, logs, source location, and available snapshots.
4. Use `trace requests`, `trace console`, or `trace errors` for cross-cutting views.
5. Use `trace snapshot <action-id>` to get the DOM snapshot, or run a browser command against it.
6. Use `trace close` to remove the extracted trace data when done.
All commands after `open` operate on the currently opened trace — no need to pass the trace file again. Opening a new trace replaces the previous one.
## Commands
### Open a trace
```bash
# Extract trace and show metadata: browser, viewport, duration, action/error counts
npx playwright trace open <trace.zip>
```
### Close a trace
```bash
# Remove extracted trace data
npx playwright trace close
```
### Actions
```bash
# List all actions as a tree with action IDs and timing
npx playwright trace actions
# Filter by action title (regex, case-insensitive)
npx playwright trace actions --grep "click"
# Only failed actions
npx playwright trace actions --errors-only
```
### Action details
```bash
# Show full details for one action: params, result, logs, source, snapshots
npx playwright trace action <action-id>
```
The `action` command displays available snapshot phases (before, input, after) and the exact command to extract them.
### Requests
```bash
# All network requests: method, status, URL, duration, size
npx playwright trace requests
# Filter by URL pattern
npx playwright trace requests --grep "api"
# Filter by HTTP method
npx playwright trace requests --method POST
# Only failed requests (status >= 400)
npx playwright trace requests --failed
```
### Request details
```bash
# Show full details for one request: headers, body, security
npx playwright trace request <request-id>
```
### Console
```bash
# All console messages and stdout/stderr
npx playwright trace console
# Only errors
npx playwright trace console --errors-only
# Only browser console (no stdout/stderr)
npx playwright trace console --browser
# Only stdout/stderr (no browser console)
npx playwright trace console --stdio
```
### Errors
```bash
# All errors with stack traces and associated actions
npx playwright trace errors
```
### Snapshots
The `snapshot` command loads the DOM snapshot for an action into a headless browser and runs a single browser command against it. Without a browser command, it returns the accessibility snapshot.
```bash
# Get the accessibility snapshot (default)
npx playwright trace snapshot <action-id>
# Use a specific phase
npx playwright trace snapshot <action-id> --name before
# Run eval to query the DOM
npx playwright trace snapshot <action-id> -- eval "document.title"
npx playwright trace snapshot <action-id> -- eval "document.querySelector('#error').textContent"
# Eval on a specific element ref (from the snapshot)
npx playwright trace snapshot <action-id> -- eval "el => el.getAttribute('data-testid')" e5
# Take a screenshot of the snapshot
npx playwright trace snapshot <action-id> -- screenshot
# Redirect output to a file
npx playwright trace snapshot <action-id> -- eval "document.body.outerHTML" --filename=page.html
npx playwright trace snapshot <action-id> -- screenshot --filename=screenshot.png
```
Only three browser commands are useful on a frozen snapshot: `snapshot`, `eval`, and `screenshot`.
### Attachments
```bash
# List all trace attachments
npx playwright trace attachments
# Extract an attachment by its number
npx playwright trace attachment 1
npx playwright trace attachment 1 -o out.png
```
## Typical investigation
```bash
# 1. Open the trace and see what's inside
npx playwright trace open test-results/my-test/trace.zip
# 2. What actions ran?
npx playwright trace actions
# 3. Which action failed?
npx playwright trace actions --errors-only
# 4. What went wrong?
npx playwright trace action 12
# 5. What did the page look like at that moment?
npx playwright trace snapshot 12
# 6. Query the DOM for more detail
npx playwright trace snapshot 12 -- eval "document.querySelector('.error-message').textContent"
# 7. Any relevant network failures?
npx playwright trace requests --failed
# 8. Any console errors?
npx playwright trace console --errors-only
```

View File

@@ -0,0 +1,48 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var installSkill_exports = {};
__export(installSkill_exports, {
installSkill: () => installSkill
});
module.exports = __toCommonJS(installSkill_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
async function installSkill() {
const cwd = process.cwd();
const skillSource = import_path.default.join(__dirname, "SKILL.md");
const destDir = import_path.default.join(cwd, ".claude", "skills", "playwright-trace");
await import_fs.default.promises.mkdir(destDir, { recursive: true });
const destFile = import_path.default.join(destDir, "SKILL.md");
await import_fs.default.promises.copyFile(skillSource, destFile);
console.log(`\u2705 Skill installed to \`${import_path.default.relative(cwd, destFile)}\`.`);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
installSkill
});

View File

@@ -0,0 +1,142 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceActions_exports = {};
__export(traceActions_exports, {
traceAction: () => traceAction,
traceActions: () => traceActions
});
module.exports = __toCommonJS(traceActions_exports);
var import_traceModel = require("../../utils/isomorphic/trace/traceModel");
var import_locatorGenerators = require("../../utils/isomorphic/locatorGenerators");
var import_traceUtils = require("./traceUtils");
var import_formatUtils = require("../../utils/isomorphic/formatUtils");
async function traceActions(options) {
const trace = await (0, import_traceUtils.loadTrace)();
const actions = filterActions(trace.model.actions, options);
const { rootItem } = (0, import_traceModel.buildActionTree)(actions);
console.log(` ${"#".padStart(4)} ${"Time".padEnd(9)} ${"Action".padEnd(55)} ${"Duration".padStart(8)}`);
console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(9)} ${"\u2500".repeat(55)} ${"\u2500".repeat(8)}`);
const visit = (item, indent) => {
const action = item.action;
const ordinal = trace.callIdToOrdinal.get(action.callId) ?? "?";
const ts = (0, import_traceUtils.formatTimestamp)(action.startTime, trace.model.startTime);
const duration = action.endTime ? (0, import_formatUtils.msToString)(action.endTime - action.startTime) : "running";
const title = (0, import_traceUtils.actionTitle)(action);
const locator = actionLocator(action);
const error = action.error ? " \u2717" : "";
const prefix = ` ${(ordinal + ".").padStart(4)} ${ts} ${indent}`;
console.log(`${prefix}${title.padEnd(Math.max(1, 55 - indent.length))} ${duration.padStart(8)}${error}`);
if (locator)
console.log(`${" ".repeat(prefix.length)}${locator}`);
for (const child of item.children)
visit(child, indent + " ");
};
for (const child of rootItem.children)
visit(child, "");
}
function filterActions(actions, options) {
let result = actions.filter((a) => a.group !== "configuration");
if (options.grep) {
const pattern = new RegExp(options.grep, "i");
result = result.filter((a) => pattern.test((0, import_traceUtils.actionTitle)(a)) || pattern.test(actionLocator(a) || ""));
}
if (options.errorsOnly)
result = result.filter((a) => !!a.error);
return result;
}
function actionLocator(action, sdkLanguage) {
return action.params.selector ? (0, import_locatorGenerators.asLocatorDescription)(sdkLanguage || "javascript", action.params.selector) : void 0;
}
async function traceAction(actionId) {
const trace = await (0, import_traceUtils.loadTrace)();
const action = trace.resolveActionId(actionId);
if (!action) {
console.error(`Action '${actionId}' not found. Use 'trace actions' to see available action IDs.`);
process.exitCode = 1;
return;
}
const title = (0, import_traceUtils.actionTitle)(action);
console.log(`
${title}
`);
console.log(" Time");
console.log(` start: ${(0, import_traceUtils.formatTimestamp)(action.startTime, trace.model.startTime)}`);
const duration = action.endTime ? (0, import_formatUtils.msToString)(action.endTime - action.startTime) : action.error ? "Timed Out" : "Running";
console.log(` duration: ${duration}`);
const paramKeys = Object.keys(action.params).filter((name) => name !== "info");
if (paramKeys.length) {
console.log("\n Parameters");
for (const key of paramKeys) {
const value = formatParamValue(action.params[key]);
console.log(` ${key}: ${value}`);
}
}
if (action.result) {
console.log("\n Return value");
for (const [key, value] of Object.entries(action.result))
console.log(` ${key}: ${formatParamValue(value)}`);
}
if (action.error) {
console.log("\n Error");
console.log(` ${action.error.message}`);
}
if (action.log.length) {
console.log("\n Log");
for (const entry of action.log) {
const time = entry.time !== -1 ? (0, import_traceUtils.formatTimestamp)(entry.time, trace.model.startTime) : "";
console.log(` ${time.padEnd(12)} ${entry.message}`);
}
}
if (action.stack?.length) {
console.log("\n Source");
for (const frame of action.stack.slice(0, 5)) {
const file = frame.file.replace(/.*[/\\](.*)/, "$1");
console.log(` ${file}:${frame.line}:${frame.column}`);
}
}
const snapshots = [];
if (action.beforeSnapshot)
snapshots.push("before");
if (action.inputSnapshot)
snapshots.push("input");
if (action.afterSnapshot)
snapshots.push("after");
if (snapshots.length) {
console.log("\n Snapshots");
console.log(` available: ${snapshots.join(", ")}`);
console.log(` usage: npx playwright trace snapshot ${actionId} --name <${snapshots.join("|")}>`);
}
console.log("");
}
function formatParamValue(value) {
if (value === void 0 || value === null)
return String(value);
if (typeof value === "string")
return `"${value}"`;
if (typeof value !== "object")
return String(value);
if (value.guid)
return "<handle>";
return JSON.stringify(value).slice(0, 1e3);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceAction,
traceActions
});

View File

@@ -0,0 +1,69 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceAttachments_exports = {};
__export(traceAttachments_exports, {
traceAttachment: () => traceAttachment,
traceAttachments: () => traceAttachments
});
module.exports = __toCommonJS(traceAttachments_exports);
var import_traceUtils = require("./traceUtils");
async function traceAttachments() {
const trace = await (0, import_traceUtils.loadTrace)();
if (!trace.model.attachments.length) {
console.log(" No attachments");
return;
}
console.log(` ${"#".padStart(4)} ${"Name".padEnd(40)} ${"Content-Type".padEnd(30)} ${"Action".padEnd(8)}`);
console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(40)} ${"\u2500".repeat(30)} ${"\u2500".repeat(8)}`);
for (let i = 0; i < trace.model.attachments.length; i++) {
const a = trace.model.attachments[i];
const actionOrdinal = trace.callIdToOrdinal.get(a.callId);
console.log(` ${(i + 1 + ".").padStart(4)} ${a.name.padEnd(40)} ${a.contentType.padEnd(30)} ${(actionOrdinal !== void 0 ? String(actionOrdinal) : a.callId).padEnd(8)}`);
}
}
async function traceAttachment(attachmentId, options) {
const trace = await (0, import_traceUtils.loadTrace)();
const ordinal = parseInt(attachmentId, 10);
const attachment = !isNaN(ordinal) && ordinal >= 1 && ordinal <= trace.model.attachments.length ? trace.model.attachments[ordinal - 1] : void 0;
if (!attachment) {
console.error(`Attachment '${attachmentId}' not found. Use 'trace attachments' to see available attachments.`);
process.exitCode = 1;
return;
}
let content;
if (attachment.sha1) {
const blob = await trace.loader.resourceForSha1(attachment.sha1);
if (blob)
content = Buffer.from(await blob.arrayBuffer());
} else if (attachment.base64) {
content = Buffer.from(attachment.base64, "base64");
}
if (!content) {
console.error(`Could not extract attachment content.`);
process.exitCode = 1;
return;
}
const outFile = await (0, import_traceUtils.saveOutputFile)(attachment.name, content, options.output);
console.log(` Attachment saved to ${outFile}`);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceAttachment,
traceAttachments
});

View File

@@ -0,0 +1,87 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceCli_exports = {};
__export(traceCli_exports, {
addTraceCommands: () => addTraceCommands
});
module.exports = __toCommonJS(traceCli_exports);
function addTraceCommands(program, logErrorAndExit) {
const traceCommand = program.command("trace").description("inspect trace files from the command line");
traceCommand.command("open <trace>").description("extract trace file for inspection").action(async (trace) => {
const { traceOpen } = require("./traceOpen");
traceOpen(trace).catch(logErrorAndExit);
});
traceCommand.command("close").description("remove extracted trace data").action(async () => {
const { closeTrace } = require("./traceUtils");
closeTrace().catch(logErrorAndExit);
});
traceCommand.command("actions").description("list actions in the trace").option("--grep <pattern>", "filter actions by title pattern").option("--errors-only", "only show failed actions").action(async (options) => {
const { traceActions } = require("./traceActions");
traceActions(options).catch(logErrorAndExit);
});
traceCommand.command("action <action-id>").description("show details of a specific action").action(async (actionId) => {
const { traceAction } = require("./traceActions");
traceAction(actionId).catch(logErrorAndExit);
});
traceCommand.command("requests").description("show network requests").option("--grep <pattern>", "filter by URL pattern").option("--method <method>", "filter by HTTP method").option("--status <code>", "filter by status code").option("--failed", "only show failed requests (status >= 400)").action(async (options) => {
const { traceRequests } = require("./traceRequests");
traceRequests(options).catch(logErrorAndExit);
});
traceCommand.command("request <request-id>").description("show details of a specific network request").action(async (requestId) => {
const { traceRequest } = require("./traceRequests");
traceRequest(requestId).catch(logErrorAndExit);
});
traceCommand.command("console").description("show console messages").option("--errors-only", "only show errors").option("--warnings", "show errors and warnings").option("--browser", "only browser console messages").option("--stdio", "only stdout/stderr").action(async (options) => {
const { traceConsole } = require("./traceConsole");
traceConsole(options).catch(logErrorAndExit);
});
traceCommand.command("errors").description("show errors with stack traces").action(async () => {
const { traceErrors } = require("./traceErrors");
traceErrors().catch(logErrorAndExit);
});
traceCommand.command("snapshot <action-id>").description("run a playwright-cli command against a DOM snapshot").option("--name <name>", "snapshot phase: before, input, or after").option("--serve", "serve snapshot on localhost and keep running").allowUnknownOption(true).allowExcessArguments(true).action(async (actionId, options, cmd) => {
try {
const { traceSnapshot } = require("./traceSnapshot");
const browserArgs = cmd.args.slice(1);
await traceSnapshot(actionId, { ...options, browserArgs });
} catch (e) {
logErrorAndExit(e);
}
});
traceCommand.command("screenshot <action-id>").description("save screencast screenshot for an action").option("-o, --output <path>", "output file path").action(async (actionId, options) => {
const { traceScreenshot } = require("./traceScreenshot");
traceScreenshot(actionId, options).catch(logErrorAndExit);
});
traceCommand.command("attachments").description("list trace attachments").action(async () => {
const { traceAttachments } = require("./traceAttachments");
traceAttachments().catch(logErrorAndExit);
});
traceCommand.command("attachment <attachment-id>").description("extract a trace attachment by its number").option("-o, --output <path>", "output file path").action(async (attachmentId, options) => {
const { traceAttachment } = require("./traceAttachments");
traceAttachment(attachmentId, options).catch(logErrorAndExit);
});
traceCommand.command("install-skill").description("install SKILL.md for LLM integration").action(async () => {
const { installSkill } = require("./installSkill");
installSkill().catch(logErrorAndExit);
});
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
addTraceCommands
});

View File

@@ -0,0 +1,97 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceConsole_exports = {};
__export(traceConsole_exports, {
traceConsole: () => traceConsole
});
module.exports = __toCommonJS(traceConsole_exports);
var import_traceUtils = require("./traceUtils");
async function traceConsole(options) {
const trace = await (0, import_traceUtils.loadTrace)();
const model = trace.model;
const items = [];
for (const event of model.events) {
if (event.type === "console") {
if (options.stdio)
continue;
const level = event.messageType;
if (options.errorsOnly && level !== "error")
continue;
if (options.warnings && level !== "error" && level !== "warning")
continue;
const url = event.location.url;
const filename = url ? url.substring(url.lastIndexOf("/") + 1) : "<anonymous>";
items.push({
type: "browser",
level,
text: event.text,
location: `${filename}:${event.location.lineNumber}`,
timestamp: event.time
});
}
if (event.type === "event" && event.method === "pageError") {
if (options.stdio)
continue;
const error = event.params.error;
items.push({
type: "browser",
level: "error",
text: error?.error?.message || String(error?.value || ""),
timestamp: event.time
});
}
}
for (const event of model.stdio) {
if (options.browser)
continue;
if (options.errorsOnly && event.type !== "stderr")
continue;
if (options.warnings && event.type !== "stderr")
continue;
let text = "";
if (event.text)
text = event.text.trim();
if (event.base64)
text = Buffer.from(event.base64, "base64").toString("utf-8").trim();
if (!text)
continue;
items.push({
type: event.type,
level: event.type === "stderr" ? "error" : "info",
text,
timestamp: event.timestamp
});
}
items.sort((a, b) => a.timestamp - b.timestamp);
if (!items.length) {
console.log(" No console entries");
return;
}
for (const item of items) {
const ts = (0, import_traceUtils.formatTimestamp)(item.timestamp, model.startTime);
const source = item.type === "browser" ? "[browser]" : `[${item.type}]`;
const level = item.level.padEnd(8);
const location = item.location ? ` ${item.location}` : "";
console.log(` ${ts} ${source.padEnd(10)} ${level} ${item.text}${location}`);
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceConsole
});

View File

@@ -0,0 +1,55 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceErrors_exports = {};
__export(traceErrors_exports, {
traceErrors: () => traceErrors
});
module.exports = __toCommonJS(traceErrors_exports);
var import_traceUtils = require("./traceUtils");
async function traceErrors() {
const trace = await (0, import_traceUtils.loadTrace)();
const model = trace.model;
if (!model.errorDescriptors.length) {
console.log(" No errors");
return;
}
for (const error of model.errorDescriptors) {
if (error.action) {
const title = (0, import_traceUtils.actionTitle)(error.action);
console.log(`
\u2717 ${title}`);
} else {
console.log(`
\u2717 Error`);
}
if (error.stack?.length) {
const frame = error.stack[0];
const file = frame.file.replace(/.*[/\\](.*)/, "$1");
console.log(` at ${file}:${frame.line}:${frame.column}`);
}
console.log("");
const indented = error.message.split("\n").map((l) => ` ${l}`).join("\n");
console.log(indented);
}
console.log("");
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceErrors
});

View File

@@ -0,0 +1,69 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceOpen_exports = {};
__export(traceOpen_exports, {
traceOpen: () => traceOpen
});
module.exports = __toCommonJS(traceOpen_exports);
var import_traceUtils = require("./traceUtils");
var import_formatUtils = require("../../utils/isomorphic/formatUtils");
async function traceOpen(traceFile) {
await (0, import_traceUtils.openTrace)(traceFile);
await traceInfo();
}
async function traceInfo() {
const trace = await (0, import_traceUtils.loadTrace)();
const model = trace.model;
const info = {
browser: model.browserName || "unknown",
platform: model.platform || "unknown",
playwrightVersion: model.playwrightVersion || "unknown",
title: model.title || "",
duration: (0, import_formatUtils.msToString)(model.endTime - model.startTime),
durationMs: model.endTime - model.startTime,
startTime: model.wallTime ? new Date(model.wallTime).toISOString() : "unknown",
viewport: model.options.viewport ? `${model.options.viewport.width}x${model.options.viewport.height}` : "default",
actions: model.actions.length,
pages: model.pages.length,
network: model.resources.length,
errors: model.errorDescriptors.length,
attachments: model.attachments.length,
consoleMessages: model.events.filter((e) => e.type === "console").length
};
console.log("");
console.log(` Browser: ${info.browser}`);
console.log(` Platform: ${info.platform}`);
console.log(` Playwright: ${info.playwrightVersion}`);
if (info.title)
console.log(` Title: ${info.title}`);
console.log(` Duration: ${info.duration}`);
console.log(` Start time: ${info.startTime}`);
console.log(` Viewport: ${info.viewport}`);
console.log(` Actions: ${info.actions}`);
console.log(` Pages: ${info.pages}`);
console.log(` Network: ${info.network} requests`);
console.log(` Errors: ${info.errors}`);
console.log(` Attachments: ${info.attachments}`);
console.log(` Console: ${info.consoleMessages} messages`);
console.log("");
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceOpen
});

View File

@@ -0,0 +1,96 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceParser_exports = {};
__export(traceParser_exports, {
DirTraceLoaderBackend: () => DirTraceLoaderBackend,
extractTrace: () => extractTrace
});
module.exports = __toCommonJS(traceParser_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_zipFile = require("../../server/utils/zipFile");
class DirTraceLoaderBackend {
constructor(dir) {
this._dir = dir;
}
isLive() {
return false;
}
async entryNames() {
const entries = [];
const walk = async (dir, prefix) => {
const items = await import_fs.default.promises.readdir(dir, { withFileTypes: true });
for (const item of items) {
if (item.isDirectory())
await walk(import_path.default.join(dir, item.name), prefix ? `${prefix}/${item.name}` : item.name);
else
entries.push(prefix ? `${prefix}/${item.name}` : item.name);
}
};
await walk(this._dir, "");
return entries;
}
async hasEntry(entryName) {
try {
await import_fs.default.promises.access(import_path.default.join(this._dir, entryName));
return true;
} catch {
return false;
}
}
async readText(entryName) {
try {
return await import_fs.default.promises.readFile(import_path.default.join(this._dir, entryName), "utf-8");
} catch {
}
}
async readBlob(entryName) {
try {
const buffer = await import_fs.default.promises.readFile(import_path.default.join(this._dir, entryName));
return new Blob([new Uint8Array(buffer)]);
} catch {
}
}
}
async function extractTrace(traceFile, outDir) {
const zipFile = new import_zipFile.ZipFile(traceFile);
const entries = await zipFile.entries();
for (const entry of entries) {
const outPath = import_path.default.join(outDir, entry);
await import_fs.default.promises.mkdir(import_path.default.dirname(outPath), { recursive: true });
const buffer = await zipFile.read(entry);
await import_fs.default.promises.writeFile(outPath, buffer);
}
zipFile.close();
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
DirTraceLoaderBackend,
extractTrace
});

View File

@@ -0,0 +1,182 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceRequests_exports = {};
__export(traceRequests_exports, {
traceRequest: () => traceRequest,
traceRequests: () => traceRequests
});
module.exports = __toCommonJS(traceRequests_exports);
var import_path = __toESM(require("path"));
var import_traceUtils = require("./traceUtils");
var import_formatUtils = require("../../utils/isomorphic/formatUtils");
async function traceRequests(options) {
const trace = await (0, import_traceUtils.loadTrace)();
const model = trace.model;
let indexed = model.resources.map((r, i) => ({ resource: r, ordinal: i + 1 }));
if (options.grep) {
const pattern = new RegExp(options.grep, "i");
indexed = indexed.filter(({ resource: r }) => pattern.test(r.request.url));
}
if (options.method)
indexed = indexed.filter(({ resource: r }) => r.request.method.toLowerCase() === options.method.toLowerCase());
if (options.status) {
const code = parseInt(options.status, 10);
indexed = indexed.filter(({ resource: r }) => r.response.status === code);
}
if (options.failed)
indexed = indexed.filter(({ resource: r }) => r.response.status >= 400 || r.response.status === -1);
if (!indexed.length) {
console.log(" No network requests");
return;
}
console.log(` ${"#".padStart(4)} ${"Method".padEnd(8)} ${"Status".padEnd(8)} ${"Name".padEnd(45)} ${"Duration".padStart(10)} ${"Size".padStart(8)} ${"Route".padEnd(10)}`);
console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(8)} ${"\u2500".repeat(8)} ${"\u2500".repeat(45)} ${"\u2500".repeat(10)} ${"\u2500".repeat(8)} ${"\u2500".repeat(10)}`);
for (const { resource: r, ordinal } of indexed) {
let name;
try {
const url = new URL(r.request.url);
name = url.pathname.substring(url.pathname.lastIndexOf("/") + 1);
if (!name)
name = url.host;
if (url.search)
name += url.search;
} catch {
name = r.request.url;
}
if (name.length > 45)
name = name.substring(0, 42) + "...";
const status = r.response.status > 0 ? String(r.response.status) : "ERR";
const size = r.response._transferSize > 0 ? r.response._transferSize : r.response.bodySize;
const route = formatRouteStatus(r);
console.log(` ${(ordinal + ".").padStart(4)} ${r.request.method.padEnd(8)} ${status.padEnd(8)} ${name.padEnd(45)} ${(0, import_formatUtils.msToString)(r.time).padStart(10)} ${bytesToString(size).padStart(8)} ${route.padEnd(10)}`);
}
}
async function traceRequest(requestId) {
const trace = await (0, import_traceUtils.loadTrace)();
const model = trace.model;
const ordinal = parseInt(requestId, 10);
const resource = !isNaN(ordinal) && ordinal >= 1 && ordinal <= model.resources.length ? model.resources[ordinal - 1] : void 0;
if (!resource) {
console.error(`Request '${requestId}' not found. Use 'trace requests' to see available request IDs.`);
process.exitCode = 1;
return;
}
const r = resource;
const status = r.response.status > 0 ? `${r.response.status} ${r.response.statusText}` : "ERR";
const size = r.response._transferSize > 0 ? r.response._transferSize : r.response.bodySize;
console.log(`
${r.request.method} ${r.request.url}
`);
console.log(" General");
console.log(` status: ${status}`);
console.log(` duration: ${(0, import_formatUtils.msToString)(r.time)}`);
console.log(` size: ${bytesToString(size)}`);
if (r.response.content.mimeType)
console.log(` type: ${r.response.content.mimeType}`);
const route = formatRouteStatus(r);
if (route)
console.log(` route: ${route}`);
if (r.serverIPAddress)
console.log(` server: ${r.serverIPAddress}${r._serverPort ? ":" + r._serverPort : ""}`);
if (r.response._failureText)
console.log(` error: ${r.response._failureText}`);
if (r.request.headers.length) {
console.log("\n Request headers");
for (const h of r.request.headers)
console.log(` ${h.name}: ${h.value}`);
}
if (r.request.postData) {
console.log("\n Request body");
const resource2 = r.request.postData._sha1 ?? r.request.postData._file;
if (resource2) {
console.log(` ${import_path.default.relative(process.cwd(), import_path.default.join(trace.model.traceUri, "resources", resource2))}`);
} else {
const text = r.request.postData.text.length > 2e3 ? r.request.postData.text.substring(0, 2e3) + "..." : r.request.postData.text;
console.log(` ${text}`);
}
}
if (r.response.headers.length) {
console.log("\n Response headers");
for (const h of r.response.headers)
console.log(` ${h.name}: ${h.value}`);
}
if (r.response.bodySize > 0) {
const resource2 = r.response.content._sha1 ?? r.response.content._file;
if (resource2) {
console.log("\n Response body");
console.log(` ${import_path.default.relative(process.cwd(), import_path.default.join(trace.model.traceUri, "resources", resource2))}`);
} else if (r.response.content.text) {
const text = r.response.content.text.length > 2e3 ? r.response.content.text.substring(0, 2e3) + "..." : r.response.content.text;
console.log("\n Response body");
console.log(` ${text}`);
}
}
if (r._securityDetails) {
console.log("\n Security");
if (r._securityDetails.protocol)
console.log(` protocol: ${r._securityDetails.protocol}`);
if (r._securityDetails.subjectName)
console.log(` subject: ${r._securityDetails.subjectName}`);
if (r._securityDetails.issuer)
console.log(` issuer: ${r._securityDetails.issuer}`);
}
console.log("");
}
function bytesToString(bytes) {
if (bytes < 0 || !isFinite(bytes))
return "-";
if (bytes === 0)
return "0";
if (bytes < 1e3)
return bytes.toFixed(0);
const kb = bytes / 1024;
if (kb < 1e3)
return kb.toFixed(1) + "K";
const mb = kb / 1024;
if (mb < 1e3)
return mb.toFixed(1) + "M";
const gb = mb / 1024;
return gb.toFixed(1) + "G";
}
function formatRouteStatus(r) {
if (r._wasAborted)
return "aborted";
if (r._wasContinued)
return "continued";
if (r._wasFulfilled)
return "fulfilled";
if (r._apiRequest)
return "api";
return "";
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceRequest,
traceRequests
});

View File

@@ -0,0 +1,68 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceScreenshot_exports = {};
__export(traceScreenshot_exports, {
traceScreenshot: () => traceScreenshot
});
module.exports = __toCommonJS(traceScreenshot_exports);
var import_traceUtils = require("./traceUtils");
async function traceScreenshot(actionId, options) {
const trace = await (0, import_traceUtils.loadTrace)();
const action = trace.resolveActionId(actionId);
if (!action) {
console.error(`Action '${actionId}' not found.`);
process.exitCode = 1;
return;
}
const pageId = action.pageId;
if (!pageId) {
console.error(`Action '${actionId}' has no associated page.`);
process.exitCode = 1;
return;
}
const callId = action.callId;
const storage = trace.loader.storage();
const snapshotNames = ["input", "before", "after"];
let sha1;
for (const name of snapshotNames) {
const renderer = storage.snapshotByName(pageId, `${name}@${callId}`);
sha1 = renderer?.closestScreenshot();
if (sha1)
break;
}
if (!sha1) {
console.error(`No screenshot found for action '${actionId}'.`);
process.exitCode = 1;
return;
}
const blob = await trace.loader.resourceForSha1(sha1);
if (!blob) {
console.error(`Screenshot resource not found.`);
process.exitCode = 1;
return;
}
const defaultName = `screenshot-${actionId}.png`;
const buffer = Buffer.from(await blob.arrayBuffer());
const outFile = await (0, import_traceUtils.saveOutputFile)(defaultName, buffer, options.output);
console.log(` Screenshot saved to ${outFile}`);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceScreenshot
});

View File

@@ -0,0 +1,149 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceSnapshot_exports = {};
__export(traceSnapshot_exports, {
traceSnapshot: () => traceSnapshot
});
module.exports = __toCommonJS(traceSnapshot_exports);
var import_browserBackend = require("../backend/browserBackend");
var import_tools = require("../backend/tools");
var playwright = __toESM(require("../../.."));
var import_utils = require("../../utils");
var import_command = require("../cli-daemon/command");
var import_minimist = require("../cli-client/minimist");
var import_commands = require("../cli-daemon/commands");
var import_traceUtils = require("./traceUtils");
async function traceSnapshot(actionId, options) {
const trace = await (0, import_traceUtils.loadTrace)();
const action = trace.resolveActionId(actionId);
if (!action) {
console.error(`Action '${actionId}' not found.`);
process.exitCode = 1;
return;
}
const pageId = action.pageId;
if (!pageId) {
console.error(`Action '${actionId}' has no associated page.`);
process.exitCode = 1;
return;
}
const callId = action.callId;
const storage = trace.loader.storage();
let snapshotName;
let renderer;
if (options.name) {
snapshotName = options.name;
renderer = storage.snapshotByName(pageId, `${snapshotName}@${callId}`);
} else {
for (const candidate of ["input", "before", "after"]) {
renderer = storage.snapshotByName(pageId, `${candidate}@${callId}`);
if (renderer) {
snapshotName = candidate;
break;
}
}
}
if (!renderer || !snapshotName) {
console.error(`No snapshot found for action '${actionId}'.`);
process.exitCode = 1;
return;
}
const snapshotKey = `${snapshotName}@${callId}`;
const server = await serveTraceSnapshot(storage, trace.loader, pageId, snapshotKey);
if (options.serve) {
console.log(`Serving snapshot at ${server.url}`);
await new Promise(() => {
});
return;
}
await runCommandOnSnapshot(server, options.browserArgs || []);
}
async function serveTraceSnapshot(storage, loader, pageId, snapshotKey) {
const { SnapshotServer } = require("../../utils/isomorphic/trace/snapshotServer");
const { HttpServer } = require("../../server/utils/httpServer");
const snapshotServer = new SnapshotServer(storage, (sha1) => loader.resourceForSha1(sha1));
const httpServer = new HttpServer();
httpServer.routePrefix("/snapshot", (request, response) => {
const url = new URL("http://localhost" + request.url);
const searchParams = url.searchParams;
searchParams.set("name", snapshotKey);
const snapshotResponse = snapshotServer.serveSnapshot(pageId, searchParams, "/snapshot");
response.statusCode = snapshotResponse.status;
snapshotResponse.headers.forEach((value, key) => response.setHeader(key, value));
snapshotResponse.text().then((text) => response.end(text));
return true;
});
httpServer.routePrefix("/", (_request, response) => {
response.statusCode = 302;
response.setHeader("Location", "/snapshot");
response.end();
return true;
});
await httpServer.start({ preferredPort: 0 });
return { url: httpServer.urlPrefix("human-readable"), stop: () => httpServer.stop() };
}
async function runCommandOnSnapshot(server, browserArgs) {
const browser = await playwright.chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(server.url);
const backend = new import_browserBackend.BrowserBackend({
snapshot: { mode: "full" },
outputMode: "file",
skillMode: true
}, context, import_tools.browserTools);
await backend.initialize({ cwd: process.cwd() });
try {
if (!browserArgs.length)
browserArgs = ["snapshot"];
const args = (0, import_minimist.minimist)(browserArgs, { string: ["_"] });
const command = import_commands.commands[args._[0]];
if (!command)
throw new Error(`Unknown command: ${args._[0]}`);
const { toolName, toolParams } = (0, import_command.parseCommand)(command, args);
const result = await backend.callTool(toolName, toolParams);
const text = result.content[0]?.type === "text" ? result.content[0].text : void 0;
if (text)
console.log(text);
if (result.isError) {
console.error("Command failed.");
process.exitCode = 1;
}
} catch (e) {
console.error(e.message);
process.exitCode = 1;
} finally {
await server.stop().catch((e) => console.error(e));
await (0, import_utils.gracefullyCloseAll)();
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
traceSnapshot
});

View File

@@ -0,0 +1,153 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var traceUtils_exports = {};
__export(traceUtils_exports, {
LoadedTrace: () => LoadedTrace,
actionTitle: () => actionTitle,
closeTrace: () => closeTrace,
formatTimestamp: () => formatTimestamp,
loadTrace: () => loadTrace,
openTrace: () => openTrace,
saveOutputFile: () => saveOutputFile
});
module.exports = __toCommonJS(traceUtils_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_traceModel = require("../../utils/isomorphic/trace/traceModel");
var import_traceLoader = require("../../utils/isomorphic/trace/traceLoader");
var import_protocolFormatter = require("../../utils/isomorphic/protocolFormatter");
var import_traceParser = require("./traceParser");
const traceDir = import_path.default.join(".playwright-cli", "trace");
const cliOutputDir = ".playwright-cli";
class LoadedTrace {
constructor(model, loader, ordinals) {
this.model = model;
this.loader = loader;
this.ordinalToCallId = ordinals.ordinalToCallId;
this.callIdToOrdinal = ordinals.callIdToOrdinal;
}
resolveActionId(actionId) {
const ordinal = parseInt(actionId, 10);
if (!isNaN(ordinal)) {
const callId = this.ordinalToCallId.get(ordinal);
if (callId)
return this.model.actions.find((a) => a.callId === callId);
}
return this.model.actions.find((a) => a.callId === actionId);
}
}
function ensureTraceOpen() {
if (!import_fs.default.existsSync(traceDir))
throw new Error(`No trace opened. Run 'npx playwright trace open <file>' first.`);
return traceDir;
}
async function closeTrace() {
if (import_fs.default.existsSync(traceDir))
await import_fs.default.promises.rm(traceDir, { recursive: true });
}
async function openTrace(traceFile) {
const filePath = import_path.default.resolve(traceFile);
if (!import_fs.default.existsSync(filePath))
throw new Error(`Trace file not found: ${filePath}`);
await closeTrace();
await import_fs.default.promises.mkdir(traceDir, { recursive: true });
if (filePath.endsWith(".zip"))
await (0, import_traceParser.extractTrace)(filePath, traceDir);
else
await import_fs.default.promises.writeFile(import_path.default.join(traceDir, ".link"), filePath, "utf-8");
}
async function loadTrace() {
const dir = ensureTraceOpen();
const linkFile = import_path.default.join(dir, ".link");
let traceDir2;
let traceFile;
if (import_fs.default.existsSync(linkFile)) {
const tracePath = await import_fs.default.promises.readFile(linkFile, "utf-8");
traceDir2 = import_path.default.dirname(tracePath);
traceFile = import_path.default.basename(tracePath);
} else {
traceDir2 = dir;
}
const backend = new import_traceParser.DirTraceLoaderBackend(traceDir2);
const loader = new import_traceLoader.TraceLoader();
await loader.load(backend, traceFile);
const model = new import_traceModel.TraceModel(traceDir2, loader.contextEntries);
return new LoadedTrace(model, loader, buildOrdinalMap(model));
}
function formatTimestamp(ms, base) {
const relative = ms - base;
if (relative < 0)
return "0:00.000";
const totalMs = Math.floor(relative);
const minutes = Math.floor(totalMs / 6e4);
const seconds = Math.floor(totalMs % 6e4 / 1e3);
const millis = totalMs % 1e3;
return `${minutes}:${seconds.toString().padStart(2, "0")}.${millis.toString().padStart(3, "0")}`;
}
function actionTitle(action) {
return (0, import_protocolFormatter.renderTitleForCall)({ ...action, type: action.class }) || `${action.class}.${action.method}`;
}
async function saveOutputFile(fileName, content, explicitOutput) {
let outFile;
if (explicitOutput) {
outFile = explicitOutput;
} else {
await import_fs.default.promises.mkdir(cliOutputDir, { recursive: true });
outFile = import_path.default.join(cliOutputDir, fileName);
}
await import_fs.default.promises.writeFile(outFile, content);
return outFile;
}
function buildOrdinalMap(model) {
const actions = model.actions.filter((a) => a.group !== "configuration");
const { rootItem } = (0, import_traceModel.buildActionTree)(actions);
const ordinalToCallId = /* @__PURE__ */ new Map();
const callIdToOrdinal = /* @__PURE__ */ new Map();
let ordinal = 1;
const visit = (item) => {
ordinalToCallId.set(ordinal, item.action.callId);
callIdToOrdinal.set(item.action.callId, ordinal);
ordinal++;
for (const child of item.children)
visit(child);
};
for (const child of rootItem.children)
visit(child);
return { ordinalToCallId, callIdToOrdinal };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
LoadedTrace,
actionTitle,
closeTrace,
formatTimestamp,
loadTrace,
openTrace,
saveOutputFile
});