import { afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/vitest";
import { FileManagerGrid } from "../../src/frontend/FileManagerGrid";
import type { FileItem } from "../../src/frontend/host-types";
vi.mock("react-i18next", () => ({
useTranslation: () => ({ t: (key: string) => key }),
initReactI18next: { type: "3rdParty", init: () => {} },
}));
vi.mock("@tanstack/react-virtual", () => ({
useVirtualizer: ({ count }: { count: number }) => ({
getTotalSize: () => count * 29,
getVirtualItems: () =>
Array.from({ length: count }, (_, index) => ({
index,
key: index,
start: index * 29,
size: 29,
})),
measureElement: () => {},
measure: () => {},
}),
}));
const file: FileItem = {
name: "notes.txt",
path: "/notes.txt",
type: "file",
modified: "2026-09-01",
owner: "owner",
permissions: "-rw-r--r--",
};
const props = {
files: [file],
selectedFiles: [file],
viewMode: "list" as const,
onFileOpen: vi.fn(),
onSelectionChange: vi.fn(),
onRefresh: vi.fn(),
};
afterEach(() => {
cleanup();
vi.restoreAllMocks();
});
describe("remote file rename", () => {
it.each(["F2", "F6"])("starts rename with %s in the visible pane", (key) => {
vi.spyOn(HTMLElement.prototype, "offsetParent", "get").mockReturnValue(
document.body,
);
const onStartEdit = vi.fn();
render();
fireEvent.keyDown(document, { key });
expect(onStartEdit).toHaveBeenCalledExactlyOnceWith(file);
});
it("does not rename files in a hidden pane", () => {
vi.spyOn(HTMLElement.prototype, "offsetParent", "get").mockReturnValue(
null,
);
const onStartEdit = vi.fn();
render();
fireEvent.keyDown(document, { key: "F2" });
expect(onStartEdit).not.toHaveBeenCalled();
});
it("hides metadata while editing and commits the new name", () => {
const onRename = vi.fn();
const { rerender } = render();
expect(screen.getByText(file.modified!)).toBeInTheDocument();
rerender(
,
);
expect(screen.queryByText(file.modified!)).not.toBeInTheDocument();
expect(screen.queryByText(file.permissions!)).not.toBeInTheDocument();
const input = screen.getByRole("textbox");
fireEvent.change(input, { target: { value: "renamed.txt" } });
fireEvent.keyDown(input, { key: "Enter" });
expect(onRename).toHaveBeenCalledWith(file, "renamed.txt");
rerender();
expect(screen.getByText(file.modified!)).toBeInTheDocument();
});
});