返回 DeepSeek-Reasonix
workspace-selection-isolation.test.tsx
根目录 / desktop / frontend / src / __tests__ / workspace-selection-isolation.test.tsx
1 // Run: tsx src/__tests__/workspace-selection-isolation.test.tsx
2
3 import { act } from "react";
4 import { flushPromises, renderFilesWorkspace, waitFor } from "./workspace-panel-test-harness";
5
6 let passed = 0;
7 let failed = 0;
8
9 function ok(value: boolean, label: string) {
10 if (value) {
11 process.stdout.write(` PASS ${label}\n`);
12 passed += 1;
13 } else {
14 process.stdout.write(` FAIL ${label}\n`);
15 failed += 1;
16 }
17 }
18
19 console.log("\nworkspace selection isolation");
20
21 const changeDetailPaths: string[] = [];
22 const readFilePaths: string[] = [];
23 const { dom, root, rerender } = await renderFilesWorkspace({
24 ListDirForTab: async (_tabId, dir) => dir === "" ? [{ name: "notes.txt", isDir: false }] : [],
25 WorkspaceChanges: async () => ({
26 files: [{ path: "src/changed.ts", sources: ["git"], gitStatus: "M" }],
27 gitAvailable: true,
28 }),
29 WorkspaceChangeDetail: async (_tabId, path) => {
30 changeDetailPaths.push(path);
31 return { source: "git", diff: "changed diff" };
32 },
33 ReadFileForTab: async (_tabId, path) => {
34 readFilePaths.push(path);
35 return { path, body: "file preview", size: 12, truncated: false, binary: false };
36 },
37 });
38
39 await waitFor("files view entry", () => document.body.textContent?.includes("notes.txt") === true);
40 await act(async () => {
41 document.querySelector<HTMLButtonElement>('[data-workspace-path="notes.txt"]')
42 ?.dispatchEvent(new window.MouseEvent("click", { bubbles: true }));
43 await flushPromises();
44 });
45 await waitFor("selected file read", () => readFilePaths.includes("notes.txt"));
46 await waitFor("selected file preview", () => document.body.textContent?.includes("file preview") === true);
47
48 await rerender({ initialViewMode: "changed" });
49 await waitFor("changes overview", () => document.body.textContent?.includes("changed.ts") === true);
50 ok(changeDetailPaths.length === 0, "entering Changes does not request diff detail for the Files selection");
51 ok(document.querySelector(".workspace-panel--changed-overview") !== null, "entering Changes opens its overview instead of leaking the Files selection");
52
53 await act(async () => {
54 document.querySelector<HTMLButtonElement>(".workspace-change")
55 ?.dispatchEvent(new window.MouseEvent("click", { bubbles: true }));
56 await flushPromises();
57 });
58 await waitFor("selected change detail", () => changeDetailPaths.includes("src/changed.ts"));
59
60 await rerender({ initialViewMode: "files" });
61 await waitFor("restored file preview", () => document.body.textContent?.includes("file preview") === true);
62 ok(changeDetailPaths.every((path) => path === "src/changed.ts"), "Changes requests only its own selected path");
63 ok(document.body.textContent?.includes("notes.txt") === true, "returning to Files restores the prior file selection after viewing a change");
64
65 await rerender({
66 initialViewMode: "changed",
67 changeListRequest: {
68 id: 1,
69 changes: [{ key: "scoped-change", path: "src/changed.ts", meta: "M", time: "", detail: "changed" }],
70 },
71 });
72 await waitFor("scoped Changes list", () => document.body.textContent?.includes("Session changes") === true);
73 await rerender({ initialViewMode: "files", changeListRequest: null });
74 await waitFor("file preview after scoped Changes", () => document.body.textContent?.includes("file preview") === true);
75 ok(document.body.textContent?.includes("notes.txt") === true, "scoped Changes requests preserve the Files preview state");
76
77 await rerender({ initialViewMode: "changed" });
78 await waitFor("change before scope switch", () => document.body.textContent?.includes("changed.ts") === true);
79 await act(async () => {
80 document.querySelector<HTMLButtonElement>(".workspace-change")
81 ?.dispatchEvent(new window.MouseEvent("click", { bubbles: true }));
82 await flushPromises();
83 });
84 await waitFor("change selected before scope switch", () => changeDetailPaths.includes("src/changed.ts"));
85 const callsBeforeScopeSwitch = changeDetailPaths.length;
86 await rerender({ workspaceScopeKey: "other-session" });
87 await waitFor("new scope Changes overview", () => document.querySelector(".workspace-panel--changed-overview") !== null);
88 ok(changeDetailPaths.length === callsBeforeScopeSwitch, "workspace scope changes do not request the previous scope's selected change");
89
90 await act(async () => {
91 root.unmount();
92 });
93 dom.window.close();
94
95 console.log(`\n${passed} passed, ${failed} failed, ${passed + failed} total`);
96 if (failed > 0) process.exit(1);
97
97 lines Plain Text