Files
openwork/evals/specs/library-state-tabs.e2e.test.ts

101 lines
4.4 KiB
TypeScript

import { fileURLToPath } from "node:url";
import { expect, test } from "vitest";
import { createAndSelectWorkspace, evalIn, waitFor } from "@openwork/behaviors";
import { createVisualEvidence, screenshot, validate } from "@openwork/test-evidence";
import { desktop } from "@openwork/hosts";
const e2eTestsEnabled = process.env.OPENWORK_EVAL_E2E_TESTS === "1";
const title = e2eTestsEnabled
? "Library shows readiness state tabs"
: "Library state tabs skipped: set OPENWORK_EVAL_E2E_TESTS=1 to opt in";
const repoRoot = fileURLToPath(new URL("../..", import.meta.url));
test.skipIf(!e2eTestsEnabled)(title, async () => {
await using app = await desktop({ name: "library-state-tabs" });
await createAndSelectWorkspace(app, { path: repoRoot });
await evalIn(app, `(() => {
window.location.hash = "#/settings/general";
return true;
})()`);
await waitFor(
app,
`[...document.querySelectorAll("button")].some((button) => button.textContent?.trim() === "Library")`,
{ timeoutMs: 60_000, label: "Library settings navigation entry" },
);
const openedLibrary = await evalIn(app, `(() => {
const button = [...document.querySelectorAll("button")]
.find((entry) => entry.textContent?.trim() === "Library");
if (!(button instanceof HTMLElement)) return false;
button.click();
return true;
})()`);
expect(openedLibrary).toBe(true);
await waitFor(
app,
`window.location.hash.includes("/settings/extensions")
&& [...document.querySelectorAll("h1, h2")].some((heading) => heading.textContent?.trim() === "Library")
&& Boolean(document.querySelector('[role="tablist"][aria-label="Library state"]'))
&& [...document.querySelectorAll('[role="tab"]')].some((tab) => tab.textContent?.trim() === "All")
&& [...document.querySelectorAll('[role="tab"]')].some((tab) => (tab.textContent ?? "").includes("Ready to use"))`,
{ timeoutMs: 60_000, label: "Library title and state tabs" },
);
const headerHasConnectedCount = await evalIn(app, `(() => {
const description = [...document.querySelectorAll("p")]
.find((entry) => entry.textContent?.includes("Skills, connections, and tools your agent can use."));
return /apps? connected/i.test(description?.parentElement?.textContent ?? "");
})()`);
expect(headerHasConnectedCount).toBe(false);
const descriptionRenderedOnce = await evalIn(
app,
`document.body.innerText.split("Skills, connections, and tools your agent can use.").length - 1`,
);
expect(descriptionRenderedOnce).toBe(1);
const clickedReady = await evalIn(app, `(() => {
const tab = [...document.querySelectorAll('[role="tab"]')]
.find((entry) => (entry.textContent ?? "").includes("Ready to use"));
if (!(tab instanceof HTMLElement)) return false;
tab.click();
return true;
})()`);
expect(clickedReady).toBe(true);
await waitFor(
app,
`window.location.hash.endsWith("/extensions/ready")
&& document.querySelectorAll("[data-inventory-group]").length > 0
&& [...document.querySelectorAll("[data-inventory-group]")]
.every((row) => row.getAttribute("data-inventory-group") === "ready")`,
{ timeoutMs: 30_000, label: "Ready Library deep link and rows" },
);
const hasNeedsSignin = await evalIn(
app,
`[...document.querySelectorAll('[role="tab"]')].some((tab) => (tab.textContent ?? "").includes("Needs your sign-in"))`,
);
if (hasNeedsSignin === true) {
const clicked = await evalIn(app, `(() => {
const tab = [...document.querySelectorAll('[role="tab"]')]
.find((entry) => (entry.textContent ?? "").includes("Needs your sign-in"));
if (!(tab instanceof HTMLElement)) return false;
tab.click();
return true;
})()`);
expect(clicked).toBe(true);
await waitFor(
app,
`window.location.hash.includes("/extensions/needs-sign-in")
&& document.querySelectorAll("[data-inventory-group]").length > 0
&& [...document.querySelectorAll("[data-inventory-group]")]
.every((row) => row.getAttribute("data-inventory-group") === "needs_signin")`,
{ timeoutMs: 30_000, label: "only needs-signin Library rows" },
);
}
await using visualEvidence = createVisualEvidence("library-state-tabs");
const shot = await screenshot(app);
const seen = await validate(shot, ["A Library settings page shows state tabs with counts"]);
expect(seen.ok, seen.why).toBe(true);
await visualEvidence.recordScreenshot(shot, seen);
});