import { describe, expect, it } from "vite-plus/test"; import { EventId, MessageId, ProjectId, ProviderInstanceId, ThreadId, TurnId, type OrchestrationThread, type OrchestrationThreadActivity,} from "@t3tools/contracts"; import { buildThreadFeed, deriveThreadFeedPresentation, type ThreadFeedActivity, type ThreadFeedEntry,} from "./threadActivity"; function makeActivity( input: Partial<OrchestrationThreadActivity> & Pick<OrchestrationThreadActivity, "id" | "kind" | "summary" | "createdAt">,): OrchestrationThreadActivity { return { tone: "info", payload: {}, turnId: null, ...input, };} function makeThread( input: Partial<OrchestrationThread> & Pick<OrchestrationThread, "id" | "projectId" | "title">,): OrchestrationThread { return { modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.4" }, runtimeMode: "full-access", interactionMode: "default", branch: null, worktreePath: null, latestTurn: null, createdAt: "2026-04-01T00:00:00.000Z", updatedAt: "2026-04-01T00:00:00.000Z", archivedAt: null, deletedAt: null, messages: [], proposedPlans: [], activities: [], checkpoints: [], session: null, ...input, settledOverride: input.settledOverride ?? null, settledAt: input.settledAt ?? null, };} describe("buildThreadFeed", () => { it("keeps historic work entries attributed to their turns", () => { const thread = makeThread({ id: ThreadId.make("thread-1"), projectId: ProjectId.make("project-1"), title: "Runtime warning thread", latestTurn: { turnId: TurnId.make("turn-latest"), state: "running", requestedAt: "2026-04-01T00:00:00.000Z", startedAt: "2026-04-01T00:00:01.000Z", completedAt: null, assistantMessageId: null, }, activities: [ makeActivity({ id: EventId.make("activity-old"), kind: "runtime.warning", summary: "Runtime warning", createdAt: "2026-04-01T00:00:02.000Z", turnId: TurnId.make("turn-old"), payload: { message: "Old warning", }, }), makeActivity({ id: EventId.make("activity-latest"), kind: "runtime.warning", summary: "Runtime warning", createdAt: "2026-04-01T00:00:03.000Z", turnId: TurnId.make("turn-latest"), payload: { message: "Latest warning", }, }), ], }); const feed = buildThreadFeed(thread); expect(feed).toMatchObject([ { type: "activity-group", turnId: "turn-old", activities: [{ id: "activity-old", turnId: "turn-old" }], }, { type: "activity-group", turnId: "turn-latest", activities: [{ id: "activity-latest", turnId: "turn-latest" }], }, ]); }); it("collapses matching tool lifecycle rows like desktop", () => { const thread = makeThread({ id: ThreadId.make("thread-2"), projectId: ProjectId.make("project-1"), title: "Collapsed tools", latestTurn: { turnId: TurnId.make("turn-1"), state: "completed", requestedAt: "2026-04-01T00:00:00.000Z", startedAt: "2026-04-01T00:00:01.000Z", completedAt: "2026-04-01T00:00:03.000Z", assistantMessageId: null, }, activities: [ makeActivity({ id: EventId.make("tool-updated"), kind: "tool.updated", tone: "tool", summary: "Run tests", createdAt: "2026-04-01T00:00:01.000Z", turnId: TurnId.make("turn-1"), payload: { title: "Run tests", itemType: "command_execution", detail: "/bin/zsh -lc 'bun run test'", }, }), makeActivity({ id: EventId.make("tool-completed"), kind: "tool.completed", tone: "tool", summary: "Run tests completed", createdAt: "2026-04-01T00:00:02.000Z", turnId: TurnId.make("turn-1"), payload: { title: "Run tests", itemType: "command_execution", detail: "/bin/zsh -lc 'bun run test'", }, }), ], }); const feed = buildThreadFeed(thread); const group = feed[0]; expect(group).toMatchObject({ type: "activity-group", }); if (!group || group.type !== "activity-group") { return; } expect(group.activities).toEqual([ { id: "tool-completed", createdAt: "2026-04-01T00:00:02.000Z", turnId: "turn-1", summary: "Run tests", detail: "bun run test", fullDetail: "/bin/zsh -lc 'bun run test'", copyText: "Run tests\nbun run test\n/bin/zsh -lc 'bun run test'", icon: "command", toolLike: true, status: "success", }, ]); }); it("keeps MCP inputs available to expanded mobile work rows", () => { const turnId = TurnId.make("turn-mcp"); const thread = makeThread({ id: ThreadId.make("thread-mcp"), projectId: ProjectId.make("project-1"), title: "Expandable MCP call", latestTurn: { turnId, state: "completed", requestedAt: "2026-04-01T00:00:00.000Z", startedAt: "2026-04-01T00:00:01.000Z", completedAt: "2026-04-01T00:00:03.000Z", assistantMessageId: null, }, activities: [ makeActivity({ id: EventId.make("mcp-completed"), kind: "tool.completed", tone: "tool", summary: "Call repository tool", createdAt: "2026-04-01T00:00:02.000Z", turnId, payload: { title: "Call repository tool", itemType: "mcp_tool_call", detail: "repository.search", status: "completed", data: { item: { server: "repository", tool: "search", arguments: { query: "work log" }, }, }, }, }), ], }); const group = buildThreadFeed(thread)[0]; expect(group).toMatchObject({ type: "activity-group" }); if (!group || group.type !== "activity-group") { return; } expect(group.activities[0]?.icon).toBe("wrench"); expect(group.activities[0]?.fullDetail).toContain('"query": "work log"'); expect(group.activities[0]?.fullDetail).toContain("repository.search"); }); it("folds settled turn work while leaving the terminal answer visible", () => { const turnId = TurnId.make("turn-1"); const thread = makeThread({ id: ThreadId.make("thread-3"), projectId: ProjectId.make("project-1"), title: "Folded work", latestTurn: { turnId, state: "completed", requestedAt: "2026-04-01T00:00:00.000Z", startedAt: "2026-04-01T00:00:01.000Z", completedAt: "2026-04-01T00:00:18.000Z", assistantMessageId: MessageId.make("assistant-final"), }, messages: [ { id: MessageId.make("assistant-commentary"), role: "assistant", text: "I am checking.", turnId, streaming: false, createdAt: "2026-04-01T00:00:02.000Z", updatedAt: "2026-04-01T00:00:03.000Z", }, { id: MessageId.make("assistant-final"), role: "assistant", text: "Done.", turnId, streaming: false, createdAt: "2026-04-01T00:00:17.000Z", updatedAt: "2026-04-01T00:00:18.000Z", }, ], activities: [ makeActivity({ id: EventId.make("tool-completed"), kind: "tool.completed", tone: "tool", summary: "Read files", createdAt: "2026-04-01T00:00:05.000Z", turnId, payload: { title: "Read files", itemType: "file_read", status: "completed", }, }), ], }); const feed = buildThreadFeed(thread); const collapsed = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set()); expect(collapsed.map((entry) => entry.id)).toEqual(["turn-fold:turn-1", "assistant-final"]); expect(collapsed[0]).toMatchObject({ type: "turn-fold", label: "Worked for 17s", expanded: false, }); const expanded = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set([turnId])); expect(expanded.map((entry) => entry.id)).toEqual([ "turn-fold:turn-1", "assistant-commentary", "tool-completed", "assistant-final", ]); }); it("measures a steer-superseded turn from its user boundary through trailing work", () => { const firstTurnId = TurnId.make("turn-1"); const secondTurnId = TurnId.make("turn-2"); const thread = makeThread({ id: ThreadId.make("thread-steered"), projectId: ProjectId.make("project-1"), title: "Steered work", latestTurn: { turnId: secondTurnId, state: "running", requestedAt: "2026-04-01T00:00:14.000Z", startedAt: "2026-04-01T00:00:14.000Z", completedAt: null, assistantMessageId: MessageId.make("assistant-next"), }, messages: [ { id: MessageId.make("user-1"), role: "user", text: "Do it once more.", turnId: null, streaming: false, createdAt: "2026-04-01T00:00:00.000Z", updatedAt: "2026-04-01T00:00:00.000Z", }, { id: MessageId.make("assistant-commentary"), role: "assistant", text: "Kicking off call 1.", turnId: firstTurnId, streaming: false, createdAt: "2026-04-01T00:00:09.000Z", updatedAt: "2026-04-01T00:00:09.000Z", }, { id: MessageId.make("user-2"), role: "user", text: "Actually do 15.", turnId: null, streaming: false, createdAt: "2026-04-01T00:00:14.000Z", updatedAt: "2026-04-01T00:00:14.000Z", }, { id: MessageId.make("assistant-next"), role: "assistant", text: "One down - adjusting.", turnId: secondTurnId, streaming: true, createdAt: "2026-04-01T00:00:17.000Z", updatedAt: "2026-04-01T00:00:17.000Z", }, ], activities: [ makeActivity({ id: EventId.make("work-1"), kind: "tool.completed", tone: "tool", summary: "Ran command", createdAt: "2026-04-01T00:00:12.000Z", turnId: firstTurnId, payload: { title: "Ran command", itemType: "command_execution", status: "completed", }, }), ], }); const feed = buildThreadFeed(thread); const collapsed = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set()); expect(collapsed.find((entry) => entry.type === "turn-fold")).toMatchObject({ turnId: firstTurnId, label: "Worked for 12s", }); }); it("keeps an active turn expanded and classifies error-shaped tool output", () => { const turnId = TurnId.make("turn-running"); const thread = makeThread({ id: ThreadId.make("thread-4"), projectId: ProjectId.make("project-1"), title: "Running work", latestTurn: { turnId, state: "running", requestedAt: "2026-04-01T00:00:00.000Z", startedAt: "2026-04-01T00:00:01.000Z", completedAt: null, assistantMessageId: null, }, activities: [ makeActivity({ id: EventId.make("tool-failed"), kind: "tool.completed", tone: "tool", summary: "Run command", createdAt: "2026-04-01T00:00:05.000Z", turnId, payload: { title: "Run command", itemType: "command_execution", detail: "zsh: command not found: nope", status: "completed", }, }), ], }); const feed = buildThreadFeed(thread); expect(deriveThreadFeedPresentation(feed, thread.latestTurn, new Set())).toEqual(feed); expect(feed[0]).toMatchObject({ type: "activity-group", activities: [{ status: "failure" }], }); }); it("appends active work as a normal timeline row", () => { const startedAt = "2026-04-01T00:00:01.000Z"; const presented = deriveThreadFeedPresentation([], null, new Set(), new Set(), startedAt); expect(presented).toEqual([ { type: "working", id: "working-indicator-row", createdAt: startedAt, }, ]); expect(deriveThreadFeedPresentation(presented, null, new Set())).toEqual([]); }); it("models work-log overflow as list rows", () => { const activity = ( id: string, createdAt: string, status: ThreadFeedActivity["status"] = "success", ): ThreadFeedActivity => ({ id, createdAt, turnId: null, summary: `Tool ${id}`, detail: null, fullDetail: null, copyText: id, icon: "command", toolLike: true, status, }); const feed: ThreadFeedEntry[] = [ { type: "activity-group", id: "work-group-1", createdAt: "2026-04-01T00:00:01.000Z", turnId: null, activities: [ activity("activity-1", "2026-04-01T00:00:01.000Z"), activity("activity-neutral", "2026-04-01T00:00:02.000Z", "neutral"), activity("activity-2", "2026-04-01T00:00:03.000Z"), activity("activity-3", "2026-04-01T00:00:04.000Z"), ], }, ]; const collapsed = deriveThreadFeedPresentation(feed, null, new Set()); expect(collapsed.map((entry) => entry.id)).toEqual(["activity-3", "work-toggle:work-group-1"]); expect(collapsed[1]).toMatchObject({ type: "work-toggle", groupId: "work-group-1", hiddenCount: 2, expanded: false, }); const expanded = deriveThreadFeedPresentation(feed, null, new Set(), new Set(["work-group-1"])); expect(expanded.map((entry) => entry.id)).toEqual([ "activity-1", "activity-2", "activity-3", "work-toggle:work-group-1", ]); expect(expanded.at(-1)).toMatchObject({ type: "work-toggle", expanded: true, }); });});
import { describe, expect, it } from "vite-plus/test";
import {
EventId,
MessageId,
ProjectId,
ProviderInstanceId,
ThreadId,
TurnId,
type OrchestrationThread,
type OrchestrationThreadActivity,
} from "@t3tools/contracts";
import {
buildThreadFeed,
deriveThreadFeedPresentation,
type ThreadFeedActivity,
type ThreadFeedEntry,
} from "./threadActivity";
function makeActivity(
input: Partial<OrchestrationThreadActivity> &
Pick<OrchestrationThreadActivity, "id" | "kind" | "summary" | "createdAt">,
): OrchestrationThreadActivity {
return {
tone: "info",
payload: {},
turnId: null,
...input,
};
}
function makeThread(
input: Partial<OrchestrationThread> & Pick<OrchestrationThread, "id" | "projectId" | "title">,
): OrchestrationThread {
return {
modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5.4" },
runtimeMode: "full-access",
interactionMode: "default",
branch: null,
worktreePath: null,
latestTurn: null,
createdAt: "2026-04-01T00:00:00.000Z",
updatedAt: "2026-04-01T00:00:00.000Z",
archivedAt: null,
deletedAt: null,
messages: [],
proposedPlans: [],
activities: [],
checkpoints: [],
session: null,
...input,
settledOverride: input.settledOverride ?? null,
settledAt: input.settledAt ?? null,
};
}
describe("buildThreadFeed", () => {
it("keeps historic work entries attributed to their turns", () => {
const thread = makeThread({
id: ThreadId.make("thread-1"),
projectId: ProjectId.make("project-1"),
title: "Runtime warning thread",
latestTurn: {
turnId: TurnId.make("turn-latest"),
state: "running",
requestedAt: "2026-04-01T00:00:00.000Z",
startedAt: "2026-04-01T00:00:01.000Z",
completedAt: null,
assistantMessageId: null,
},
activities: [
makeActivity({
id: EventId.make("activity-old"),
kind: "runtime.warning",
summary: "Runtime warning",
createdAt: "2026-04-01T00:00:02.000Z",
turnId: TurnId.make("turn-old"),
payload: {
message: "Old warning",
},
}),
makeActivity({
id: EventId.make("activity-latest"),
kind: "runtime.warning",
summary: "Runtime warning",
createdAt: "2026-04-01T00:00:03.000Z",
turnId: TurnId.make("turn-latest"),
payload: {
message: "Latest warning",
},
}),
],
});
const feed = buildThreadFeed(thread);
expect(feed).toMatchObject([
{
type: "activity-group",
turnId: "turn-old",
activities: [{ id: "activity-old", turnId: "turn-old" }],
},
{
type: "activity-group",
turnId: "turn-latest",
activities: [{ id: "activity-latest", turnId: "turn-latest" }],
},
]);
});
it("collapses matching tool lifecycle rows like desktop", () => {
const thread = makeThread({
id: ThreadId.make("thread-2"),
projectId: ProjectId.make("project-1"),
title: "Collapsed tools",
latestTurn: {
turnId: TurnId.make("turn-1"),
state: "completed",
requestedAt: "2026-04-01T00:00:00.000Z",
startedAt: "2026-04-01T00:00:01.000Z",
completedAt: "2026-04-01T00:00:03.000Z",
assistantMessageId: null,
},
activities: [
makeActivity({
id: EventId.make("tool-updated"),
kind: "tool.updated",
tone: "tool",
summary: "Run tests",
createdAt: "2026-04-01T00:00:01.000Z",
turnId: TurnId.make("turn-1"),
payload: {
title: "Run tests",
itemType: "command_execution",
detail: "/bin/zsh -lc 'bun run test'",
},
}),
makeActivity({
id: EventId.make("tool-completed"),
kind: "tool.completed",
tone: "tool",
summary: "Run tests completed",
createdAt: "2026-04-01T00:00:02.000Z",
turnId: TurnId.make("turn-1"),
payload: {
title: "Run tests",
itemType: "command_execution",
detail: "/bin/zsh -lc 'bun run test'",
},
}),
],
});
const feed = buildThreadFeed(thread);
const group = feed[0];
expect(group).toMatchObject({
type: "activity-group",
});
if (!group || group.type !== "activity-group") {
return;
}
expect(group.activities).toEqual([
{
id: "tool-completed",
createdAt: "2026-04-01T00:00:02.000Z",
turnId: "turn-1",
summary: "Run tests",
detail: "bun run test",
fullDetail: "/bin/zsh -lc 'bun run test'",
copyText: "Run tests\nbun run test\n/bin/zsh -lc 'bun run test'",
icon: "command",
toolLike: true,
status: "success",
},
]);
});
it("keeps MCP inputs available to expanded mobile work rows", () => {
const turnId = TurnId.make("turn-mcp");
const thread = makeThread({
id: ThreadId.make("thread-mcp"),
projectId: ProjectId.make("project-1"),
title: "Expandable MCP call",
latestTurn: {
turnId,
state: "completed",
requestedAt: "2026-04-01T00:00:00.000Z",
startedAt: "2026-04-01T00:00:01.000Z",
completedAt: "2026-04-01T00:00:03.000Z",
assistantMessageId: null,
},
activities: [
makeActivity({
id: EventId.make("mcp-completed"),
kind: "tool.completed",
tone: "tool",
summary: "Call repository tool",
createdAt: "2026-04-01T00:00:02.000Z",
turnId,
payload: {
title: "Call repository tool",
itemType: "mcp_tool_call",
detail: "repository.search",
status: "completed",
data: {
item: {
server: "repository",
tool: "search",
arguments: { query: "work log" },
},
},
},
}),
],
});
const group = buildThreadFeed(thread)[0];
expect(group).toMatchObject({ type: "activity-group" });
if (!group || group.type !== "activity-group") {
return;
}
expect(group.activities[0]?.icon).toBe("wrench");
expect(group.activities[0]?.fullDetail).toContain('"query": "work log"');
expect(group.activities[0]?.fullDetail).toContain("repository.search");
});
it("folds settled turn work while leaving the terminal answer visible", () => {
const turnId = TurnId.make("turn-1");
const thread = makeThread({
id: ThreadId.make("thread-3"),
projectId: ProjectId.make("project-1"),
title: "Folded work",
latestTurn: {
turnId,
state: "completed",
requestedAt: "2026-04-01T00:00:00.000Z",
startedAt: "2026-04-01T00:00:01.000Z",
completedAt: "2026-04-01T00:00:18.000Z",
assistantMessageId: MessageId.make("assistant-final"),
},
messages: [
{
id: MessageId.make("assistant-commentary"),
role: "assistant",
text: "I am checking.",
turnId,
streaming: false,
createdAt: "2026-04-01T00:00:02.000Z",
updatedAt: "2026-04-01T00:00:03.000Z",
},
{
id: MessageId.make("assistant-final"),
role: "assistant",
text: "Done.",
turnId,
streaming: false,
createdAt: "2026-04-01T00:00:17.000Z",
updatedAt: "2026-04-01T00:00:18.000Z",
},
],
activities: [
makeActivity({
id: EventId.make("tool-completed"),
kind: "tool.completed",
tone: "tool",
summary: "Read files",
createdAt: "2026-04-01T00:00:05.000Z",
turnId,
payload: {
title: "Read files",
itemType: "file_read",
status: "completed",
},
}),
],
});
const feed = buildThreadFeed(thread);
const collapsed = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set());
expect(collapsed.map((entry) => entry.id)).toEqual(["turn-fold:turn-1", "assistant-final"]);
expect(collapsed[0]).toMatchObject({
type: "turn-fold",
label: "Worked for 17s",
expanded: false,
});
const expanded = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set([turnId]));
expect(expanded.map((entry) => entry.id)).toEqual([
"turn-fold:turn-1",
"assistant-commentary",
"tool-completed",
"assistant-final",
]);
});
it("measures a steer-superseded turn from its user boundary through trailing work", () => {
const firstTurnId = TurnId.make("turn-1");
const secondTurnId = TurnId.make("turn-2");
const thread = makeThread({
id: ThreadId.make("thread-steered"),
projectId: ProjectId.make("project-1"),
title: "Steered work",
latestTurn: {
turnId: secondTurnId,
state: "running",
requestedAt: "2026-04-01T00:00:14.000Z",
startedAt: "2026-04-01T00:00:14.000Z",
completedAt: null,
assistantMessageId: MessageId.make("assistant-next"),
},
messages: [
{
id: MessageId.make("user-1"),
role: "user",
text: "Do it once more.",
turnId: null,
streaming: false,
createdAt: "2026-04-01T00:00:00.000Z",
updatedAt: "2026-04-01T00:00:00.000Z",
},
{
id: MessageId.make("assistant-commentary"),
role: "assistant",
text: "Kicking off call 1.",
turnId: firstTurnId,
streaming: false,
createdAt: "2026-04-01T00:00:09.000Z",
updatedAt: "2026-04-01T00:00:09.000Z",
},
{
id: MessageId.make("user-2"),
role: "user",
text: "Actually do 15.",
turnId: null,
streaming: false,
createdAt: "2026-04-01T00:00:14.000Z",
updatedAt: "2026-04-01T00:00:14.000Z",
},
{
id: MessageId.make("assistant-next"),
role: "assistant",
text: "One down - adjusting.",
turnId: secondTurnId,
streaming: true,
createdAt: "2026-04-01T00:00:17.000Z",
updatedAt: "2026-04-01T00:00:17.000Z",
},
],
activities: [
makeActivity({
id: EventId.make("work-1"),
kind: "tool.completed",
tone: "tool",
summary: "Ran command",
createdAt: "2026-04-01T00:00:12.000Z",
turnId: firstTurnId,
payload: {
title: "Ran command",
itemType: "command_execution",
status: "completed",
},
}),
],
});
const feed = buildThreadFeed(thread);
const collapsed = deriveThreadFeedPresentation(feed, thread.latestTurn, new Set());
expect(collapsed.find((entry) => entry.type === "turn-fold")).toMatchObject({
turnId: firstTurnId,
label: "Worked for 12s",
});
});
it("keeps an active turn expanded and classifies error-shaped tool output", () => {
const turnId = TurnId.make("turn-running");
const thread = makeThread({
id: ThreadId.make("thread-4"),
projectId: ProjectId.make("project-1"),
title: "Running work",
latestTurn: {
turnId,
state: "running",
requestedAt: "2026-04-01T00:00:00.000Z",
startedAt: "2026-04-01T00:00:01.000Z",
completedAt: null,
assistantMessageId: null,
},
activities: [
makeActivity({
id: EventId.make("tool-failed"),
kind: "tool.completed",
tone: "tool",
summary: "Run command",
createdAt: "2026-04-01T00:00:05.000Z",
turnId,
payload: {
title: "Run command",
itemType: "command_execution",
detail: "zsh: command not found: nope",
status: "completed",
},
}),
],
});
const feed = buildThreadFeed(thread);
expect(deriveThreadFeedPresentation(feed, thread.latestTurn, new Set())).toEqual(feed);
expect(feed[0]).toMatchObject({
type: "activity-group",
activities: [{ status: "failure" }],
});
});
it("appends active work as a normal timeline row", () => {
const startedAt = "2026-04-01T00:00:01.000Z";
const presented = deriveThreadFeedPresentation([], null, new Set(), new Set(), startedAt);
expect(presented).toEqual([
{
type: "working",
id: "working-indicator-row",
createdAt: startedAt,
},
]);
expect(deriveThreadFeedPresentation(presented, null, new Set())).toEqual([]);
});
it("models work-log overflow as list rows", () => {
const activity = (
id: string,
createdAt: string,
status: ThreadFeedActivity["status"] = "success",
): ThreadFeedActivity => ({
id,
createdAt,
turnId: null,
summary: `Tool ${id}`,
detail: null,
fullDetail: null,
copyText: id,
icon: "command",
toolLike: true,
status,
});
const feed: ThreadFeedEntry[] = [
{
type: "activity-group",
id: "work-group-1",
createdAt: "2026-04-01T00:00:01.000Z",
turnId: null,
activities: [
activity("activity-1", "2026-04-01T00:00:01.000Z"),
activity("activity-neutral", "2026-04-01T00:00:02.000Z", "neutral"),
activity("activity-2", "2026-04-01T00:00:03.000Z"),
activity("activity-3", "2026-04-01T00:00:04.000Z"),
],
},
];
const collapsed = deriveThreadFeedPresentation(feed, null, new Set());
expect(collapsed.map((entry) => entry.id)).toEqual(["activity-3", "work-toggle:work-group-1"]);
expect(collapsed[1]).toMatchObject({
type: "work-toggle",
groupId: "work-group-1",
hiddenCount: 2,
expanded: false,
});
const expanded = deriveThreadFeedPresentation(feed, null, new Set(), new Set(["work-group-1"]));
expect(expanded.map((entry) => entry.id)).toEqual([
"activity-1",
"activity-2",
"activity-3",
"work-toggle:work-group-1",
]);
expect(expanded.at(-1)).toMatchObject({
type: "work-toggle",
expanded: true,
});
});
});