Files
openworker/surfaces/gui/e2e/access-section.spec.ts
T
Rohit C PrasadandDevika 2b45018ffa OpenWorker: initial import
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>
2026-07-21 11:09:41 -07:00

97 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// The rail's Access section (§32 — absorbs the §23 Session-settings drawer; the topbar
// row/glance machinery is retired). Contract: the header carries a PERMANENT summary of what
// the session can touch; expanding edits inline at rail width (no overlay, no dialog).
// Fixture state: browser + slack + github connected/enabled (github is two_way WITHOUT
// channels — relay mentions, no subscriptions), gmail recommended-not-connected, one
// primary root → summary "Browser, Slack +1 · 1 folder".
import { expect } from "@playwright/test";
import { test } from "./fixtures";
test("no topbar opener; the Access header IS the ambient glance; expanding edits inline", async ({
page,
}) => {
await page.goto("/");
await page.getByText("Draft the launch note").first().click();
// §32: the settings row/icon is gone from the topbar — the panel toggle is the one entry.
await expect(page.getByRole("button", { name: "Open session settings" })).toHaveCount(0);
await expect(page.getByTestId("session-settings-row")).toHaveCount(0);
// The trust surface is ambient: the collapsed header always shows the summary — and no
// nudge text ever renders at rest (§23's rule carried over).
const section = page.getByTestId("access-section");
await expect(section.getByTestId("access-summary")).toHaveText("Browser, Slack +1 · 1 folder");
await expect(section.getByText(/recommended/i)).toHaveCount(0);
// Expand → Sources (per-session toggles), Recommended (with its reason), Folders — all
// inline in the rail; no dialog appears anywhere.
await section.getByTestId("access-toggle").click();
const body = page.getByRole("region", { name: "Session access" });
await expect(body.getByText("Sources")).toBeVisible();
await expect(body.getByText("Slack", { exact: true })).toBeVisible();
await expect(body.getByText("email context for morning summaries")).toBeVisible();
await expect(body.getByTestId("drawer-directories").getByText("Temporary space")).toBeVisible();
await expect(page.getByRole("dialog")).toHaveCount(0);
// Channels is a chat capability, not a two_way one: Slack gets the drill-down, GitHub
// (two_way via the relay, no channel semantics) must NOT (owner report 2026-07-13).
await expect(body.getByRole("button", { name: /Channels ·/ })).toHaveCount(1);
await expect(body.getByText("GitHub", { exact: true })).toBeVisible();
});
test("+ Add a source: full catalog on focus, filter as you type → connect-in-context; connected sources never match", async ({
page,
}) => {
await page.goto("/");
await page.getByText("Draft the launch note").first().click();
await page.getByTestId("access-toggle").click();
// Focusing the empty input shows the FULL catalog (FB-012) — every available connector
// minus the already-connected three, before any typing.
await page.getByTestId("access-add-source").click();
const search = page.getByTestId("access-add-search");
await expect(search).toBeFocused();
const rows = page.locator('[data-testid^="access-add-"]:not([data-testid="access-add-search"])');
await expect(rows).toHaveCount(9); // 12 in the catalog browser/slack/github (connected)
await expect(page.getByTestId("access-add-notion")).toBeVisible();
// Already-connected sources don't match (Slack and GitHub are connected in fixtures)…
await search.fill("slack");
await expect(page.getByText("No match — see all on the Connectors page below.")).toBeVisible();
await search.fill("github");
await expect(page.getByText("No match — see all on the Connectors page below.")).toBeVisible();
// …and clearing the query restores the full list ("filter as you type", not search-only).
await search.fill("");
await expect(rows).toHaveCount(9);
// Capability aliases match too: "calendar" surfaces Outlook (title alone never would).
await search.fill("calendar");
await expect(page.getByTestId("access-add-outlook")).toBeVisible();
// …the long tail does: Notion is in the catalog but neither connected nor recommended.
await search.fill("notion");
await page.getByTestId("access-add-notion").click();
// Lands in the SAME connect-in-context child view the Recommended flow uses, with the
// scope-semantics line; back returns to the Sources list.
const body = page.getByRole("region", { name: "Session access" });
await expect(body.getByText("Connecting makes Notion available to all your coworkers", { exact: false })).toBeVisible();
await expect(body.getByPlaceholder("ntn_…")).toBeVisible();
await body.getByRole("button", { name: "Back to sources" }).click();
await expect(body.getByText("Slack", { exact: true })).toBeVisible();
});
test("per-session mute round-trips; the summary follows", async ({ page }) => {
await page.goto("/");
await page.getByText("Draft the launch note").first().click();
const section = page.getByTestId("access-section");
await section.getByTestId("access-toggle").click();
const body = page.getByRole("region", { name: "Session access" });
// Muting Slack for this session drops it from the live summary (the fixture flips
// enabled on POST and the section reloads).
await body.getByTitle("Enabled for this session — tap to mute here").nth(1).click();
await expect(section.getByTestId("access-summary")).toHaveText("Browser, GitHub · 1 folder");
});