返回 DeepSeek-Reasonix
file-navigation-revision.test.tsx
根目录 / desktop / frontend / src / __tests__ / file-navigation-revision.test.tsx
1 // Run: node --import ./scripts/svg-stub-register.mjs --import tsx src/__tests__/file-navigation-revision.test.tsx
2 //
3 // A dock record's revision counter belongs to that record: when the dock reads
4 // a different record, its counter starts over, and the panel must not mistake
5 // the new record's first command for a revision it already applied.
6
7 import assert from "node:assert/strict";
8 import React, { act } from "react";
9 import { renderFilesWorkspace } from "./workspace-panel-test-harness";
10 import { WorkspaceDockRegion, type WorkspaceDockRegionProps } from "../app-shell/WorkspaceDockRegion";
11 import { LocaleProvider } from "../lib/i18n";
12 import { performResourceAction, fileNavigationOwner } from "../lib/fileNavigationCommands";
13 import { fileNavigationKey } from "../lib/fileNavigationOwner";
14 import { useActivityBarStore } from "../store/activityBar";
15
16 const { dom, root, dockTabId } = await renderFilesWorkspace({
17 ReadPresentedFileForTab: async (_tab, _tool, path) => ({ path, body: `CONTENT ${path}`, size: 20, truncated: false, binary: false }),
18 ListDirForTab: async () => [],
19 });
20 const props: WorkspaceDockRegionProps = {
21 visible: true, overlay: false, mode: "files", showContext: false,
22 t: key => key, onPickEntry: () => {}, remote: { onClose: () => {} }, context: {} as WorkspaceDockRegionProps["context"],
23 workspace: { open: true, tabId: "tab-one", cwd: "/repo", maximized: false, onClose: () => {}, onToggleMaximized: () => {} },
24 workspaceKey: "revision-test", workspaceRoot: "/repo",
25 };
26 const sessionTabId = "tab-one";
27 const paint = () => act(async () => root.render(
28 <LocaleProvider><WorkspaceDockRegion {...props} workspace={{ ...props.workspace, tabId: sessionTabId }} visible /></LocaleProvider>,
29 ));
30 const record = () => fileNavigationOwner().getSnapshot(fileNavigationKey({ sessionTabId, dockTabId }));
31 const open = async (path: string) => {
32 await act(async () => performResourceAction({ hostId: "local", tabId: sessionTabId, path, source: "presented", toolCallId: "call" }, "preview"));
33 };
34 const onChangesView = () => document.querySelector(".workspace-panel--changed-overview") !== null;
35
36 await paint();
37 await open("first.md");
38 await paint();
39 assert.equal(record()?.navigation?.revision, 1, "the dock's first navigation is revision one");
40
41 // The user moves to the Changes view, then the dock tab is closed and reopened:
42 // the dock reads a new record, and the revision is one sequence for the whole
43 // instance, so that record cannot hand out a revision the panel already applied.
44 const changesView = [...document.querySelectorAll<HTMLButtonElement>("button")]
45 .find(button => /^changes$/i.test((button.textContent ?? "").trim()));
46 assert(changesView, "the dock exposes its Changes view");
47 await act(async () => { changesView!.dispatchEvent(new window.MouseEvent("click", { bubbles: true })); });
48 assert(onChangesView(), "the dock is on the Changes view");
49 const closedGeneration = record()!.generation;
50 await act(async () => {
51 useActivityBarStore.getState().closeTab(dockTabId);
52 fileNavigationOwner().retain([]);
53 await Promise.resolve();
54 });
55 assert.equal(record(), null, "a closed dock tab keeps no record");
56 await act(async () => useActivityBarStore.getState().reopenTab(dockTabId));
57 await paint();
58 assert.equal(record()?.generation, closedGeneration + 1, "reopening starts a new dock lifetime");
59 await open("second.md");
60 await paint();
61 assert.equal(record()?.navigation?.revision, 2, "the new record's navigation continues the instance's sequence");
62 assert.equal(record()?.selected?.resource.path, "second.md");
63 assert(!onChangesView(), "that command is applied: the dock returns to its file preview");
64 assert(document.body.textContent?.includes("CONTENT second.md") === true, "and shows the file it opened");
65
66 await act(async () => root.unmount());
67 dom.window.close();
68 console.log("PASS a dock reading another record still applies that record's first navigation");
69
69 lines Plain Text