feat: add shared toolbox header and appearance
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import type { ToolboxAppManifest } from "@add-ideas/toolbox-contract";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import {
|
||||
TOOLBOX_PREFERENCES_KEY,
|
||||
type ToolboxAppManifest,
|
||||
} from "@add-ideas/toolbox-contract";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { AppShell } from "../src/index.js";
|
||||
|
||||
@@ -76,11 +79,15 @@ function catalogFetch() {
|
||||
}
|
||||
|
||||
describe("AppShell", () => {
|
||||
beforeEach(() => localStorage.clear());
|
||||
|
||||
it("renders identity, privacy, version, actions, and content standalone", async () => {
|
||||
const onHelp = vi.fn();
|
||||
const fetch = vi.fn();
|
||||
render(
|
||||
<AppShell
|
||||
app={currentApp}
|
||||
helpAction={{ onClick: onHelp }}
|
||||
appActions={<a href="/help">Help</a>}
|
||||
contextOptions={{
|
||||
location: "https://tools.example.test/pdf/",
|
||||
@@ -107,7 +114,14 @@ describe("AppShell", () => {
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole("navigation", { name: "Toolbox applications" }),
|
||||
).not.toBeInTheDocument();
|
||||
).toHaveTextContent("Open this app from Toolbox");
|
||||
expect(
|
||||
screen.getByRole("link", { name: /Source for PDF Workbench/u }),
|
||||
).toHaveAttribute("href", "https://git.example.test/pdf-tools");
|
||||
fireEvent.click(screen.getByRole("button", { name: "Help" }));
|
||||
expect(onHelp).toHaveBeenCalledOnce();
|
||||
expect(screen.getByText("Personalize")).toBeInTheDocument();
|
||||
expect(screen.getByText("Apps")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("loads same-origin context and creates full-page contextual switch links", async () => {
|
||||
@@ -171,7 +185,7 @@ describe("AppShell", () => {
|
||||
expect(fetch).not.toHaveBeenCalled();
|
||||
expect(
|
||||
screen.queryByRole("navigation", { name: "Toolbox applications" }),
|
||||
).not.toBeInTheDocument();
|
||||
).toHaveTextContent("Open this app from Toolbox");
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -199,4 +213,53 @@ describe("AppShell", () => {
|
||||
document.querySelector("[data-toolbox-context='standalone']"),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("uses and updates the shared light, dark, and system preference", async () => {
|
||||
localStorage.setItem(
|
||||
TOOLBOX_PREFERENCES_KEY,
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
pinned: [],
|
||||
order: [],
|
||||
hidden: [],
|
||||
theme: "dark",
|
||||
}),
|
||||
);
|
||||
render(
|
||||
<AppShell
|
||||
app={currentApp}
|
||||
contextOptions={{ location: "https://tools.example.test/pdf/" }}
|
||||
>
|
||||
PDF
|
||||
</AppShell>,
|
||||
);
|
||||
|
||||
const shell = document.querySelector(".toolbox-shell");
|
||||
expect(shell).toHaveAttribute("data-toolbox-theme", "dark");
|
||||
fireEvent.click(screen.getByText("Personalize"));
|
||||
fireEvent.click(screen.getByRole("button", { name: "Light" }));
|
||||
expect(shell).toHaveAttribute("data-toolbox-theme", "light");
|
||||
expect(
|
||||
JSON.parse(localStorage.getItem(TOOLBOX_PREFERENCES_KEY) ?? "{}"),
|
||||
).toMatchObject({ theme: "light" });
|
||||
});
|
||||
|
||||
it("resolves a relative explicit manifest URL against the deployed page", async () => {
|
||||
render(
|
||||
<AppShell
|
||||
app={currentApp}
|
||||
manifestUrl="./toolbox-app.json"
|
||||
contextOptions={{
|
||||
location: "https://tools.example.test/nested/pdf/index.html",
|
||||
}}
|
||||
>
|
||||
PDF
|
||||
</AppShell>,
|
||||
);
|
||||
|
||||
expect(document.querySelector(".toolbox-shell__icon")).toHaveAttribute(
|
||||
"src",
|
||||
"https://tools.example.test/nested/pdf/icon.svg",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user