Delete message-input.test.tsx, left-sidebar.test.tsx, agent-stream-view.test.tsx, and agent-panel.test.tsx — all heavy vi.mock + JSDOM + toHaveBeenCalledWith slop. Coverage preserved by extracting the testable derivations: - agent-stream-view-data.ts: isSameAssistantBlockGroup, getAssistantBlockSpacing, resolveInlineWorkingIndicatorItemId — 14 pure unit tests, zero mocks - message-input-state.ts: computeCanStartDictation (dictation readiness gate) — 7 pure unit tests, zero mocks Remaining behaviors confirmed covered by existing E2E: - left-sidebar subscription-while-hidden → sidebar-workspace.spec.ts - agent-panel render isolation + archived agent store hygiene → archive-tab.spec.ts - message-input attachment menu / submit icon → workspace-setup-streaming.spec.ts
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
import type { StreamItem } from "@/types/stream";
|
|
|
|
export function isSameAssistantBlockGroup(params: {
|
|
item: StreamItem | null | undefined;
|
|
other: StreamItem | null | undefined;
|
|
}): boolean {
|
|
return (
|
|
params.item?.kind === "assistant_message" &&
|
|
params.other?.kind === "assistant_message" &&
|
|
params.item.blockGroupId !== undefined &&
|
|
params.item.blockGroupId === params.other.blockGroupId
|
|
);
|
|
}
|
|
|
|
export function getAssistantBlockSpacing(params: {
|
|
item: StreamItem;
|
|
aboveItem: StreamItem | null | undefined;
|
|
belowItem: StreamItem | null | undefined;
|
|
}): "default" | "compactTop" | "compactBottom" | "compactBoth" {
|
|
if (params.item.kind !== "assistant_message") {
|
|
return "default";
|
|
}
|
|
const compactTop = isSameAssistantBlockGroup({ item: params.item, other: params.aboveItem });
|
|
const compactBottom = isSameAssistantBlockGroup({ item: params.item, other: params.belowItem });
|
|
if (compactTop && compactBottom) return "compactBoth";
|
|
if (compactTop) return "compactTop";
|
|
if (compactBottom) return "compactBottom";
|
|
return "default";
|
|
}
|
|
|
|
export interface NeighborResolver {
|
|
getNeighborItem(
|
|
items: StreamItem[],
|
|
index: number,
|
|
relation: "above" | "below",
|
|
): StreamItem | undefined;
|
|
}
|
|
|
|
// null → auxiliary working indicator; non-null → inline footer on that block.
|
|
export function resolveInlineWorkingIndicatorItemId(
|
|
status: string,
|
|
liveHeadItems: StreamItem[],
|
|
strategy: NeighborResolver,
|
|
): string | null {
|
|
if (status !== "running") return null;
|
|
const footerItem = liveHeadItems.find((item, index, items) => {
|
|
if (item.kind !== "assistant_message") return false;
|
|
return strategy.getNeighborItem(items, index, "below") === undefined;
|
|
});
|
|
return footerItem?.id ?? null;
|
|
}
|