Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/coding-agent/test/interactive-mode-status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function createInitialRenderHarness(): { ctx: InteractiveModeContext; helpers: U
},
toolOutputExpanded: false,
hideThinkingBlock: false,
resetAssistantTextPresentation: vi.fn(),
} as unknown as InteractiveModeContext;
helpers = new UiHelpers(ctx);
return { ctx, helpers };
Expand Down Expand Up @@ -108,6 +109,7 @@ describe("InteractiveMode.showStatus", () => {
helpers.renderInitialMessages(undefined, { preserveExistingChat: true });

expect(renderContainer(ctx.chatContainer)).toContain("startup notification probe");
expect(ctx.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
});

test("preserves optimistic user signatures when rebuilding transcript state", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* streaming must render its header/output/exit status continuously and land in
* the chat transcript on completion, exactly like the idle path.
*/
import { beforeAll, describe, expect, it } from "bun:test";
import { beforeAll, describe, expect, it, vi } from "bun:test";
import { BashExecutionComponent } from "@gajae-code/coding-agent/modes/components/bash-execution";
import type { EvalExecutionComponent } from "@gajae-code/coding-agent/modes/components/eval-execution";
import { CommandController } from "@gajae-code/coding-agent/modes/controllers/command-controller";
Expand Down Expand Up @@ -115,6 +115,7 @@ function createHarness(options: { isStreaming: boolean }): Harness {
statusLine: { invalidate: () => {}, setSessionStartTime: () => {} },
updateEditorTopBorder: () => {},
updateEditorBorderColor: () => {},
resetAssistantTextPresentation: vi.fn(),
resetIrcSidebarSession: () => {},
resetObserverRegistry: () => {},
reloadTodos: async () => {},
Expand Down Expand Up @@ -258,6 +259,7 @@ describe("deferred shell command display", () => {
harness.rebuiltTranscriptRows.push("earlier command");
new UiHelpers(harness.ctx).renderInitialMessages();

expect(harness.ctx.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
expect(harness.ctx.pendingBashComponents).toEqual([liveComponent]);
expect(harness.pendingMessagesContainer.children).toEqual([liveComponent]);
expect(harness.pendingMessagesContainer.render(80).join("\n")).toContain("$ printf parked");
Expand Down Expand Up @@ -336,6 +338,7 @@ describe("deferred shell command parentage after the transcript is cleared", ()
expect(harness.pendingMessagesContainer.children).toContain(parked);

expect(await controller.handleClearCommand()).toBe(true);
expect(harness.ctx.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
expect(harness.pendingMessagesContainer.hasLiveChild(parked)).toBe(false);
const chatChildrenAfterClear = harness.chatContainer.children.length;

Expand All @@ -356,6 +359,7 @@ describe("deferred shell command parentage after the transcript is cleared", ()

const parked = harness.ctx.pendingBashComponents[0];
await controller.handleContextClearCommand();
expect(harness.ctx.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
expect(harness.pendingMessagesContainer.hasLiveChild(parked)).toBe(false);
const chatChildrenAfterClear = harness.chatContainer.children.length;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function createContext(success: boolean): InteractiveModeContext {
statusLine: { invalidate: vi.fn(), setSessionStartTime: vi.fn() },
updateEditorTopBorder: vi.fn(),
updateEditorBorderColor: vi.fn(),
resetAssistantTextPresentation: vi.fn(),
ui: { requestRender: vi.fn(), resetViewportAnchorIntent: vi.fn() },
chatContainer: { clear: vi.fn(), addChild: vi.fn() },
pendingMessagesContainer: { clear: vi.fn() },
Expand Down Expand Up @@ -45,6 +46,7 @@ describe("Issue #2261 CommandController fail-closed session replacement", () =>
expect(context.loadingAnimation?.stop).not.toHaveBeenCalled();
expect(context.statusContainer.clear).not.toHaveBeenCalled();
expect(context.resetIrcSidebarSession).not.toHaveBeenCalled();
expect(context.resetAssistantTextPresentation).not.toHaveBeenCalled();
expect(context.chatContainer.clear).not.toHaveBeenCalled();
expect(context.pendingMessagesContainer.clear).not.toHaveBeenCalled();
expect(context.compactionQueuedMessages).toEqual([{ text: "old", mode: "followUp" }]);
Expand All @@ -63,6 +65,7 @@ describe("Issue #2261 CommandController fail-closed session replacement", () =>
expect(stopLoading).toHaveBeenCalledTimes(1);
expect(context.statusContainer.clear).toHaveBeenCalledTimes(1);
expect(context.resetIrcSidebarSession).toHaveBeenCalledTimes(1);
expect(context.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
expect(context.chatContainer.clear).toHaveBeenCalledTimes(1);
expect(context.pendingMessagesContainer.clear).toHaveBeenCalledTimes(1);
expect(context.compactionQueuedMessages).toEqual([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function createContext(options: {
streamingComponent: undefined,
streamingMessage: undefined,
pendingTools: { clear: vi.fn() },
resetAssistantTextPresentation: vi.fn(),
loadingAnimation: undefined,
stopLoadingAnimation: vi.fn(),
syncActivityIndicator: vi.fn(),
Expand Down Expand Up @@ -110,6 +111,7 @@ describe("SelectorController resume model choice", () => {
restoreBackground: false,
});
expect(ctx.syncActivityIndicator).toHaveBeenCalledTimes(1);
expect(ctx.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
});

it("prompts and switches when resumeModelBehavior is ask and models differ", async () => {
Expand Down Expand Up @@ -166,6 +168,7 @@ describe("SelectorController resume model choice", () => {
expect(ctx.retryLoader).toBe(typedRetryLoader);
expect(ctx.retryCountdownTimer).toBe(retryTimer);
expect(retryLoader.stop).not.toHaveBeenCalled();
expect(ctx.resetAssistantTextPresentation).not.toHaveBeenCalled();
clearInterval(retryTimer);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ function createContext(currentSessionFile: string): {
calls.push(`showStatus:${message}`);
}),
showError: vi.fn(),
resetAssistantTextPresentation: vi.fn(() => {
calls.push("resetAssistantTextPresentation");
}),
resetIrcSidebarSession: vi.fn(() => {
calls.push("resetIrcSidebarSession");
}),
Expand Down Expand Up @@ -425,6 +428,7 @@ describe("SelectorController session deletion", () => {
"ui.requestRender",
"session.newSession",
"resetIrcSidebarSession",
"resetAssistantTextPresentation",
"loadingAnimation.stop",
"statusContainer.clear",
"pendingMessagesContainer.clear",
Expand Down Expand Up @@ -501,6 +505,7 @@ describe("SelectorController session deletion", () => {
expect(calls).toEqual([
"session.newSession",
"resetIrcSidebarSession",
"resetAssistantTextPresentation",
"loadingAnimation.stop",
"statusContainer.clear",
"pendingMessagesContainer.clear",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ function makeCtx(sessionManager?: Pick<SessionManager, "buildSessionContext" | "
ctx: InteractiveModeContext;
buildSessionContextSpy: Mock<() => SessionContext>;
renderSessionContextSpy: Mock<(...args: unknown[]) => void>;
resetAssistantTextPresentationSpy: Mock<() => void>;
} {
const buildSessionContextSpy = vi.fn(() => makeEmptyContext());
const renderSessionContextSpy = vi.fn();
const resetAssistantTextPresentationSpy = vi.fn();

const sm = sessionManager ?? {
buildSessionContext: buildSessionContextSpy,
Expand All @@ -65,20 +67,22 @@ function makeCtx(sessionManager?: Pick<SessionManager, "buildSessionContext" | "
pendingPythonComponents: [],
sessionManager: sm,
renderSessionContext: renderSessionContextSpy,
resetAssistantTextPresentation: resetAssistantTextPresentationSpy,
showStatus: vi.fn(),
ui: { requestRender: vi.fn() },
} as unknown as InteractiveModeContext;

return { ctx, buildSessionContextSpy, renderSessionContextSpy };
return { ctx, buildSessionContextSpy, renderSessionContextSpy, resetAssistantTextPresentationSpy };
}

// ─── Part 1: Isolated renderInitialMessages behaviour ─────────────────────────

describe("UiHelpers.renderInitialMessages — isolated", () => {
it("calls sessionManager.buildSessionContext when no prebuilt context is given", () => {
const { ctx, buildSessionContextSpy } = makeCtx();
const { ctx, buildSessionContextSpy, resetAssistantTextPresentationSpy } = makeCtx();
new UiHelpers(ctx).renderInitialMessages();
expect(buildSessionContextSpy).toHaveBeenCalledTimes(1);
expect(resetAssistantTextPresentationSpy).toHaveBeenCalledTimes(1);
});

it("does NOT call sessionManager.buildSessionContext when a prebuilt context is provided", () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/coding-agent/test/resume-progress-lease.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ describe("resume progress lease", () => {
getCwd: () => "/tmp",
},
resetIrcSidebarSession: vi.fn(),
resetAssistantTextPresentation: vi.fn(),
updateEditorBorderColor: vi.fn(),
rebuildInitialMessages: vi.fn(),
reloadTodos: vi.fn(async () => undefined),
Expand All @@ -71,6 +72,7 @@ describe("resume progress lease", () => {
await resume;
expect(statusContainer.children).toHaveLength(0);
expect(context.showStatus).toHaveBeenCalledWith("Resumed session");
expect(context.resetAssistantTextPresentation).toHaveBeenCalledTimes(1);
expect(session.switchSession).toHaveBeenCalledWith("/tmp/target.jsonl", expect.any(Object));

ui.stop();
Expand Down Expand Up @@ -115,6 +117,7 @@ describe("resume progress lease", () => {
getCwd: () => "/tmp",
},
resetIrcSidebarSession: vi.fn(),
resetAssistantTextPresentation: vi.fn(),
updateEditorBorderColor: vi.fn(),
rebuildInitialMessages: vi.fn(),
reloadTodos: vi.fn(async () => undefined),
Expand Down
Loading