fix(cli): parse localDaemon field in daemon supervisor test assertions

The daemon status JSON uses `localDaemon` not `status`, so the polling
condition was always null and timed out after 120s on CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2026-04-11 05:43:41 +00:00
parent 31b0c7e668
commit 04a3f4bf5b
4 changed files with 56 additions and 36 deletions

View File

@@ -69,7 +69,7 @@ function readProcessCommand(pid: number): string | null {
}
type DaemonStatus = {
status: string | null;
localDaemon: string | null;
pid: number | null;
};
@@ -77,19 +77,19 @@ async function readDaemonStatus(paseoHome: string): Promise<DaemonStatus> {
const result =
await $`PASEO_HOME=${paseoHome} PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${testEnv.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${testEnv.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${testEnv.PASEO_VOICE_MODE_ENABLED} npx paseo daemon status --home ${paseoHome} --json`.nothrow();
if (result.exitCode !== 0) {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
try {
const parsed = JSON.parse(result.stdout) as { status?: unknown; pid?: unknown };
const status = typeof parsed.status === "string" ? parsed.status : null;
const parsed = JSON.parse(result.stdout) as { localDaemon?: unknown; pid?: unknown };
const localDaemon = typeof parsed.localDaemon === "string" ? parsed.localDaemon : null;
const pid =
typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0
? parsed.pid
: null;
return { status, pid };
return { localDaemon, pid };
} catch {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
}
@@ -145,7 +145,11 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "running" && status.pid !== null && isProcessRunning(status.pid);
return (
status.localDaemon === "running" &&
status.pid !== null &&
isProcessRunning(status.pid)
);
},
120000,
"daemon did not become running in time",
@@ -153,7 +157,11 @@ try {
const statusBeforeStop = await readDaemonStatus(paseoHome);
const daemonPid = statusBeforeStop.pid;
assert.strictEqual(statusBeforeStop.status, "running", "daemon should be running before stop");
assert.strictEqual(
statusBeforeStop.localDaemon,
"running",
"daemon should be running before stop",
);
assert(daemonPid !== null, "daemon pid should exist once daemon starts");
assert(isProcessRunning(daemonPid), "daemon process should be running");
const pidLockBeforeStop = await readPidLockState(paseoHome);
@@ -176,7 +184,7 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "stopped";
return status.localDaemon === "stopped";
},
15000,
"daemon status did not transition to stopped after stop",
@@ -202,7 +210,7 @@ try {
const statusAfterStop = await readDaemonStatus(paseoHome);
assert.strictEqual(
statusAfterStop.status,
statusAfterStop.localDaemon,
"stopped",
"daemon should remain stopped after stop command",
);

View File

@@ -62,7 +62,7 @@ function signalProcessGroup(pid: number, signal: NodeJS.Signals): boolean {
}
type DaemonStatus = {
status: string | null;
localDaemon: string | null;
pid: number | null;
};
@@ -70,19 +70,19 @@ async function readDaemonStatus(paseoHome: string): Promise<DaemonStatus> {
const result =
await $`PASEO_HOME=${paseoHome} PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${testEnv.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${testEnv.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${testEnv.PASEO_VOICE_MODE_ENABLED} npx paseo daemon status --home ${paseoHome} --json`.nothrow();
if (result.exitCode !== 0) {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
try {
const parsed = JSON.parse(result.stdout) as { status?: unknown; pid?: unknown };
const status = typeof parsed.status === "string" ? parsed.status : null;
const parsed = JSON.parse(result.stdout) as { localDaemon?: unknown; pid?: unknown };
const localDaemon = typeof parsed.localDaemon === "string" ? parsed.localDaemon : null;
const pid =
typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0
? parsed.pid
: null;
return { status, pid };
return { localDaemon, pid };
} catch {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
}
@@ -157,7 +157,11 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "running" && status.pid !== null && isProcessRunning(status.pid);
return (
status.localDaemon === "running" &&
status.pid !== null &&
isProcessRunning(status.pid)
);
},
120000,
"daemon did not become running in time",
@@ -183,7 +187,7 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "stopped";
return status.localDaemon === "stopped";
},
15000,
"daemon status did not transition to stopped after SIGINT",

View File

@@ -70,7 +70,7 @@ function readWorkerPid(supervisorPid: number): number | null {
}
type DaemonStatus = {
status: string | null;
localDaemon: string | null;
pid: number | null;
};
@@ -78,19 +78,19 @@ async function readDaemonStatus(paseoHome: string): Promise<DaemonStatus> {
const result =
await $`PASEO_HOME=${paseoHome} PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${testEnv.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${testEnv.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${testEnv.PASEO_VOICE_MODE_ENABLED} npx paseo daemon status --home ${paseoHome} --json`.nothrow();
if (result.exitCode !== 0) {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
try {
const parsed = JSON.parse(result.stdout) as { status?: unknown; pid?: unknown };
const status = typeof parsed.status === "string" ? parsed.status : null;
const parsed = JSON.parse(result.stdout) as { localDaemon?: unknown; pid?: unknown };
const localDaemon = typeof parsed.localDaemon === "string" ? parsed.localDaemon : null;
const pid =
typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0
? parsed.pid
: null;
return { status, pid };
return { localDaemon, pid };
} catch {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
}
@@ -147,7 +147,11 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "running" && status.pid !== null && isProcessRunning(status.pid);
return (
status.localDaemon === "running" &&
status.pid !== null &&
isProcessRunning(status.pid)
);
},
120000,
"daemon did not become running in time",
@@ -156,7 +160,7 @@ try {
const statusBeforeRestart = await readDaemonStatus(paseoHome);
const supervisorPid = statusBeforeRestart.pid;
assert.strictEqual(
statusBeforeRestart.status,
statusBeforeRestart.localDaemon,
"running",
"daemon should be running before restart",
);
@@ -207,7 +211,7 @@ try {
const statusAfterRestart = await readDaemonStatus(paseoHome);
assert.strictEqual(
statusAfterRestart.status,
statusAfterRestart.localDaemon,
"running",
"daemon should stay running after restart",
);

View File

@@ -41,7 +41,7 @@ function isProcessRunning(pid: number): boolean {
}
type DaemonStatus = {
status: string | null;
localDaemon: string | null;
pid: number | null;
};
@@ -49,19 +49,19 @@ async function readDaemonStatus(paseoHome: string): Promise<DaemonStatus> {
const result =
await $`PASEO_HOME=${paseoHome} PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${testEnv.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${testEnv.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${testEnv.PASEO_VOICE_MODE_ENABLED} npx paseo daemon status --home ${paseoHome} --json`.nothrow();
if (result.exitCode !== 0) {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
try {
const parsed = JSON.parse(result.stdout) as { status?: unknown; pid?: unknown };
const status = typeof parsed.status === "string" ? parsed.status : null;
const parsed = JSON.parse(result.stdout) as { localDaemon?: unknown; pid?: unknown };
const localDaemon = typeof parsed.localDaemon === "string" ? parsed.localDaemon : null;
const pid =
typeof parsed.pid === "number" && Number.isInteger(parsed.pid) && parsed.pid > 0
? parsed.pid
: null;
return { status, pid };
return { localDaemon, pid };
} catch {
return { status: null, pid: null };
return { localDaemon: null, pid: null };
}
}
@@ -146,7 +146,11 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "running" && status.pid !== null && isProcessRunning(status.pid);
return (
status.localDaemon === "running" &&
status.pid !== null &&
isProcessRunning(status.pid)
);
},
120000,
"daemon did not become running in time",
@@ -154,7 +158,7 @@ try {
const statusBeforeRestart = await readDaemonStatus(paseoHome);
assert.strictEqual(
statusBeforeRestart.status,
statusBeforeRestart.localDaemon,
"running",
"daemon should be running before restart",
);
@@ -191,7 +195,7 @@ try {
await waitFor(
async () => {
const status = await readDaemonStatus(paseoHome);
return status.status === "stopped";
return status.localDaemon === "stopped";
},
15000,
"daemon status did not transition to stopped after unsupervised restart request",