Files
kandev/apps/web/components/task/file-editor-content.test.tsx
T
2026-09-07 13:45:28 +01:00

215 lines
6.8 KiB
TypeScript

import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { FileEditorContentProps } from "./file-editor-content";
import { FileEditorContent } from "./file-editor-content";
const htmlPreview = vi.hoisted(() => ({
status: "ready" as const,
url: "http://api.test/port-proxy/session-1/43127/reports/index.html?v=4",
error: null,
isPublishing: false,
publish: vi
.fn()
.mockResolvedValue("http://api.test/port-proxy/session-1/43127/reports/index.html?v=4"),
reset: vi.fn(),
}));
const openBrowserPanel = vi.hoisted(() => vi.fn());
const HTML_CONTENT = "<h1>Report</h1>";
const HTML_PREVIEW_TEST_ID = "html-preview";
const HTML_PATH = "reports/index.html";
const MONACO_EDITOR_TEST_ID = "monaco-editor";
const PREVIEW_HTML_LABEL = "Preview HTML";
const SESSION_ID = "session-1";
vi.mock("@/hooks/use-editor-resolver", () => ({
useEditorProvider: () => "monaco",
}));
vi.mock("@/components/editors/monaco/monaco-code-editor", () => ({
MonacoCodeEditor: (props: { path: string; content: string; onPreviewHtml?: () => void }) => (
<div data-testid="monaco-editor" data-path={props.path} data-content={props.content}>
{props.onPreviewHtml && (
<button type="button" onClick={props.onPreviewHtml}>
Preview HTML
</button>
)}
</div>
),
}));
vi.mock("@/components/editors/codemirror/codemirror-code-editor", () => ({
CodeMirrorCodeEditor: () => <div data-testid="codemirror-editor" />,
}));
vi.mock("@/hooks/use-html-preview-publisher", () => ({
useHtmlPreviewPublisher: () => htmlPreview,
}));
vi.mock("@/lib/state/dockview-store", () => ({
useDockviewStore: (selector: (state: { openBrowserPanel: typeof openBrowserPanel }) => unknown) =>
selector({ openBrowserPanel }),
}));
vi.mock("./html-preview-content", () => ({
HtmlPreviewContent: ({
previewUrl,
onTogglePreview,
onRefresh,
onOpenInBrowser,
}: {
previewUrl?: string | null;
onTogglePreview: () => void;
onRefresh?: () => void;
onOpenInBrowser?: () => void;
}) => (
<div data-testid="html-preview" data-url={previewUrl}>
<button type="button" onClick={onTogglePreview}>
Show code
</button>
<button type="button" onClick={onRefresh}>
Refresh HTML preview
</button>
<button type="button" onClick={onOpenInBrowser}>
Open in Browser panel
</button>
</div>
),
}));
vi.mock("./markdown-preview-content", () => ({
MarkdownPreviewContent: (props: { content: string }) => (
<div data-testid="markdown-preview" data-content={props.content} />
),
}));
afterEach(cleanup);
beforeEach(() => {
vi.clearAllMocks();
});
const baseProps: FileEditorContentProps = {
path: HTML_PATH,
content: HTML_CONTENT,
originalContent: "<h1>Old report</h1>",
isDirty: true,
isSaving: false,
onChange: vi.fn(),
onSave: vi.fn(),
};
describe("FileEditorContent preview selection", () => {
it("replaces HTML source with the published iframe and restores the unchanged buffer", () => {
render(<FileEditorContent {...baseProps} sessionId={SESSION_ID} previewKind="html" />);
expect(screen.getByTestId(MONACO_EDITOR_TEST_ID).getAttribute("data-content")).toBe(
HTML_CONTENT,
);
fireEvent.click(screen.getByRole("button", { name: PREVIEW_HTML_LABEL }));
expect(htmlPreview.publish).toHaveBeenCalledWith({
path: HTML_PATH,
content: HTML_CONTENT,
});
expect(screen.queryByTestId(MONACO_EDITOR_TEST_ID)).toBeNull();
expect(screen.getByTestId(HTML_PREVIEW_TEST_ID).getAttribute("data-url")).toBe(htmlPreview.url);
fireEvent.click(screen.getByRole("button", { name: "Show code" }));
expect(screen.getByTestId(MONACO_EDITOR_TEST_ID).getAttribute("data-content")).toBe(
HTML_CONTENT,
);
expect(baseProps.onChange).not.toHaveBeenCalled();
});
it("opens a Browser panel only from the explicit preview action", () => {
render(<FileEditorContent {...baseProps} sessionId={SESSION_ID} previewKind="html" />);
fireEvent.click(screen.getByRole("button", { name: PREVIEW_HTML_LABEL }));
expect(openBrowserPanel).not.toHaveBeenCalled();
fireEvent.click(screen.getByRole("button", { name: "Open in Browser panel" }));
expect(openBrowserPanel).toHaveBeenCalledWith(htmlPreview.url);
});
it("refreshes from the latest unsaved buffer", () => {
const { rerender } = render(
<FileEditorContent {...baseProps} sessionId={SESSION_ID} previewKind="html" />,
);
fireEvent.click(screen.getByRole("button", { name: PREVIEW_HTML_LABEL }));
rerender(
<FileEditorContent
{...baseProps}
content="<h1>Updated report</h1>"
sessionId={SESSION_ID}
previewKind="html"
/>,
);
fireEvent.click(screen.getByRole("button", { name: "Refresh HTML preview" }));
expect(htmlPreview.publish).toHaveBeenLastCalledWith({
path: HTML_PATH,
content: "<h1>Updated report</h1>",
});
});
it("restores source and invalidates the published URL when file identity changes", () => {
const { rerender } = render(
<FileEditorContent {...baseProps} sessionId={SESSION_ID} previewKind="html" />,
);
fireEvent.click(screen.getByRole("button", { name: PREVIEW_HTML_LABEL }));
expect(screen.getByTestId(HTML_PREVIEW_TEST_ID)).toBeTruthy();
rerender(
<FileEditorContent
{...baseProps}
path="reports/next.html"
sessionId="session-2"
previewKind="html"
/>,
);
expect(screen.getByTestId(MONACO_EDITOR_TEST_ID).getAttribute("data-path")).toBe(
"reports/next.html",
);
expect(screen.queryByTestId(HTML_PREVIEW_TEST_ID)).toBeNull();
expect(htmlPreview.reset).toHaveBeenCalled();
rerender(<FileEditorContent {...baseProps} sessionId={SESSION_ID} previewKind="html" />);
expect(screen.getByTestId(MONACO_EDITOR_TEST_ID).getAttribute("data-path")).toBe(HTML_PATH);
expect(screen.queryByTestId(HTML_PREVIEW_TEST_ID)).toBeNull();
});
it("keeps Markdown preview selection separate from HTML preview", () => {
render(
<FileEditorContent
{...baseProps}
path="README.md"
previewKind="markdown"
renderedPreview
onTogglePreview={vi.fn()}
/>,
);
expect(screen.getByTestId("markdown-preview").getAttribute("data-content")).toBe(
"<h1>Report</h1>",
);
expect(screen.queryByTestId(HTML_PREVIEW_TEST_ID)).toBeNull();
});
it("returns to the configured source editor when preview is inactive", () => {
render(
<FileEditorContent
{...baseProps}
previewKind="html"
renderedPreview={false}
onTogglePreview={vi.fn()}
/>,
);
expect(screen.getByTestId(MONACO_EDITOR_TEST_ID)).toBeTruthy();
expect(screen.queryByTestId(HTML_PREVIEW_TEST_ID)).toBeNull();
});
});