101 lines
4.4 KiB
TypeScript
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);
|
|
});
|