Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/controller/useAgentConversationMessagePaging.spec.tsx
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

177 lines
5.2 KiB
TypeScript

import { act, renderHook } from "@testing-library/react";
import type { AgentActivityMessagePage } from "@tutti-os/agent-activity-core";
import { StrictMode, type ReactNode } from "react";
import { describe, expect, it, vi } from "vitest";
import type { AgentGUIRuntime } from "../../../agentActivityRuntime";
import { createTestAgentSessionEngine } from "../../../shared/testing/createTestAgentSessionEngine";
import { useAgentConversationMessagePaging } from "./useAgentConversationMessagePaging";
describe("useAgentConversationMessagePaging", () => {
it("binds the AgentGUI runtime to the shared message controller", async () => {
const engine = createTestAgentSessionEngine("workspace-1");
engine.dispatch({
messages: [],
sessionMessageWindows: [
{
agentSessionId: "session-1",
hasOlderMessages: true,
oldestLoadedVersion: 5
}
],
type: "message/snapshotReceived",
workspaceId: "workspace-1"
});
const listSessionMessages = vi.fn().mockResolvedValue({
hasMore: false,
latestVersion: 1,
messages: [
{
agentSessionId: "session-1",
kind: "text",
messageId: "message-1",
occurredAtUnixMs: 1,
payload: {},
role: "assistant",
sequence: 1,
turnId: "turn-1",
version: 1
}
]
});
const onOlderPageLoadingChanged = vi.fn();
const { result, unmount } = renderHook(() =>
useAgentConversationMessagePaging({
diagnostics: { error: vi.fn(), page: vi.fn() },
getActiveSessionId: () => "session-1",
isMounted: () => true,
onOlderPageLoadingChanged,
runtime: {
listSessionMessages
} as unknown as AgentGUIRuntime,
sessionEngine: engine,
workspaceId: "workspace-1"
})
);
await act(async () => {
await result.current.loadOlderMessages();
});
expect(listSessionMessages).toHaveBeenCalledWith({
agentSessionId: "session-1",
beforeVersion: 5,
cache: false,
limit: 100,
order: "desc",
signal: expect.any(AbortSignal),
workspaceId: "workspace-1"
});
expect(onOlderPageLoadingChanged.mock.calls).toEqual([
[false],
[true],
[false]
]);
unmount();
engine.dispose();
});
it("disposes its request-owning controller on unmount", async () => {
const engine = createTestAgentSessionEngine("workspace-1");
engine.dispatch({
messages: [],
sessionMessageWindows: [
{
agentSessionId: "session-1",
hasOlderMessages: true,
oldestLoadedVersion: 5
}
],
type: "message/snapshotReceived",
workspaceId: "workspace-1"
});
let requestSignal!: AbortSignal;
let resolvePage!: (page: AgentActivityMessagePage) => void;
const { result, unmount } = renderHook(() =>
useAgentConversationMessagePaging({
diagnostics: { error: vi.fn(), page: vi.fn() },
getActiveSessionId: () => "session-1",
isMounted: () => true,
onOlderPageLoadingChanged: vi.fn(),
runtime: {
listSessionMessages: ({ signal }: { signal: AbortSignal }) => {
requestSignal = signal;
return new Promise<AgentActivityMessagePage>((resolve) => {
resolvePage = resolve;
});
}
} as unknown as AgentGUIRuntime,
sessionEngine: engine,
workspaceId: "workspace-1"
})
);
let request!: Promise<void>;
act(() => {
request = result.current.loadOlderMessages();
});
expect(requestSignal.aborted).toBe(false);
unmount();
await Promise.resolve();
expect(requestSignal.aborted).toBe(true);
resolvePage({ hasMore: false, latestVersion: 0, messages: [] });
await request;
engine.dispose();
});
it("remains usable after the Strict Mode lifecycle probe", async () => {
const engine = createTestAgentSessionEngine("workspace-1");
engine.dispatch({
messages: [],
sessionMessageWindows: [
{
agentSessionId: "session-1",
hasOlderMessages: true,
oldestLoadedVersion: 5
}
],
type: "message/snapshotReceived",
workspaceId: "workspace-1"
});
const listSessionMessages = vi.fn().mockResolvedValue({
hasMore: false,
latestVersion: 1,
messages: []
});
const { result, unmount } = renderHook(
() =>
useAgentConversationMessagePaging({
diagnostics: { error: vi.fn(), page: vi.fn() },
getActiveSessionId: () => "session-1",
isMounted: () => true,
onOlderPageLoadingChanged: vi.fn(),
runtime: {
listSessionMessages
} as unknown as AgentGUIRuntime,
sessionEngine: engine,
workspaceId: "workspace-1"
}),
{
wrapper: ({ children }: { children: ReactNode }) => (
<StrictMode>{children}</StrictMode>
)
}
);
await act(async () => {
await result.current.loadOlderMessages();
});
expect(listSessionMessages).toHaveBeenCalledOnce();
unmount();
engine.dispose();
});
});