Skip to content

Commit 425de63

Browse files
committed
test: add icon theme review scenes
1 parent cee8e30 commit 425de63

5 files changed

Lines changed: 279 additions & 0 deletions

File tree

e2e-ui/report/build-report.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,29 @@ describe("build-report", () => {
2929
});
3030
});
3131

32+
it("keeps icon review scene manifest entries grouped by exact scene id and theme", () => {
33+
const entry = buildManifestEntry({
34+
scene: {
35+
id: "toast-icon-review",
36+
title: "Toast Icon Review",
37+
category: "toast",
38+
source: "showcase",
39+
description: "Theme review for toast icons",
40+
},
41+
screenshotPath: "screenshots/toast/toast-icon-review/mobile__graphite-light__en.png",
42+
variant: {
43+
device: "mobile",
44+
theme: "graphite-light",
45+
locale: "en",
46+
},
47+
});
48+
49+
expect(entry).toMatchObject({
50+
id: "toast-icon-review",
51+
theme: "graphite-light",
52+
});
53+
});
54+
3255
it("renders a report html shell with filters and grouped scenes", () => {
3356
const html = renderReportHtml([
3457
{

packages/web/src/ui-preview/catalog.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,19 @@ describe("UI preview catalog", () => {
174174
expect(await screen.findByText(/delete preview-file.ts/i)).toBeInTheDocument();
175175
expect(document.querySelector(".modal-card")).toBeTruthy();
176176
});
177+
178+
it("renders the workspace icon review scene with file tree and git status content", async () => {
179+
renderScene("workspace-icon-review");
180+
181+
expect(await screen.findByText("packages")).toBeInTheDocument();
182+
expect(document.querySelector(".file-tree-shell")).toBeTruthy();
183+
expect(document.querySelector(".git-panel, .git-row")).toBeTruthy();
184+
});
185+
186+
it("renders the toast icon review scene with four status tones", async () => {
187+
renderScene("toast-icon-review");
188+
189+
expect(await screen.findByText("Workspace opened")).toBeInTheDocument();
190+
expect(document.querySelectorAll(".toast").length).toBeGreaterThanOrEqual(4);
191+
});
177192
});

packages/web/src/ui-preview/scene-metadata.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ import { UI_PREVIEW_SCENE_METADATA } from "./scene-metadata";
77
const source = readFileSync(`${process.cwd()}/src/ui-preview/scene-metadata.ts`, "utf8");
88

99
describe("ui preview scene metadata", () => {
10+
it("registers icon-focused scenes for theme review", () => {
11+
expect(UI_PREVIEW_SCENE_METADATA.map((scene) => scene.id)).toEqual(
12+
expect.arrayContaining([
13+
"workspace-icon-review",
14+
"toast-icon-review",
15+
"supervisor-icon-review",
16+
])
17+
);
18+
});
19+
1020
it("covers every built-in theme for route-backed workspace scenes", () => {
1121
expect(
1222
UI_PREVIEW_SCENE_METADATA.filter(

packages/web/src/ui-preview/scene-metadata.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,41 @@ export const UI_PREVIEW_SCENE_METADATA: UiPreviewSceneMetadata[] = [
211211
locales: ["zh", "en"],
212212
capture: { selector: ".toast-container" },
213213
},
214+
{
215+
id: "workspace-icon-review",
216+
title: "Workspace Icon Review",
217+
category: "page",
218+
source: "showcase",
219+
description:
220+
"File tree, git states, terminal empty state, and mobile dock/supervisor icon surfaces for theme review.",
221+
devices: ["desktop", "mobile"],
222+
themes: allThemeIds(),
223+
locales: ["zh", "en"],
224+
capture: { selector: ".workspace-icon-review" },
225+
},
226+
{
227+
id: "toast-icon-review",
228+
title: "Toast Icon Review",
229+
category: "toast",
230+
source: "showcase",
231+
description:
232+
"Success, warning, error, and info toast icons rendered together for theme review.",
233+
devices: ["desktop", "mobile"],
234+
themes: allThemeIds(),
235+
locales: ["zh", "en"],
236+
capture: { selector: ".toast-container" },
237+
},
238+
{
239+
id: "supervisor-icon-review",
240+
title: "Supervisor Icon Review",
241+
category: "modal",
242+
source: "showcase",
243+
description: "Supervisor dialog header icon and destructive callout surface review.",
244+
devices: ["desktop", "mobile"],
245+
themes: allThemeIds(),
246+
locales: ["zh", "en"],
247+
capture: { selector: ".supervisor-dialog, .mobile-sheet__content" },
248+
},
214249
{
215250
id: "mobile-workspace-drawer",
216251
title: "Mobile Workspace Drawer",

packages/web/src/ui-preview/scenes/showcase-scenes.tsx

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
import type { FileNode, GitStatus, Supervisor, Workspace, WorktreeInfo } from "@coder-studio/core";
2+
import {
3+
CircleAlert,
4+
CircleCheckBig,
5+
CircleDot,
6+
File,
7+
FileCode2,
8+
FileJson2,
9+
FileText,
10+
Folder,
11+
Image as ImageIcon,
12+
} from "lucide-react";
213
import { ConfirmDialog, EmptyState, Notice, Sheet } from "../../components/ui";
314
import { CommandPalette } from "../../features/command-palette";
415
import { ToastContainer } from "../../features/notifications";
16+
import { MobileSupervisorBadge } from "../../features/supervisor/views/mobile/mobile-supervisor-badge";
517
import { MobileSupervisorSheet } from "../../features/supervisor/views/mobile/mobile-supervisor-sheet";
618
import { ObjectiveDialog } from "../../features/supervisor/views/shared/objective-dialog";
719
import { XtermPlaceholder } from "../../features/terminal-panel/views/shared/xterm-placeholder";
20+
import { MobileDock } from "../../features/workspace/views/mobile/mobile-dock";
821
import { MobileWorkspaceDrawer } from "../../features/workspace/views/mobile/mobile-workspace-drawer";
922
import { BranchQuickPick } from "../../features/workspace/views/shared/branch-quick-pick";
1023
import { WorkspaceLaunchModal } from "../../features/workspace/views/shared/workspace-launch-modal";
@@ -166,6 +179,189 @@ export function createShowcaseScenes(): UiPreviewSceneDefinition[] {
166179
}),
167180
render: () => <ToastContainer />,
168181
}),
182+
scene("workspace-icon-review", {
183+
router: () => ({ initialEntries: ["/workspace"], path: "/workspace" }),
184+
seed: (context) => ({
185+
...context,
186+
supervisorBySessionId: {
187+
"session-preview-1": supervisor,
188+
},
189+
}),
190+
render: (context) =>
191+
context.device === "mobile" ? (
192+
<div className="workspace-icon-review">
193+
<div className="mobile-shell__stage">
194+
<div className="flex items-center justify-between gap-3 p-3">
195+
<MobileSupervisorBadge sessionId="session-preview-1" onOpen={() => {}} />
196+
</div>
197+
<div className="file-tree-shell file-tree-shell--mobile">
198+
<div className="tree-item">
199+
<span className="tree-icon folder" aria-hidden="true">
200+
<Folder size={14} />
201+
</span>
202+
<span>packages</span>
203+
</div>
204+
<div className="tree-item">
205+
<span className="tree-icon code" aria-hidden="true">
206+
<FileCode2 size={14} />
207+
</span>
208+
<span>app.tsx</span>
209+
</div>
210+
<div className="tree-item">
211+
<span className="tree-icon data" aria-hidden="true">
212+
<FileJson2 size={14} />
213+
</span>
214+
<span>theme.json</span>
215+
</div>
216+
<div className="tree-item">
217+
<span className="tree-icon doc" aria-hidden="true">
218+
<FileText size={14} />
219+
</span>
220+
<span>README.md</span>
221+
</div>
222+
</div>
223+
<MobileDock activeItem="files" onSelectItem={() => {}} />
224+
</div>
225+
</div>
226+
) : (
227+
<div className="workspace-icon-review">
228+
<div className="file-tree-shell">
229+
<div className="tree-item">
230+
<span className="tree-icon folder" aria-hidden="true">
231+
<Folder size={14} />
232+
</span>
233+
<span>packages</span>
234+
</div>
235+
<div className="tree-item">
236+
<span className="tree-icon code" aria-hidden="true">
237+
<FileCode2 size={14} />
238+
</span>
239+
<span>app.tsx</span>
240+
</div>
241+
<div className="tree-item">
242+
<span className="tree-icon data" aria-hidden="true">
243+
<FileJson2 size={14} />
244+
</span>
245+
<span>theme.json</span>
246+
</div>
247+
<div className="tree-item">
248+
<span className="tree-icon doc" aria-hidden="true">
249+
<FileText size={14} />
250+
</span>
251+
<span>README.md</span>
252+
</div>
253+
<div className="tree-item">
254+
<span className="tree-icon media" aria-hidden="true">
255+
<ImageIcon size={14} />
256+
</span>
257+
<span>logo.png</span>
258+
</div>
259+
<div className="tree-item">
260+
<span className="tree-icon file" aria-hidden="true">
261+
<File size={14} />
262+
</span>
263+
<span>LICENSE</span>
264+
</div>
265+
</div>
266+
<div className="git-panel">
267+
<div className="git-row">
268+
<span className="git-row-icon git-row-icon-staged" aria-hidden="true">
269+
<CircleCheckBig size={12} />
270+
</span>
271+
<span>staged.ts</span>
272+
</div>
273+
<div className="git-row">
274+
<span className="git-row-icon git-row-icon-modified" aria-hidden="true">
275+
<CircleAlert size={12} />
276+
</span>
277+
<span>modified.ts</span>
278+
</div>
279+
<div className="git-row">
280+
<span className="git-row-icon git-row-icon-deleted" aria-hidden="true">
281+
<CircleAlert size={12} />
282+
</span>
283+
<span>deleted.ts</span>
284+
</div>
285+
<div className="git-row">
286+
<span className="git-row-icon git-row-icon-untracked" aria-hidden="true">
287+
<CircleDot size={12} />
288+
</span>
289+
<span>untracked.ts</span>
290+
</div>
291+
</div>
292+
</div>
293+
),
294+
}),
295+
scene("toast-icon-review", {
296+
router: () => ({ initialEntries: ["/"], path: "/" }),
297+
seed: (context) => ({
298+
...context,
299+
toasts: [
300+
{
301+
id: "toast-success",
302+
kind: "success",
303+
title: "Workspace opened",
304+
body: "coder-studio is ready.",
305+
createdAt: 1,
306+
duration: 0,
307+
},
308+
{
309+
id: "toast-warning",
310+
kind: "warning",
311+
title: "Unsaved config",
312+
body: "Review pending changes before continuing.",
313+
createdAt: 2,
314+
duration: 0,
315+
},
316+
{
317+
id: "toast-error",
318+
kind: "error",
319+
title: "Failed to refresh provider config",
320+
body: "Retry after checking the provider settings.",
321+
createdAt: 3,
322+
duration: 0,
323+
},
324+
{
325+
id: "toast-info",
326+
kind: "info",
327+
title: "Theme preview active",
328+
body: "Comparing icon palettes across themes.",
329+
createdAt: 4,
330+
duration: 0,
331+
},
332+
],
333+
}),
334+
render: () => <ToastContainer />,
335+
}),
336+
scene("supervisor-icon-review", {
337+
router: () => ({ initialEntries: ["/workspace"], path: "/workspace" }),
338+
seed: (context) => ({
339+
...context,
340+
supervisorBySessionId: {
341+
"session-preview-1": supervisor,
342+
},
343+
supervisorDialog: {
344+
open: true,
345+
sessionId: "session-preview-1",
346+
mode: "disable",
347+
draftObjective: supervisor.objective,
348+
draftEvaluatorProviderId: "claude",
349+
draftEvaluatorModel: "",
350+
draftMaxSupervisionCount: "0",
351+
draftScheduledAt: "",
352+
},
353+
}),
354+
render: (context) =>
355+
context.device === "mobile" ? (
356+
<MobileSupervisorSheet
357+
sessionId="session-preview-1"
358+
workspaceId={workspace.id}
359+
onClose={() => {}}
360+
/>
361+
) : (
362+
<ObjectiveDialog workspaceId={workspace.id} sessionId="session-preview-1" />
363+
),
364+
}),
169365
scene("mobile-workspace-drawer", {
170366
router: () => ({ initialEntries: ["/workspace"], path: "/workspace" }),
171367
seed: (context) => ({

0 commit comments

Comments
 (0)