import { act, renderHook } from "@testing-library/react";
import type {
AgentActivityMessage,
AgentActivitySnapshot
} from "@tutti-os/agent-activity-core";
import type { PropsWithChildren } from "react";
import { describe, expect, it } from "vitest";
import {
AgentGUIRuntimeProvider,
useAgentActivitySessionMessages,
type AgentGUIRuntime
} from "./agentActivityRuntime";
describe("useAgentActivitySessionMessages", () => {
it("delivers projected streaming text without rendering an unrelated Session", () => {
const messagesA = [message("session-a", "partial")];
const messagesB = [message("session-b", "settled")];
const store = createRuntimeStore(
snapshot({ "session-a": messagesA, "session-b": messagesB })
);
const wrapper = ({ children }: PropsWithChildren) => (
{children}
);
let rendersA = 0;
let rendersB = 0;
const renderedA = renderHook(
() => {
rendersA += 1;
return useAgentActivitySessionMessages("workspace-1", ["session-a"]);
},
{ wrapper }
);
renderHook(
() => {
rendersB += 1;
return useAgentActivitySessionMessages("workspace-1", ["session-b"]);
},
{ wrapper }
);
const initialRendersA = rendersA;
const initialRendersB = rendersB;
act(() => {
store.publish(
snapshot({
"session-a": [message("session-a", "partial text")],
"session-b": messagesB
})
);
});
expect(renderedA.result.current["session-a"]?.[0]?.payload.text).toBe(
"partial text"
);
expect(rendersA).toBeGreaterThan(initialRendersA);
expect(rendersB).toBe(initialRendersB);
});
it("subscribes to projected messages for child Sessions in the family", () => {
const rootMessages = [message("root", "root text")];
const store = createRuntimeStore(
snapshot({
root: rootMessages,
child: [message("child", "child partial")]
})
);
const wrapper = ({ children }: PropsWithChildren) => (
{children}
);
const rendered = renderHook(
() => useAgentActivitySessionMessages("workspace-1", ["root", "child"]),
{ wrapper }
);
act(() => {
store.publish(
snapshot({
root: rootMessages,
child: [message("child", "child partial text")]
})
);
});
expect(rendered.result.current.child?.[0]?.payload.text).toBe(
"child partial text"
);
});
});
function createRuntimeStore(initial: AgentActivitySnapshot) {
let current = initial;
const listeners = new Set<() => void>();
const runtime = {
getSnapshot: () => current,
origin: "test",
subscribe(_workspaceId: string, listener: () => void) {
listeners.add(listener);
return () => listeners.delete(listener);
}
} as unknown as AgentGUIRuntime;
return {
publish(next: AgentActivitySnapshot) {
current = next;
for (const listener of listeners) listener();
},
runtime
};
}
function snapshot(
sessionMessagesById: Record
): AgentActivitySnapshot {
return { sessionMessagesById } as AgentActivitySnapshot;
}
function message(agentSessionId: string, text: string): AgentActivityMessage {
return {
agentSessionId,
kind: "text",
messageId: `message-${agentSessionId}`,
occurredAtUnixMs: 1,
payload: { text },
role: "assistant",
sequence: 1,
status: "streaming",
turnId: "turn-1",
version: 1,
workspaceId: "workspace-1"
};
}