test(app): triage desktop test files — delete 16-mock component slop, tighten attachment store (#721)
* test(app): triage desktop test files — delete 16-mock component slop, tighten attachment store assertion Removes desktop-updates-section.test.tsx (16 internal mocks, JSDOM, toHaveBeenCalledWith chains on component renders). Tightens desktop-attachment-store.test.ts: toHaveBeenCalled() → toHaveBeenCalledWith(attachment). * refactor(app): extract daemon management toggle coordinator with unit tests Fills the coverage gap left by deleting desktop-updates-section.test.tsx. Extracts executeDaemonManagementToggle from useDaemonManagementToggle — pure async coordinator with injected deps (no vi.mock). Unit tests verify the three key invariants: settings persist before stop, stop is skipped when not desktop-managed, and start/stop are invoked on enable/disable.
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { executeDaemonManagementToggle } from "./daemon-management-toggle";
|
||||
import type { DesktopDaemonStatus } from "./desktop-daemon";
|
||||
|
||||
const runningManagedStatus: DesktopDaemonStatus = {
|
||||
serverId: "desktop",
|
||||
status: "running",
|
||||
listen: null,
|
||||
hostname: null,
|
||||
pid: 123,
|
||||
home: "/tmp/paseo",
|
||||
version: "1.0.0",
|
||||
desktopManaged: true,
|
||||
error: null,
|
||||
};
|
||||
|
||||
const stoppedStatus: DesktopDaemonStatus = { ...runningManagedStatus, status: "stopped" };
|
||||
|
||||
function makeDeps(overrides?: {
|
||||
confirm?: () => Promise<boolean>;
|
||||
persistSettings?: (next: { manageBuiltInDaemon: boolean }) => Promise<void>;
|
||||
startDaemon?: () => Promise<DesktopDaemonStatus>;
|
||||
stopDaemon?: () => Promise<DesktopDaemonStatus>;
|
||||
}) {
|
||||
const calls: string[] = [];
|
||||
return {
|
||||
deps: {
|
||||
confirm: overrides?.confirm ?? (() => Promise.resolve(true)),
|
||||
persistSettings:
|
||||
overrides?.persistSettings ??
|
||||
(async () => {
|
||||
calls.push("persist");
|
||||
}),
|
||||
startDaemon:
|
||||
overrides?.startDaemon ??
|
||||
(async () => {
|
||||
calls.push("start");
|
||||
return { ...runningManagedStatus, status: "running" as const };
|
||||
}),
|
||||
stopDaemon:
|
||||
overrides?.stopDaemon ??
|
||||
(async () => {
|
||||
calls.push("stop");
|
||||
return stoppedStatus;
|
||||
}),
|
||||
},
|
||||
calls,
|
||||
};
|
||||
}
|
||||
|
||||
describe("executeDaemonManagementToggle", () => {
|
||||
describe("enable path (currentlyManaging: false)", () => {
|
||||
it("persists the new setting then starts the daemon", async () => {
|
||||
const { deps, calls } = makeDeps();
|
||||
|
||||
const result = await executeDaemonManagementToggle(false, null, deps);
|
||||
|
||||
expect(result).toEqual({ kind: "enabled", newStatus: runningManagedStatus });
|
||||
expect(calls).toEqual(["persist", "start"]);
|
||||
});
|
||||
|
||||
it("persists manageBuiltInDaemon: true", async () => {
|
||||
let persisted: { manageBuiltInDaemon: boolean } | null = null;
|
||||
const { deps } = makeDeps({
|
||||
persistSettings: async (next) => {
|
||||
persisted = next;
|
||||
},
|
||||
});
|
||||
|
||||
await executeDaemonManagementToggle(false, null, deps);
|
||||
|
||||
expect(persisted).toEqual({ manageBuiltInDaemon: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("disable path (currentlyManaging: true)", () => {
|
||||
it("returns cancelled without changing settings when confirmation is rejected", async () => {
|
||||
const persistedSettings: unknown[] = [];
|
||||
const { deps } = makeDeps({
|
||||
confirm: () => Promise.resolve(false),
|
||||
persistSettings: async (next) => {
|
||||
persistedSettings.push(next);
|
||||
},
|
||||
});
|
||||
|
||||
const result = await executeDaemonManagementToggle(true, runningManagedStatus, deps);
|
||||
|
||||
expect(result).toEqual({ kind: "cancelled" });
|
||||
expect(persistedSettings).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("persists settings BEFORE stopping the daemon", async () => {
|
||||
const callOrder: string[] = [];
|
||||
const { deps } = makeDeps({
|
||||
persistSettings: async () => {
|
||||
callOrder.push("persist");
|
||||
},
|
||||
stopDaemon: async () => {
|
||||
callOrder.push("stop");
|
||||
return stoppedStatus;
|
||||
},
|
||||
});
|
||||
|
||||
await executeDaemonManagementToggle(true, runningManagedStatus, deps);
|
||||
|
||||
expect(callOrder).toEqual(["persist", "stop"]);
|
||||
});
|
||||
|
||||
it("persists manageBuiltInDaemon: false when disabling", async () => {
|
||||
let persisted: { manageBuiltInDaemon: boolean } | null = null;
|
||||
const { deps } = makeDeps({
|
||||
persistSettings: async (next) => {
|
||||
persisted = next;
|
||||
},
|
||||
});
|
||||
|
||||
await executeDaemonManagementToggle(true, runningManagedStatus, deps);
|
||||
|
||||
expect(persisted).toEqual({ manageBuiltInDaemon: false });
|
||||
});
|
||||
|
||||
it("stops the daemon when it is running and desktop-managed", async () => {
|
||||
const { deps, calls } = makeDeps();
|
||||
|
||||
const result = await executeDaemonManagementToggle(true, runningManagedStatus, deps);
|
||||
|
||||
expect(calls).toContain("stop");
|
||||
expect(result).toEqual({ kind: "disabled", newStatus: stoppedStatus });
|
||||
});
|
||||
|
||||
it("skips stop when daemon is running but not desktop-managed", async () => {
|
||||
const { deps, calls } = makeDeps();
|
||||
const manuallyManagedStatus = { ...runningManagedStatus, desktopManaged: false };
|
||||
|
||||
const result = await executeDaemonManagementToggle(true, manuallyManagedStatus, deps);
|
||||
|
||||
expect(calls).not.toContain("stop");
|
||||
expect(result).toEqual({ kind: "disabled", newStatus: null });
|
||||
});
|
||||
|
||||
it("skips stop when daemon is stopped (regardless of desktopManaged)", async () => {
|
||||
const { deps, calls } = makeDeps();
|
||||
|
||||
const result = await executeDaemonManagementToggle(true, stoppedStatus, deps);
|
||||
|
||||
expect(calls).not.toContain("stop");
|
||||
expect(result).toEqual({ kind: "disabled", newStatus: null });
|
||||
});
|
||||
|
||||
it("skips stop when daemonStatus is null", async () => {
|
||||
const { deps, calls } = makeDeps();
|
||||
|
||||
const result = await executeDaemonManagementToggle(true, null, deps);
|
||||
|
||||
expect(calls).not.toContain("stop");
|
||||
expect(result).toEqual({ kind: "disabled", newStatus: null });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { DesktopDaemonStatus } from "./desktop-daemon";
|
||||
|
||||
export interface DaemonManagementToggleDeps {
|
||||
confirm: () => Promise<boolean>;
|
||||
persistSettings: (next: { manageBuiltInDaemon: boolean }) => Promise<void>;
|
||||
startDaemon: () => Promise<DesktopDaemonStatus>;
|
||||
stopDaemon: () => Promise<DesktopDaemonStatus>;
|
||||
}
|
||||
|
||||
export type DaemonManagementToggleResult =
|
||||
| { kind: "cancelled" }
|
||||
| { kind: "enabled"; newStatus: DesktopDaemonStatus }
|
||||
| { kind: "disabled"; newStatus: DesktopDaemonStatus | null };
|
||||
|
||||
export async function executeDaemonManagementToggle(
|
||||
currentlyManaging: boolean,
|
||||
daemonStatus: Pick<DesktopDaemonStatus, "status" | "desktopManaged"> | null,
|
||||
deps: DaemonManagementToggleDeps,
|
||||
): Promise<DaemonManagementToggleResult> {
|
||||
if (!currentlyManaging) {
|
||||
await deps.persistSettings({ manageBuiltInDaemon: true });
|
||||
const newStatus = await deps.startDaemon();
|
||||
return { kind: "enabled", newStatus };
|
||||
}
|
||||
|
||||
const confirmed = await deps.confirm();
|
||||
if (!confirmed) {
|
||||
return { kind: "cancelled" };
|
||||
}
|
||||
|
||||
// Settings must persist before the daemon is stopped so the persisted
|
||||
// state reflects what was actually applied if the stop fails.
|
||||
await deps.persistSettings({ manageBuiltInDaemon: false });
|
||||
|
||||
if (daemonStatus?.status === "running" && daemonStatus.desktopManaged) {
|
||||
const newStatus = await deps.stopDaemon();
|
||||
return { kind: "disabled", newStatus };
|
||||
}
|
||||
|
||||
return { kind: "disabled", newStatus: null };
|
||||
}
|
||||
Reference in New Issue
Block a user