From 0a79dba7f501a4daef47482ef0729d3e5b471b0d Mon Sep 17 00:00:00 2001 From: can1357 Date: Tue, 14 Jul 2026 23:39:15 +0200 Subject: [PATCH] test(coding-agent): adapted plugin-install and loader-accent tests to landed behavior changes - plugin-install-validation mocks now answer the bun pm cache probe that refreshBunGitCache issues before bun update on git re-installs. - working-accent tests render the loader before asserting accent computation counts: colorizers run lazily at render time since the loader layout cache landed. --- .../test/core/js-executor.test.ts | 8 +++---- .../interactive-mode-working-accent.test.ts | 16 +++++++++----- .../test/plugin-install-validation.test.ts | 22 +++++++++++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/packages/coding-agent/test/core/js-executor.test.ts b/packages/coding-agent/test/core/js-executor.test.ts index f0886a915..1655c8573 100644 --- a/packages/coding-agent/test/core/js-executor.test.ts +++ b/packages/coding-agent/test/core/js-executor.test.ts @@ -339,8 +339,8 @@ describe("executeJs", () => { it("delegates URI reads through the read tool with positional slicing", async () => { const execute = vi.fn(async (_toolCallId: string, args: unknown): Promise => { - const record = args as { path: string }; - return { content: [{ type: "text", text: record.path.endsWith(":1-1400") ? "wide" : "limited" }] }; + const record = args as { path: string; selector?: string }; + return { content: [{ type: "text", text: record.selector === "1-1400" ? "wide" : "limited" }] }; }); const toolSession: ToolSession = { ...session, @@ -366,13 +366,13 @@ describe("executeJs", () => { expect(execute).toHaveBeenNthCalledWith( 1, expect.stringMatching(/^js-read-/), - { path: "artifact://15:raw:1-1400", [INTENT_FIELD]: "js prelude" }, + { path: "artifact://15:raw", selector: "1-1400", [INTENT_FIELD]: "js prelude" }, expect.any(AbortSignal), ); expect(execute).toHaveBeenNthCalledWith( 2, expect.stringMatching(/^js-read-/), - { path: "artifact://15:raw:1-2", [INTENT_FIELD]: "js prelude" }, + { path: "artifact://15:raw", selector: "1-2", [INTENT_FIELD]: "js prelude" }, expect.any(AbortSignal), ); }); diff --git a/packages/coding-agent/test/interactive-mode-working-accent.test.ts b/packages/coding-agent/test/interactive-mode-working-accent.test.ts index 4b02fee03..6739ba776 100644 --- a/packages/coding-agent/test/interactive-mode-working-accent.test.ts +++ b/packages/coding-agent/test/interactive-mode-working-accent.test.ts @@ -96,11 +96,15 @@ describe("InteractiveMode working-message session accent cache", () => { const getHex = vi.spyOn(sessionColor, "getSessionAccentHex"); const getAnsi = vi.spyOn(sessionColor, "getSessionAccentAnsi"); + // Colorizers run lazily at render time (loader layout cache); the accent + // computation is observable only after a render. startStableLoader(mode); + renderLoader(mode); expect(getHex).toHaveBeenCalledTimes(1); expect(getAnsi).toHaveBeenCalledTimes(2); mode.loadingAnimation?.setMessage("Still working"); + renderLoader(mode); expect(getHex).toHaveBeenCalledTimes(1); expect(getAnsi).toHaveBeenCalledTimes(2); }); @@ -130,13 +134,13 @@ describe("InteractiveMode working-message session accent cache", () => { const getHex = vi.spyOn(sessionColor, "getSessionAccentHex"); startStableLoader(mode); - expect(getHex).toHaveBeenCalledTimes(1); expect(renderLoader(mode)).toContain(initialAnsi); + expect(getHex).toHaveBeenCalledTimes(1); await sessionManager.setSessionName(renamedName, "user"); mode.loadingAnimation?.setMessage("Renamed session"); - expect(getHex).toHaveBeenCalledTimes(2); expect(renderLoader(mode)).toContain(renamedAnsi); + expect(getHex).toHaveBeenCalledTimes(2); }); it("keys cached accents by theme accent-surface luminance", async () => { @@ -147,6 +151,7 @@ describe("InteractiveMode working-message session accent cache", () => { try { startStableLoader(mode); + renderLoader(mode); expect(getHex).toHaveBeenCalledTimes(1); expect(getHex.mock.calls[0]).toEqual([sessionName, theme.getMajorThemeColorHexes(), undefined]); @@ -154,6 +159,7 @@ describe("InteractiveMode working-message session accent cache", () => { const restoreLight = shadowAccentSurfaceLuminance(0.72); try { mode.loadingAnimation?.setMessage("Light theme"); + renderLoader(mode); expect(getHex).toHaveBeenCalledTimes(2); expect(getHex.mock.calls[1]).toEqual([sessionName, theme.getMajorThemeColorHexes(), 0.72]); } finally { @@ -179,17 +185,17 @@ describe("InteractiveMode working-message session accent cache", () => { const getHex = vi.spyOn(sessionColor, "getSessionAccentHex"); startStableLoader(mode); - expect(getHex).toHaveBeenCalledTimes(1); expect(renderLoader(mode)).toContain(accentAnsi); + expect(getHex).toHaveBeenCalledTimes(1); settings.set("statusLine.sessionAccent", false); mode.loadingAnimation?.setMessage("Accent disabled"); - expect(getHex).toHaveBeenCalledTimes(1); expect(renderLoader(mode)).not.toContain(accentAnsi); + expect(getHex).toHaveBeenCalledTimes(1); settings.set("statusLine.sessionAccent", true); mode.loadingAnimation?.setMessage("Accent enabled"); - expect(getHex).toHaveBeenCalledTimes(2); expect(renderLoader(mode)).toContain(accentAnsi); + expect(getHex).toHaveBeenCalledTimes(2); }); }); diff --git a/packages/coding-agent/test/plugin-install-validation.test.ts b/packages/coding-agent/test/plugin-install-validation.test.ts index 08b59356e..1621954ce 100644 --- a/packages/coding-agent/test/plugin-install-validation.test.ts +++ b/packages/coding-agent/test/plugin-install-validation.test.ts @@ -15,6 +15,25 @@ function emptyStream(): ReadableStream { return body; } +/** + * Mock response for the `bun pm cache` probe the manager runs before a git + * re-install (refreshBunGitCache). Points at a nonexistent directory so the + * cache refresh is a no-op. + */ +function pmCacheSubprocess(tmpRoot: string, cmd: string[]): Subprocess { + expect(cmd).toEqual(["bun", "pm", "cache"]); + const body = new Response(path.join(tmpRoot, "no-such-bun-cache")).body; + if (!body) { + throw new Error("Failed to create response stream"); + } + return { + pid: 3, + stdout: body, + stderr: emptyStream(), + exited: Promise.resolve(0), + } as Subprocess; +} + interface PluginFixture { readonly version: string; readonly source: string; @@ -255,6 +274,7 @@ describe("PluginManager.install load validation", () => { exited: prepare.then(() => 0), } as Subprocess; } + if (cmd[1] === "pm") return pmCacheSubprocess(tmpRoot, cmd); // The manager follows a git re-install with `bun update ` to refresh // the lockfile pin (#3063). The mock treats it as a no-op exit-0 — the // on-disk state already reflects the v2 install above. @@ -390,6 +410,7 @@ describe("PluginManager.install load validation", () => { exited: prepare.then(() => 0), } as Subprocess; } + if (cmd[1] === "pm") return pmCacheSubprocess(tmpRoot, cmd); expect(cmd).toEqual(["bun", "update", "git-plugin"]); const prepare = (async () => { // bun update re-resolves the ref and rewrites the lockfile pin @@ -503,6 +524,7 @@ describe("PluginManager.install load validation", () => { exited: prepare.then(() => 0), } as Subprocess; } + if (cmd[1] === "pm") return pmCacheSubprocess(tmpRoot, cmd); expect(cmd).toEqual(["bun", "update", "git-plugin"]); const prepare = (async () => { await Bun.write(bunLockPath, '# bun.lock\n"git-plugin": "github:org/plugin#sha-update"\n');