// @vitest-environment jsdom
import { act, createRef, forwardRef, useImperativeHandle } from "react";
import type { ReactNode } from "react";
import { createRoot } from "react-dom/client";
import { MemoryRouter } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { IssueChatThread, canStopIssueChatRun, resolveAssistantMessageFoldedState } from "./IssueChatThread";
const { markdownEditorFocusMock } = vi.hoisted(() => ({
markdownEditorFocusMock: vi.fn(),
}));
const { appendMock } = vi.hoisted(() => ({
appendMock: vi.fn(async () => undefined),
}));
const { threadMessagesMock } = vi.hoisted(() => ({
threadMessagesMock: vi.fn(() =>
),
}));
const {
captureComposerViewportSnapshotMock,
restoreComposerViewportSnapshotMock,
shouldPreserveComposerViewportMock,
} = vi.hoisted(() => ({
captureComposerViewportSnapshotMock: vi.fn(),
restoreComposerViewportSnapshotMock: vi.fn(),
shouldPreserveComposerViewportMock: vi.fn(),
}));
vi.mock("@assistant-ui/react", () => ({
AssistantRuntimeProvider: ({ children }: { children: ReactNode }) => {children}
,
ThreadPrimitive: {
Root: ({ children, className }: { children: ReactNode; className?: string }) => (
{children}
),
Viewport: ({ children, className }: { children: ReactNode; className?: string }) => (
{children}
),
Empty: ({ children }: { children: ReactNode }) => {children}
,
Messages: () => threadMessagesMock(),
},
MessagePrimitive: {
Root: ({ children }: { children: ReactNode }) => {children}
,
Content: () => null,
Parts: () => null,
},
useAui: () => ({ thread: () => ({ append: appendMock }) }),
useAuiState: () => false,
useMessage: () => ({
id: "message",
role: "assistant",
createdAt: new Date("2026-04-06T12:00:00.000Z"),
content: [],
metadata: { custom: {} },
status: { type: "complete" },
}),
}));
vi.mock("./transcript/useLiveRunTranscripts", () => ({
useLiveRunTranscripts: () => ({
transcriptByRun: new Map(),
hasOutputForRun: () => false,
}),
}));
vi.mock("../lib/issue-chat-scroll", async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
captureComposerViewportSnapshot: captureComposerViewportSnapshotMock.mockImplementation(actual.captureComposerViewportSnapshot),
restoreComposerViewportSnapshot: restoreComposerViewportSnapshotMock.mockImplementation(actual.restoreComposerViewportSnapshot),
shouldPreserveComposerViewport: shouldPreserveComposerViewportMock.mockImplementation(actual.shouldPreserveComposerViewport),
};
});
vi.mock("./MarkdownBody", () => ({
MarkdownBody: ({ children }: { children: ReactNode }) => {children}
,
}));
vi.mock("./MarkdownEditor", () => ({
MarkdownEditor: forwardRef(({
value = "",
onChange,
placeholder,
className,
contentClassName,
}: {
value?: string;
onChange?: (value: string) => void;
placeholder?: string;
className?: string;
contentClassName?: string;
}, ref) => {
useImperativeHandle(ref, () => ({
focus: markdownEditorFocusMock,
}));
return (