Skip to content

Commit 328eac0

Browse files
authored
refactor: handle issues #147 and #149 (complete helper migration + unit test for ensurePatchloomReadyOrNotify) (#151)
refactor+test: complete migration to ensurePatchloomReadyOrNotify for configureMcp/setup/verifyMcp (#147); improve testability and add unit test for helper (#149) - Updated remaining commands using the early-ready-notify pattern. - Moved vscode import inside notify branches (only when UI needed). - Added ensure test for success path (error paths require VSCode env). - Re-ran compile + unit tests: all green. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
1 parent a20da2b commit 328eac0

5 files changed

Lines changed: 35 additions & 57 deletions

File tree

src/binary/patchloom.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,16 @@ export function patchloomNeedsUpgrade(status: PatchloomStatus): boolean {
160160
*
161161
* This removes duplicated ready-check + notify logic across commands.
162162
*/
163-
export async function ensurePatchloomReadyOrNotify(contextSuffix = ""): Promise<string | null> {
164-
const status = await resolvePatchloomStatus();
165-
const vscode = await import("vscode");
163+
export async function ensurePatchloomReadyOrNotify(
164+
contextSuffix = "",
165+
testInputs?: PatchloomStatusInputs
166+
): Promise<string | null> {
167+
const status = testInputs
168+
? await resolvePatchloomStatusWithInputs(testInputs)
169+
: await resolvePatchloomStatus();
166170

167171
if (!status.ready || !status.binaryPath) {
172+
const vscode = await import("vscode");
168173
const choice = await vscode.window.showWarningMessage(
169174
`${status.message}${contextSuffix ? `\n\n${contextSuffix}` : ""}`,
170175
"Open Settings"
@@ -176,6 +181,7 @@ export async function ensurePatchloomReadyOrNotify(contextSuffix = ""): Promise<
176181
}
177182

178183
if (patchloomNeedsUpgrade(status)) {
184+
const vscode = await import("vscode");
179185
const choice = await vscode.window.showWarningMessage(
180186
`${status.compatibilityMessage}${contextSuffix ? `\n\n${contextSuffix}` : ""}`,
181187
"Open Releases"

src/commands/configureMcp.ts

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,14 @@
11
import * as fs from "node:fs/promises";
22
import * as path from "node:path";
33
import * as vscode from "vscode";
4-
import { patchloomNeedsUpgrade, resolvePatchloomStatus } from "../binary/patchloom.js";
4+
import { ensurePatchloomReadyOrNotify } from "../binary/patchloom.js";
55
import { configureMcpTargets, inspectMcpTargets } from "../mcp/config.js";
66
import { activeWorkspaceFolder, describeWorkspaceEnvironment } from "../workspace/readiness.js";
77
import { refreshStatusBar } from "../status/statusBar.js";
88

99
export async function configureMcp(): Promise<void> {
10-
const status = await resolvePatchloomStatus();
11-
if (!status.ready) {
12-
const choice = await vscode.window.showWarningMessage(
13-
`${status.message}\n\nPatchloom needs a working binary before MCP setup can continue.`,
14-
"Open Settings"
15-
);
16-
if (choice === "Open Settings") {
17-
await vscode.commands.executeCommand("patchloom.openPatchloomSettings");
18-
}
19-
return;
20-
}
21-
22-
if (patchloomNeedsUpgrade(status)) {
23-
const choice = await vscode.window.showWarningMessage(
24-
`${status.compatibilityMessage}\n\nUpgrade Patchloom before MCP setup can continue.`,
25-
"Open Releases"
26-
);
27-
if (choice === "Open Releases") {
28-
await vscode.commands.executeCommand("patchloom.openPatchloomReleases");
29-
}
10+
const binaryPath = await ensurePatchloomReadyOrNotify("Patchloom needs a working binary before MCP setup can continue.");
11+
if (!binaryPath) {
3012
return;
3113
}
3214

@@ -66,7 +48,7 @@ export async function configureMcp(): Promise<void> {
6648
workspaceFolderPath,
6749
includeKinds: selectedKinds,
6850
includeUserTarget: environment.supportsUserMcpConfig,
69-
patchloomPathSetting: status.binaryPath,
51+
patchloomPathSetting: binaryPath,
7052
readFile: async (filePath) => {
7153
try {
7254
return await fs.readFile(filePath, "utf8");

src/commands/setupWorkspace.ts

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,17 @@
11
import * as vscode from "vscode";
2-
import { PATCHLOOM_DOCS_URL, PATCHLOOM_RELEASES_URL, patchloomNeedsUpgrade, resolvePatchloomStatus } from "../binary/patchloom.js";
2+
import { ensurePatchloomReadyOrNotify, PATCHLOOM_DOCS_URL, PATCHLOOM_RELEASES_URL } from "../binary/patchloom.js";
33
import { describeWorkspaceEnvironment, inspectWorkspaceReadiness } from "../workspace/readiness.js";
44

55
export async function setupWorkspace(): Promise<void> {
6-
const status = await resolvePatchloomStatus();
7-
if (!status.ready) {
8-
const choice = await vscode.window.showWarningMessage(
9-
`${status.message}\n\nPatchloom needs a working binary before workspace setup can continue.`,
10-
"Open Settings"
11-
);
12-
if (choice === "Open Settings") {
13-
await vscode.commands.executeCommand("patchloom.openPatchloomSettings");
14-
}
6+
const binaryPath = await ensurePatchloomReadyOrNotify("Patchloom needs a working binary before workspace setup can continue.");
7+
if (!binaryPath) {
158
return;
169
}
1710

1811
const readiness = await inspectWorkspaceReadiness({
1912
promptIfMany: true,
2013
placeHolder: "Select the workspace folder to inspect for Patchloom setup"
2114
});
22-
if (patchloomNeedsUpgrade(status)) {
23-
const choice = await vscode.window.showWarningMessage(
24-
`${status.compatibilityMessage}\n\nUpgrade Patchloom before workspace setup can continue.`,
25-
"Open Releases"
26-
);
27-
if (choice === "Open Releases") {
28-
await vscode.commands.executeCommand("patchloom.openPatchloomReleases");
29-
}
30-
return;
31-
}
3215

3316
if (!readiness.hasWorkspace) {
3417
await vscode.window.showWarningMessage("Open a workspace folder before running Patchloom: Setup Workspace.");

src/commands/verifyMcp.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { spawn } from "node:child_process";
2-
import { patchloomNeedsUpgrade, resolvePatchloomStatus } from "../binary/patchloom.js";
2+
import { ensurePatchloomReadyOrNotify } from "../binary/patchloom.js";
33
import { getPatchloomLog } from "../logging/outputChannel.js";
44

55
export interface VerifyMcpInputs {
@@ -16,16 +16,8 @@ export interface VerifyMcpResult {
1616

1717
export async function verifyMcp(): Promise<void> {
1818
const vscode = await import("vscode");
19-
const status = await resolvePatchloomStatus();
20-
if (!status.ready || !status.binaryPath) {
21-
await vscode.window.showWarningMessage(status.message);
22-
return;
23-
}
24-
25-
if (patchloomNeedsUpgrade(status)) {
26-
await vscode.window.showWarningMessage(
27-
`${status.compatibilityMessage}\n\nUpgrade Patchloom before verifying the MCP server.`
28-
);
19+
const binaryPath = await ensurePatchloomReadyOrNotify("Upgrade Patchloom before verifying the MCP server.");
20+
if (!binaryPath) {
2921
return;
3022
}
3123

@@ -37,7 +29,7 @@ export async function verifyMcp(): Promise<void> {
3729
},
3830
async (progress) => {
3931
progress.report({ message: "Verifying MCP server..." });
40-
return verifyMcpServer({ binaryPath: status.binaryPath! });
32+
return verifyMcpServer({ binaryPath });
4133
}
4234
);
4335

test/unit/binary.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
MINIMUM_SUPPORTED_PATCHLOOM_VERSION,
1414
patchloomNeedsUpgrade,
1515
parsePatchloomVersion,
16+
ensurePatchloomReadyOrNotify,
1617
resolvePatchloomStatusWithInputs
1718
} from "../../src/binary/patchloom.js";
1819
import {
@@ -127,6 +128,20 @@ test("resolvePatchloomStatusWithInputs exposes compatibility diagnostics", async
127128
assert.match(status.compatibilityMessage ?? "", /older than the minimum supported version/i);
128129
});
129130

131+
test("ensurePatchloomReadyOrNotify returns path for ready supported status (test inputs)", async () => {
132+
const path = await ensurePatchloomReadyOrNotify("", {
133+
configuredPath: "/good/patchloom",
134+
canExecute: async () => true,
135+
getVersion: async () => "patchloom 0.2.0"
136+
});
137+
assert.equal(path, "/good/patchloom");
138+
});
139+
140+
// Note: error paths (not-ready, upgrade) execute vscode.window.show* which is
141+
// not unit-testable in pure node (would require full VS Code test env or mocks).
142+
// They are exercised via command integration and manual. The core logic delegates
143+
// to resolve+needsUpgrade which are unit tested.
144+
130145
test("defaultWorkspaceFolderIndex prefers active folders and only auto-selects single roots", () => {
131146
assert.equal(defaultWorkspaceFolderIndex(3, 2), 2);
132147
assert.equal(defaultWorkspaceFolderIndex(1, undefined), 0);

0 commit comments

Comments
 (0)