mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
|
|
// @vitest-environment jsdom
|
||
|
|
|
||
|
|
import { act } 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 } from "./IssueChatThread";
|
||
|
|
|
||
|
|
vi.mock("@assistant-ui/react", () => ({
|
||
|
|
AssistantRuntimeProvider: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||
|
|
ThreadPrimitive: {
|
||
|
|
Root: ({ children, className }: { children: ReactNode; className?: string }) => (
|
||
|
|
<div data-testid="thread-root" className={className}>{children}</div>
|
||
|
|
),
|
||
|
|
Viewport: ({ children, className }: { children: ReactNode; className?: string }) => (
|
||
|
|
<div data-testid="thread-viewport" className={className}>{children}</div>
|
||
|
|
),
|
||
|
|
Empty: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||
|
|
Messages: () => <div data-testid="thread-messages" />,
|
||
|
|
},
|
||
|
|
MessagePrimitive: {
|
||
|
|
Root: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||
|
|
Content: () => null,
|
||
|
|
},
|
||
|
|
useAui: () => ({ thread: () => ({ append: vi.fn() }) }),
|
||
|
|
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("./MarkdownBody", () => ({
|
||
|
|
MarkdownBody: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("./MarkdownEditor", () => ({
|
||
|
|
MarkdownEditor: () => <textarea aria-label="Issue chat editor" />,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("./InlineEntitySelector", () => ({
|
||
|
|
InlineEntitySelector: () => null,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("./Identity", () => ({
|
||
|
|
Identity: ({ name }: { name: string }) => <span>{name}</span>,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("./OutputFeedbackButtons", () => ({
|
||
|
|
OutputFeedbackButtons: () => null,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("./AgentIconPicker", () => ({
|
||
|
|
AgentIcon: () => null,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("./StatusBadge", () => ({
|
||
|
|
StatusBadge: ({ status }: { status: string }) => <span>{status}</span>,
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("../hooks/usePaperclipIssueRuntime", () => ({
|
||
|
|
usePaperclipIssueRuntime: () => ({}),
|
||
|
|
}));
|
||
|
|
|
||
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
|
|
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
|
||
|
|
|
||
|
|
describe("IssueChatThread", () => {
|
||
|
|
let container: HTMLDivElement;
|
||
|
|
|
||
|
|
beforeEach(() => {
|
||
|
|
container = document.createElement("div");
|
||
|
|
document.body.appendChild(container);
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
container.remove();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("drops the count heading and does not use an internal scrollbox", () => {
|
||
|
|
const root = createRoot(container);
|
||
|
|
|
||
|
|
act(() => {
|
||
|
|
root.render(
|
||
|
|
<MemoryRouter>
|
||
|
|
<IssueChatThread
|
||
|
|
comments={[]}
|
||
|
|
linkedRuns={[]}
|
||
|
|
timelineEvents={[]}
|
||
|
|
liveRuns={[]}
|
||
|
|
onAdd={async () => {}}
|
||
|
|
showComposer={false}
|
||
|
|
enableLiveTranscriptPolling={false}
|
||
|
|
/>
|
||
|
|
</MemoryRouter>,
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(container.textContent).toContain("Jump to latest");
|
||
|
|
expect(container.textContent).not.toContain("Chat (");
|
||
|
|
|
||
|
|
const viewport = container.querySelector('[data-testid="thread-viewport"]') as HTMLDivElement | null;
|
||
|
|
expect(viewport).not.toBeNull();
|
||
|
|
expect(viewport?.className).not.toContain("overflow-y-auto");
|
||
|
|
expect(viewport?.className).not.toContain("max-h-[70vh]");
|
||
|
|
|
||
|
|
act(() => {
|
||
|
|
root.unmount();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|