import type { BenchmarkCommand, Scenario } from "./scenarios.js";
// ---------------------------------------------------------------------------
// HTML generators for realistic pages with complex DOM structures
// ---------------------------------------------------------------------------
function generateArticlePage(): string {
const paragraphs = Array.from({ length: 30 }, (_, i) => {
const words = Array.from(
{ length: 40 + (i % 5) * 10 },
(_, w) => ["the", "quick", "browser", "engine", "renders", "content", "across", "multiple", "layout", "passes", "while", "handling", "style", "recalculations", "and", "DOM", "mutations"][w % 17],
).join(" ");
return `
${words}
`;
});
const comments = Array.from(
{ length: 40 },
(_, i) =>
``,
);
const sidebar = Array.from(
{ length: 20 },
(_, i) =>
``,
);
return [
"Benchmark Article",
"",
``,
'',
"
Understanding Modern Browser Engine Architecture
",
'
Dr. Smith | | 15 min read
',
`
${Array.from({ length: 6 }, (_, i) => `tag-${i + 1}`).join("")}
`,
"
Introduction
",
...paragraphs.slice(0, 5),
"
Core Concepts
",
...paragraphs.slice(5, 12),
'
"Performance is not just about speed, it is about efficiency." - Anonymous
',
"
Implementation Details
",
...paragraphs.slice(12, 20),
"
Subsection A
",
...paragraphs.slice(20, 25),
"
Subsection B
",
...paragraphs.slice(25),
"
Comments
",
'
",
'",
"",
].join("");
}
function generateDataTablePage(): string {
const headerCells = [
"ID", "Name", "Email", "Department", "Role", "Status", "Joined", "Last Active",
];
const header = `${headerCells.map((h) => `| ${h} | `).join("")}
`;
const rows = Array.from({ length: 200 }, (_, i) => {
const dept = ["Engineering", "Design", "Marketing", "Sales", "Support"][i % 5];
const role = ["Admin", "Manager", "Member", "Viewer"][i % 4];
const status = ["Active", "Inactive", "Pending"][i % 3];
return (
`` +
`| ${i + 1} | ` +
`User ${i + 1} | ` +
`user${i + 1}@example.com | ` +
`${dept} | ` +
`${role} | ` +
`${status} | ` +
`2024-${String((i % 12) + 1).padStart(2, "0")}-${String((i % 28) + 1).padStart(2, "0")} | ` +
`${i % 3 === 0 ? "Today" : i % 3 === 1 ? "Yesterday" : "Last week"} | ` +
`
`
);
});
return [
"Benchmark Table",
"",
"User Management Dashboard
",
'',
'',
'',
'',
'',
'Showing 200 users',
"
",
`${header}${rows.join("")}
`,
'",
"",
].join("");
}
function generateNestedPage(): string {
function nest(depth: number, breadth: number, prefix: string): string {
if (depth === 0) {
return `Leaf node at ${prefix}`;
}
const children = Array.from(
{ length: breadth },
(_, i) =>
`` +
`` +
`
${nest(depth - 1, Math.max(2, breadth - 1), `${prefix}.${i + 1}`)}
` +
`
`,
);
return children.join("");
}
return [
"Benchmark Nested",
"",
"Deeply Nested Document Structure
",
nest(7, 3, "root"),
"",
].join("");
}
function generateDashboardPage(): string {
const cards = Array.from(
{ length: 12 },
(_, i) =>
`` +
`
Metric ${i + 1}
` +
`
${Math.floor(Math.random() * 10000)}
` +
`
${i % 2 === 0 ? "+" : "-"}${(Math.random() * 20).toFixed(1)}%
` +
`
`,
);
const chartBars = Array.from(
{ length: 24 },
(_, i) => {
const h = 20 + (i * 7 + 13) % 80;
return `${String(i).padStart(2, "0")}:00
`;
},
);
const logRows = Array.from(
{ length: 100 },
(_, i) => {
const level = ["INFO", "WARN", "ERROR", "DEBUG"][i % 4];
return (
`` +
`| ${new Date(2025, 0, 1, i % 24, i % 60).toISOString()} | ` +
`${level} | ` +
`Service ${["auth", "api", "worker", "cache", "db"][i % 5]} | ` +
`Log message number ${i + 1}: operation completed in ${(Math.random() * 1000).toFixed(0)}ms | ` +
`
`
);
},
);
return [
"Benchmark Dashboard",
"",
'',
`${cards.join("")}
`,
'',
`Request Volume
${chartBars.join("")}
`,
'',
"
Recent Logs
",
`
| Timestamp | Level | Service | Message |
${logRows.join("")}
`,
"
",
"",
].join("");
}
// ---------------------------------------------------------------------------
// Pre-build HTML strings and injection commands
// ---------------------------------------------------------------------------
const ARTICLE_HTML = generateArticlePage();
const TABLE_HTML = generateDataTablePage();
const NESTED_HTML = generateNestedPage();
const DASHBOARD_HTML = generateDashboardPage();
function injectCmd(id: string, html: string): BenchmarkCommand {
return {
id,
action: "evaluate",
script: `document.open(); document.write(${JSON.stringify(html)}); document.close(); 'ok'`,
};
}
function setupPage(html: string, tag: string): BenchmarkCommand[] {
return [
{ id: `${tag}-nav`, action: "navigate", url: "about:blank", waitUntil: "domcontentloaded" },
injectCmd(`${tag}-inject`, html),
];
}
// ---------------------------------------------------------------------------
// Engine-specific scenarios: complex pages that stress real-world workloads
// ---------------------------------------------------------------------------
export const engineScenarios: Scenario[] = [
{
name: "article-snapshot",
description: "Snapshot a realistic article page (~800 DOM nodes, 30 paragraphs, 40 comments)",
setup: setupPage(ARTICLE_HTML, "art"),
commands: [{ id: "snap", action: "snapshot" }],
},
{
name: "table-snapshot",
description: "Snapshot a data table with 200 rows and 8 columns",
setup: setupPage(TABLE_HTML, "tbl"),
commands: [{ id: "snap", action: "snapshot" }],
},
{
name: "nested-snapshot",
description: "Snapshot a deeply nested DOM tree (7 levels, ~3000 nodes)",
setup: setupPage(NESTED_HTML, "nest"),
commands: [{ id: "snap", action: "snapshot" }],
},
{
name: "dashboard-snap",
description: "Snapshot an operations dashboard with cards, chart, and 100 log rows",
setup: setupPage(DASHBOARD_HTML, "dash"),
commands: [{ id: "snap", action: "snapshot" }],
},
{
name: "article-inject",
description: "Write a full article page into the DOM (measures parse + layout)",
setup: [
{ id: "ai-nav", action: "navigate", url: "about:blank", waitUntil: "domcontentloaded" },
],
commands: [injectCmd("ai-write", ARTICLE_HTML)],
},
{
name: "table-query",
description: "Evaluate a querySelectorAll across a large table",
setup: setupPage(TABLE_HTML, "tq"),
commands: [
{
id: "query",
action: "evaluate",
script: "document.querySelectorAll('tr[data-row]').length + ' rows, ' + document.querySelectorAll('td').length + ' cells'",
},
],
},
{
name: "dashboard-workflow",
description: "Full agent workflow on complex dashboard: snapshot, click, fill, eval, screenshot",
setup: setupPage(DASHBOARD_HTML, "dw"),
commands: [
{ id: "dw-snap", action: "snapshot" },
{ id: "dw-fill", action: "fill", selector: "#dash-search", value: "error logs" },
{ id: "dw-click", action: "click", selector: "#refresh" },
{ id: "dw-eval", action: "evaluate", script: "document.querySelectorAll('.card').length + ' cards'" },
{ id: "dw-ss", action: "screenshot" },
],
},
{
name: "nested-eval",
description: "Recursive DOM traversal via evaluate on deeply nested tree",
setup: setupPage(NESTED_HTML, "ne"),
commands: [
{
id: "walk",
action: "evaluate",
script: "(function(){let c=0;const w=n=>{c++;for(const ch of n.children)w(ch);};w(document.body);return c+' nodes';})()",
},
],
},
];
This is comment number ${i + 1} with some discussion text.