Files
kandev/apps/web/components/task/file-viewer-content.test.tsx
T

112 lines
3.2 KiB
TypeScript

import { act, render } from "@testing-library/react";
import type { EditorView } from "@codemirror/view";
import { useLayoutEffect } from "react";
import { afterEach, describe, expect, it, vi } from "vitest";
const editorHarness = vi.hoisted(() => ({
autoCreateView: null as EditorView | null,
extensions: [] as unknown[],
onCreateEditor: null as ((view: EditorView) => void) | null,
}));
const revealPendingCodeMirrorCursor = vi.hoisted(() => vi.fn());
const clearCodeMirrorCursorFlash = vi.hoisted(() => vi.fn());
const codeMirrorCursorFlashExtension = vi.hoisted(() => ({}));
vi.mock("@uiw/react-codemirror", () => ({
default: ({
extensions,
onCreateEditor,
}: {
extensions: unknown[];
onCreateEditor: (view: EditorView) => void;
}) => {
editorHarness.extensions = extensions;
editorHarness.onCreateEditor = onCreateEditor;
useLayoutEffect(() => {
if (editorHarness.autoCreateView) onCreateEditor(editorHarness.autoCreateView);
}, [onCreateEditor]);
return <div data-testid="file-viewer-codemirror" />;
},
}));
vi.mock("@/lib/languages", () => ({
getCodeMirrorExtensionFromPath: () => null,
}));
vi.mock("@/components/editors/codemirror/use-codemirror-walkthrough-range", () => ({
useCodeMirrorWalkthroughRange: () => null,
}));
vi.mock("@/components/editors/codemirror/codemirror-cursor-navigation", () => ({
clearCodeMirrorCursorFlash,
codeMirrorCursorFlashExtension,
revealPendingCodeMirrorCursor,
}));
vi.mock("@/hooks/use-file-editors", () => ({
consumePendingCursorPosition: () => undefined,
}));
import { FileViewerContent } from "./file-viewer-content";
afterEach(() => {
editorHarness.autoCreateView = null;
vi.clearAllMocks();
});
describe("FileViewerContent cursor navigation", () => {
it("uses shared CodeMirror reveal behavior on mount and reused path changes", () => {
const view = {} as EditorView;
const rendered = render(
<FileViewerContent
path="src/first.ts"
content="first"
repo="frontend"
sessionId="session-1"
/>,
);
act(() => editorHarness.onCreateEditor?.(view));
expect(editorHarness.extensions).toContain(codeMirrorCursorFlashExtension);
expect(revealPendingCodeMirrorCursor).toHaveBeenLastCalledWith(
view,
"src/first.ts",
"frontend",
"session-1",
);
expect(revealPendingCodeMirrorCursor).toHaveBeenCalledTimes(1);
rendered.rerender(
<FileViewerContent
path="src/second.ts"
content="second"
repo="frontend"
sessionId="session-1"
/>,
);
expect(clearCodeMirrorCursorFlash).toHaveBeenLastCalledWith(view);
expect(revealPendingCodeMirrorCursor).toHaveBeenLastCalledWith(
view,
"src/second.ts",
"frontend",
"session-1",
);
});
it("consumes the initial pending reveal once when CodeMirror creates in a layout effect", () => {
const view = {} as EditorView;
editorHarness.autoCreateView = view;
render(
<FileViewerContent
path="src/first.ts"
content="first"
repo="frontend"
sessionId="session-1"
/>,
);
expect(revealPendingCodeMirrorCursor).toHaveBeenCalledTimes(1);
});
});