fix(frontend): make Pi operator tabs keyboard accessible
This commit is contained in:
@@ -172,11 +172,24 @@ test("shows a seven-step host-terminal workflow in scrollable platform tabs", as
|
||||
renderManagement();
|
||||
|
||||
const tablist = await screen.findByRole("tablist", { name: "Pi host platform" });
|
||||
expect(within(tablist).getAllByRole("tab").map((tab) => tab.textContent)).toEqual(["Linux", "macOS", "Windows"]);
|
||||
const [linuxTab, macosTab, windowsTab] = within(tablist).getAllByRole("tab");
|
||||
expect([linuxTab, macosTab, windowsTab].map((tab) => tab.textContent)).toEqual(["Linux", "macOS", "Windows"]);
|
||||
expect(screen.getByRole("dialog", { name: "Pi management" })).toHaveClass("max-h-[calc(100vh-6rem)]");
|
||||
expect(screen.getByTestId("pi-platform-instructions-scroll")).toHaveClass("overflow-y-scroll");
|
||||
expect(screen.queryByRole("tabpanel")).not.toBeInTheDocument();
|
||||
expect(within(tablist).getAllByRole("tab").every((tab) => tab.getAttribute("aria-selected") === "false")).toBe(true);
|
||||
expect([linuxTab, macosTab, windowsTab].every((tab) => tab.getAttribute("aria-selected") === "false")).toBe(true);
|
||||
expect(linuxTab).toHaveAttribute("tabindex", "0");
|
||||
expect(macosTab).toHaveAttribute("tabindex", "-1");
|
||||
expect(windowsTab).toHaveAttribute("tabindex", "-1");
|
||||
for (const tab of [linuxTab, macosTab, windowsTab]) {
|
||||
const panelId = tab.getAttribute("aria-controls");
|
||||
const panel = panelId ? document.getElementById(panelId) : null;
|
||||
expect(panel).toBeInTheDocument();
|
||||
expect(panel).toHaveAttribute("role", "tabpanel");
|
||||
expect(panel).toHaveAttribute("aria-labelledby", tab.id);
|
||||
expect(panel).toHaveAttribute("hidden");
|
||||
expect(panel).toHaveAttribute("tabindex", "-1");
|
||||
}
|
||||
expect(screen.getByText("Using the host terminal:")).toBeVisible();
|
||||
expect(screen.queryByText(/not this browser page/i)).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("region", { name: "Host update" })).not.toBeInTheDocument();
|
||||
@@ -185,9 +198,51 @@ test("shows a seven-step host-terminal workflow in scrollable platform tabs", as
|
||||
expect(await screen.findByText("Select the provider, model, and reasoning used for new Pi work. Credentials stay in protected host files.")).toBeVisible();
|
||||
expect(screen.getByText("Shows at most 200 recent lines with declared secret values removed.")).toBeVisible();
|
||||
|
||||
await user.click(within(tablist).getByRole("tab", { name: "Linux" }));
|
||||
linuxTab.focus();
|
||||
await user.keyboard("{ArrowRight}");
|
||||
expect(macosTab).toHaveFocus();
|
||||
expect(macosTab).toHaveAttribute("aria-selected", "true");
|
||||
expect(macosTab).toHaveAttribute("tabindex", "0");
|
||||
expect(linuxTab).toHaveAttribute("tabindex", "-1");
|
||||
await user.keyboard("{ArrowRight}");
|
||||
expect(windowsTab).toHaveFocus();
|
||||
expect(windowsTab).toHaveAttribute("aria-selected", "true");
|
||||
expect(windowsTab).toHaveAttribute("tabindex", "0");
|
||||
expect(macosTab).toHaveAttribute("tabindex", "-1");
|
||||
await user.keyboard("{ArrowRight}");
|
||||
expect(linuxTab).toHaveFocus();
|
||||
expect(linuxTab).toHaveAttribute("aria-selected", "true");
|
||||
await user.keyboard("{ArrowLeft}");
|
||||
expect(windowsTab).toHaveFocus();
|
||||
await user.keyboard("{Home}");
|
||||
expect(linuxTab).toHaveFocus();
|
||||
await user.keyboard("{End}");
|
||||
expect(windowsTab).toHaveFocus();
|
||||
|
||||
await user.click(windowsTab);
|
||||
expect(windowsTab).toHaveAttribute("aria-selected", "false");
|
||||
expect(screen.queryByRole("tabpanel")).not.toBeInTheDocument();
|
||||
await user.keyboard(" ");
|
||||
expect(windowsTab).toHaveAttribute("aria-selected", "true");
|
||||
await user.keyboard(" ");
|
||||
expect(windowsTab).toHaveAttribute("aria-selected", "false");
|
||||
await user.keyboard("{Enter}");
|
||||
expect(windowsTab).toHaveAttribute("aria-selected", "true");
|
||||
await user.keyboard("{Enter}");
|
||||
expect(windowsTab).toHaveAttribute("aria-selected", "false");
|
||||
|
||||
await user.click(linuxTab);
|
||||
const linux = screen.getByRole("tabpanel", { name: "Linux" });
|
||||
expect(within(linux).getAllByRole("listitem")).toHaveLength(7);
|
||||
expect(within(linux).getAllByRole("heading", { level: 4 }).map((heading) => heading.textContent)).toEqual([
|
||||
"Open the project root",
|
||||
"Edit the provider catalog",
|
||||
"Enable the model",
|
||||
"Set the provider credential",
|
||||
"Reload Pi configuration",
|
||||
"Update the Pi version",
|
||||
"Recover a failed update",
|
||||
]);
|
||||
expect(linux).toHaveTextContent("The deploy directory is in the ThothII project root, beside compose.yaml");
|
||||
expect(linux).toHaveTextContent("deploy/pi/models.json");
|
||||
expect(linux).toHaveTextContent("deploy/pi/settings.json");
|
||||
@@ -195,29 +250,53 @@ test("shows a seven-step host-terminal workflow in scrollable platform tabs", as
|
||||
expect(linux).toHaveTextContent("enabledModels uses provider/model identifiers");
|
||||
expect(linux).toHaveTextContent("PI_AUTH_FILE is a setting in the installation environment file");
|
||||
expect(linux).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi restart --yes --drain");
|
||||
expect(linux).toHaveTextContent("pi update --version <VERSION> --source build --yes --drain");
|
||||
expect(linux).toHaveTextContent("pi rollback --yes");
|
||||
expect(linux).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi update --version <VERSION> --source build --yes --drain");
|
||||
expect(linux).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi update --version <VERSION> --source pull --image <IMAGE>@sha256:<DIGEST> --yes --drain");
|
||||
expect(linux).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi rollback --yes");
|
||||
expect(linux).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi maintenance recover --yes");
|
||||
expect(linux).not.toHaveTextContent("~/.pi/agent/");
|
||||
|
||||
await user.click(within(tablist).getByRole("tab", { name: "macOS" }));
|
||||
await user.click(macosTab);
|
||||
const macos = screen.getByRole("tabpanel", { name: "macOS" });
|
||||
expect(within(macos).getAllByRole("listitem")).toHaveLength(7);
|
||||
expect(within(macos).getAllByRole("heading", { level: 4 }).map((heading) => heading.textContent)).toEqual([
|
||||
"Open the project root",
|
||||
"Edit the provider catalog",
|
||||
"Enable the model",
|
||||
"Set the provider credential",
|
||||
"Reload Pi configuration",
|
||||
"Update the Pi version",
|
||||
"Recover a failed update",
|
||||
]);
|
||||
expect(macos).toHaveTextContent("The deploy directory is in the ThothII project root, beside compose.yaml");
|
||||
expect(macos).toHaveTextContent("deploy/pi/models.json");
|
||||
expect(macos).toHaveTextContent("deploy/pi/settings.json");
|
||||
expect(macos).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi restart --yes --drain");
|
||||
expect(macos).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi update --version <VERSION> --source build --yes --drain");
|
||||
expect(macos).toHaveTextContent("pi maintenance recover --yes");
|
||||
expect(macos).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi update --version <VERSION> --source pull --image <IMAGE>@sha256:<DIGEST> --yes --drain");
|
||||
expect(macos).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi rollback --yes");
|
||||
expect(macos).toHaveTextContent("~/bin/thothctl --installation ~/thothii-installation.yaml pi maintenance recover --yes");
|
||||
|
||||
await user.click(within(tablist).getByRole("tab", { name: "Windows" }));
|
||||
await user.click(windowsTab);
|
||||
const windows = screen.getByRole("tabpanel", { name: "Windows" });
|
||||
expect(within(windows).getAllByRole("listitem")).toHaveLength(7);
|
||||
expect(within(windows).getAllByRole("heading", { level: 4 }).map((heading) => heading.textContent)).toEqual([
|
||||
"Open the project root",
|
||||
"Edit the provider catalog",
|
||||
"Enable the model",
|
||||
"Set the provider credential",
|
||||
"Reload Pi configuration",
|
||||
"Update the Pi version",
|
||||
"Recover a failed update",
|
||||
]);
|
||||
expect(windows).toHaveTextContent("The deploy directory is in the ThothII project root, beside compose.yaml");
|
||||
expect(windows).toHaveTextContent("deploy\\pi\\models.json");
|
||||
expect(windows).toHaveTextContent("deploy\\pi\\settings.json");
|
||||
expect(windows).toHaveTextContent('& (Resolve-Path "~\\bin\\thothctl-windows-amd64.exe") --installation (Resolve-Path "~\\thothii-installation.yaml") pi restart --yes --drain');
|
||||
expect(windows).toHaveTextContent('& (Resolve-Path "~\\bin\\thothctl-windows-amd64.exe") --installation (Resolve-Path "~\\thothii-installation.yaml") pi update --version <VERSION> --source build --yes --drain');
|
||||
expect(windows).toHaveTextContent("pi rollback --yes");
|
||||
expect(windows).toHaveTextContent('& (Resolve-Path "~\\bin\\thothctl-windows-amd64.exe") --installation (Resolve-Path "~\\thothii-installation.yaml") pi update --version <VERSION> --source pull --image <IMAGE>@sha256:<DIGEST> --yes --drain');
|
||||
expect(windows).toHaveTextContent('& (Resolve-Path "~\\bin\\thothctl-windows-amd64.exe") --installation (Resolve-Path "~\\thothii-installation.yaml") pi rollback --yes');
|
||||
expect(windows).toHaveTextContent('& (Resolve-Path "~\\bin\\thothctl-windows-amd64.exe") --installation (Resolve-Path "~\\thothii-installation.yaml") pi maintenance recover --yes');
|
||||
});
|
||||
|
||||
test("reloads installation defaults when the panel is reopened", async () => {
|
||||
|
||||
Reference in New Issue
Block a user