Files
openwork/evals/specs/desktop-render-cycle-stability.e2e.test.ts

108 lines
4.3 KiB
TypeScript

import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { expect, onTestFinished } from "vitest";
import type { Surface } from "@openwork/cdp";
import { clickButton, evalIn, fill, waitFor, waitForText } from "@openwork/behaviors";
import { desktop } from "@openwork/hosts";
import { needs, test, unmetNeeds } from "@openwork/testkit";
import type { TestNeeds } from "@openwork/testkit";
const requirements: TestNeeds = {
optIn: ["OPENWORK_EVAL_E2E_TESTS"],
};
const missingRequirements = unmetNeeds(requirements, process.env);
const title = missingRequirements.length > 0
? `desktop render-cycle stability skipped — needs: ${missingRequirements.join(", ")}`
: "workspace onboarding settles without timer-driven React commits";
interface WelcomeRenderFacts {
commitCount: number;
longestHalfSecondRun: number;
recentCommitCount: number;
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function readNumber(value: Record<string, unknown>, key: string): number {
const field = Reflect.get(value, key);
if (typeof field !== "number") throw new Error(`Render facts omitted numeric ${key}.`);
return field;
}
async function readWelcomeRenderFacts(app: Surface): Promise<WelcomeRenderFacts> {
const value = await evalIn(app, `(() => {
const profiler = window.__openwork.snapshot().profiler;
const zone = profiler.zones.find((entry) => entry.id === "WelcomeRoute");
const commits = profiler.recent
.filter((entry) => entry.id === "WelcomeRoute")
.map((entry) => entry.commitAt);
let longestHalfSecondRun = 0;
let currentRun = 0;
for (let index = 1; index < commits.length; index += 1) {
const gap = commits[index] - commits[index - 1];
currentRun = gap >= 400 && gap <= 600 ? currentRun + 1 : 0;
longestHalfSecondRun = Math.max(longestHalfSecondRun, currentRun);
}
return {
commitCount: zone?.commitCount ?? 0,
longestHalfSecondRun,
recentCommitCount: commits.length,
};
})()`);
if (!isRecord(value)) throw new Error("Welcome render facts were not an object.");
return {
commitCount: readNumber(value, "commitCount"),
longestHalfSecondRun: readNumber(value, "longestHalfSecondRun"),
recentCommitCount: readNumber(value, "recentCommitCount"),
};
}
test(title, async ({ evidence }) => {
needs(requirements);
await using app = await desktop({
name: "desktop-render-cycle-stability",
env: { VITE_OPENWORK_PROFILER: "1" },
});
let workspacePath = "";
onTestFinished(async () => {
if (workspacePath) await rm(workspacePath, { recursive: true, force: true });
});
expect(app.readiness.route).toContain("/welcome");
await waitForText(app, "Welcome to OpenWork");
await evalIn(app, `(() => {
localStorage.setItem("openwork.debug.profilerOverlay", "1");
location.reload();
return true;
})()`);
await waitForText(app, "Welcome to OpenWork", { timeoutMs: 30_000 });
await clickButton(app, "Use Without Cloud");
await waitFor(app, 'Boolean(document.querySelector(\'input[placeholder="/workspace/my-project"]\'))', {
timeoutMs: 15_000,
label: "local workspace folder input",
});
workspacePath = await mkdtemp(join(tmpdir(), "openwork-render-cycle-"));
await fill(app, 'input[placeholder="/workspace/my-project"]', workspacePath);
await clickButton(app, "Use this folder");
await waitForText(app, "Skip and use the free model", { timeoutMs: 90_000 });
const completed = await readWelcomeRenderFacts(app);
expect(completed.recentCommitCount).toBeGreaterThan(0);
expect(completed.longestHalfSecondRun).toBeLessThan(2);
await new Promise((resolve) => setTimeout(resolve, 2_500));
const settled = await readWelcomeRenderFacts(app);
expect(settled.commitCount - completed.commitCount).toBeLessThanOrEqual(1);
evidence.recordAssertionEvidence(
"Workspace creation does not drive an invisible half-second render loop",
`recentWelcomeCommits=${completed.recentCommitCount}; longestHalfSecondRun=${completed.longestHalfSecondRun}; settledCommitDelta=${settled.commitCount - completed.commitCount}`,
completed.longestHalfSecondRun < 2 && settled.commitCount - completed.commitCount <= 1,
);
});