mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-04 07:20:10 +00:00
Imported from andrewyng/aisuite@1b4bbf303e (contents of its platform/ directory, hoisted to the repo root). Development history prior to this commit lives in that repository. Co-authored-by: Devika <devikaverma11@gmail.com>
112 lines
5.5 KiB
TypeScript
112 lines
5.5 KiB
TypeScript
// Settings ▸ Personas ▸ Gallery: the catalog lives in a screen-sized modal opened
|
|
// from the Personas page (link → featured carousel + list → in-modal solo page →
|
|
// informed install → Done lands back on Personas). Plus the page-level delete
|
|
// affordance for non-builtin personas.
|
|
import { expect } from "@playwright/test";
|
|
import { test } from "./fixtures";
|
|
|
|
async function openPersonas(page) {
|
|
// Personas is launch-flagged off by default — these suites cover the flagged-on flows.
|
|
await page.addInitScript(() => localStorage.setItem("ocw.flag.personas", "1"));
|
|
await page.goto("/");
|
|
await page.getByTestId("account-row").click();
|
|
await page.getByRole("button", { name: "Settings", exact: true }).click();
|
|
await page.getByRole("button", { name: "Personas", exact: true }).click();
|
|
await expect(page.getByTestId("gallery-link")).toBeVisible();
|
|
}
|
|
|
|
async function openGallery(page) {
|
|
await openPersonas(page);
|
|
await page.getByTestId("gallery-link").click();
|
|
await expect(page.getByTestId("gallery-modal")).toBeVisible();
|
|
}
|
|
|
|
test("slow cloud: skeleton shows while the gallery loads, never a blank body", async ({
|
|
page,
|
|
}) => {
|
|
// The real gallery is a cloud round-trip (Lambda + Dynamo) that can take seconds;
|
|
// delay the mocked endpoints to assert the skeleton bridges the gap.
|
|
await page.route("**/v1/cloud/status", async (route) => {
|
|
await new Promise((r) => setTimeout(r, 1200));
|
|
await route.fulfill({ json: { ok: true, signed_in: false } });
|
|
});
|
|
await openGallery(page);
|
|
await expect(page.getByTestId("gallery-loading")).toBeVisible();
|
|
await expect(page.getByTestId("gallery-loading")).toContainText("Loading the gallery");
|
|
// Resolves into the real body (signed-out prompt here) once the cloud answers.
|
|
await expect(page.getByTestId("gallery-signin")).toBeVisible({ timeout: 10_000 });
|
|
await expect(page.getByTestId("gallery-loading")).toHaveCount(0);
|
|
});
|
|
|
|
test("signed out: modal prompts for sign-in, manual install path unaffected", async ({ page }) => {
|
|
await openGallery(page);
|
|
const prompt = page.getByTestId("gallery-signin");
|
|
await expect(prompt).toContainText("needs a (free) cloud sign-in");
|
|
await expect(prompt).toContainText("always works without an account");
|
|
await expect(prompt.getByRole("button", { name: "Sign in" })).toBeVisible();
|
|
// Esc closes; the Personas page (with its dir/Git importer) is still there.
|
|
await page.keyboard.press("Escape");
|
|
await expect(page.getByTestId("gallery-modal")).not.toBeVisible();
|
|
await expect(page.getByRole("button", { name: "Install", exact: true })).toBeVisible();
|
|
});
|
|
|
|
test("signed in: featured carousel + list; solo page installs informed; Done returns", async ({
|
|
page,
|
|
}) => {
|
|
await openGallery(page);
|
|
await page.getByTestId("gallery-signin").getByRole("button", { name: "Sign in" }).click();
|
|
|
|
// Featured carousel holds the flagged persona; the list holds both.
|
|
const featured = page.getByTestId("gallery-featured");
|
|
await expect(featured).toBeVisible({ timeout: 10_000 });
|
|
await expect(featured).toContainText("Sales Coworker");
|
|
await expect(featured).not.toContainText("Recruiter");
|
|
await expect(page.getByTestId("gallery-recruiter")).toContainText("View & install");
|
|
await expect(page.getByTestId("gallery-team-teaser")).toContainText("coming soon");
|
|
|
|
// Search narrows the list.
|
|
await page.getByPlaceholder("Search personas").fill("recruit");
|
|
await expect(page.getByTestId("gallery-sales")).not.toBeVisible();
|
|
await page.getByPlaceholder("Search personas").fill("");
|
|
|
|
// Solo page: pitch + manifest-derived capabilities BEFORE install.
|
|
await page.getByTestId("gallery-sales").click();
|
|
const detail = page.getByTestId("gallery-detail");
|
|
await expect(detail).toContainText("Walk into every call already knowing the account");
|
|
const caps = page.getByTestId("gallery-capabilities");
|
|
await expect(caps).toContainText("verified from its manifest");
|
|
await expect(caps).toContainText("files, search, todo");
|
|
await expect(caps).toContainText("hubspot · core");
|
|
await expect(caps).toContainText("read deals and contacts");
|
|
|
|
await detail.getByRole("button", { name: "Install" }).click();
|
|
await expect(detail).toContainText("disabled until you approve and enable it");
|
|
|
|
// Done closes the modal, landing back on the Personas page.
|
|
await detail.getByRole("button", { name: "Done" }).click();
|
|
await expect(page.getByTestId("gallery-modal")).not.toBeVisible();
|
|
await expect(page.getByTestId("gallery-link")).toBeVisible();
|
|
});
|
|
|
|
test("back link returns from the solo page to the catalog", async ({ page }) => {
|
|
await openGallery(page);
|
|
await page.getByTestId("gallery-signin").getByRole("button", { name: "Sign in" }).click();
|
|
await page.getByTestId("gallery-sales").click({ timeout: 10_000 });
|
|
await expect(page.getByTestId("gallery-detail")).toBeVisible();
|
|
await page.getByRole("button", { name: "← Gallery" }).click();
|
|
await expect(page.getByTestId("gallery-cards")).toBeVisible();
|
|
});
|
|
|
|
test("delete: non-builtin personas removable after confirm; built-ins are not", async ({
|
|
page,
|
|
}) => {
|
|
await openPersonas(page);
|
|
// Built-ins expose no delete affordance.
|
|
await expect(page.getByTestId("persona-delete-cowork")).toHaveCount(0);
|
|
// Non-builtin: trash → inline confirm → row gone (works signed out).
|
|
await expect(page.getByText("Acme Notes")).toBeVisible();
|
|
await page.getByTestId("persona-delete-acme-notes").click();
|
|
await page.getByTestId("persona-delete-confirm-acme-notes").click();
|
|
await expect(page.getByText("Acme Notes")).not.toBeVisible();
|
|
});
|