Files
paseo/packages/cli/tests/11-agent-wait.test.ts
Mohamed Boudra 0110302b6f fix(daemon): keep lifecycle operations on the selected instance (#4575)
* fix(daemon): keep lifecycle operations on the selected instance

Restart reconstructed launch inputs and address fallback could redirect a home-selected shutdown to another daemon. Let supervisors publish bound endpoints, retain their worker restart contract, and share captured local lifecycle ownership between CLI and Desktop.

* test(daemon): verify bounded desktop readiness and cancellable artifacts

* test(cli): verify reload target hints and durable offline pairing

* test(daemon): align lifecycle fixtures with ownership and targeting

* fix(daemon): preserve reachability when status details time out

Provider discovery can outlast a status request after authentication succeeds. Keep local connection facts separate from unavailable details, while explicit remote queries retain their error outcome.

Migrate CLI and packaged Desktop fixtures to persistent managed configuration and explicit targets. Isolate generic Git observation from forge discovery and reuse disposable CLI homes on Windows.

* test(daemon): observe restart through the worker status RPC

The bounded CLI status observation may omit worker details while an authenticated connection remains healthy. Exercise the app-style restart through its full RPC and retain the replacement observation, with a real slow provider probe covering the distinction.
2026-09-11 08:33:22 +02:00

186 lines
7.5 KiB
TypeScript

#!/usr/bin/env npx tsx
/**
* Phase 11: Wait Command Tests
*
* Tests the wait command - waiting for an agent to become idle (top-level command).
* Since daemon may not be running, we test both:
* - Help and argument parsing
* - Graceful error handling when daemon not running
* - All flags are accepted
*
* Tests:
* - wait --help shows options
* - wait requires id argument
* - wait handles daemon not running
* - wait --timeout flag is accepted
* - wait --host flag is accepted
* - agent shows wait in subcommands
*/
import assert from "node:assert";
import { getAvailablePort } from "./helpers/network.ts";
import { $ } from "zx";
import { mkdtemp, rm } from "fs/promises";
import { tmpdir } from "os";
import { join } from "path";
$.verbose = false;
console.log("=== Wait Command Tests ===\n");
// Allocate an unused endpoint for connection-error and argument-validation checks.
const port = await getAvailablePort();
const paseoHome = await mkdtemp(join(tmpdir(), "paseo-test-home-"));
try {
// Test 1: wait --help shows options
{
console.log("Test 1: wait --help shows options");
const result = await $`npx paseo wait --help`.nothrow();
assert.strictEqual(result.exitCode, 0, "wait --help should exit 0");
assert(result.stdout.includes("--host"), "help should mention --host option");
assert(result.stdout.includes("--timeout"), "help should mention --timeout option");
assert(result.stdout.includes("<id>"), "help should mention id argument");
console.log(" help should mention --host option");
console.log(" help should mention --timeout option");
console.log(" help should mention <id> argument");
console.log("wait --help shows options\n");
}
// Test 2: wait requires id argument
{
console.log("Test 2: wait requires id argument");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo --host localhost:${port} wait`.nothrow();
assert.notStrictEqual(result.exitCode, 0, "should fail without id");
const output = result.stdout + result.stderr;
// Commander should complain about missing argument
const hasMissingArg =
output.toLowerCase().includes("missing") ||
output.toLowerCase().includes("required") ||
output.toLowerCase().includes("argument");
assert(hasMissingArg, "error should mention missing argument");
console.log("wait requires id argument\n");
}
// Test 3: wait handles daemon not running
{
console.log("Test 3: wait handles daemon not running");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo --host localhost:${port} wait abc123`.nothrow();
// Should fail because daemon not running
assert.notStrictEqual(result.exitCode, 0, "should fail when daemon not running");
const output = result.stdout + result.stderr;
const hasError =
output.toLowerCase().includes("daemon") ||
output.toLowerCase().includes("connect") ||
output.toLowerCase().includes("cannot");
assert(hasError, "error message should mention connection issue");
console.log("wait handles daemon not running\n");
}
// Test 4: wait --timeout flag is accepted
{
console.log("Test 4: wait --timeout flag is accepted");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo wait --timeout 30 --host localhost:${port} abc123`.nothrow();
const output = result.stdout + result.stderr;
assert(!output.includes("unknown option"), "should accept --timeout flag");
assert(!output.includes("error: option"), "should not have option parsing error");
console.log("wait --timeout flag is accepted\n");
}
// Test 5: wait --host flag is accepted
{
console.log("Test 5: wait --host flag is accepted");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo wait --host localhost:${port} abc123`.nothrow();
const output = result.stdout + result.stderr;
assert(!output.includes("unknown option"), "should accept --host flag");
assert(!output.includes("error: option"), "should not have option parsing error");
console.log("wait --host flag is accepted\n");
}
// Test 6: -q (quiet) flag is accepted with wait
{
console.log("Test 6: -q (quiet) flag is accepted with wait");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo --host localhost:${port} -q wait abc123`.nothrow();
const output = result.stdout + result.stderr;
assert(!output.includes("unknown option"), "should accept -q flag");
assert(!output.includes("error: option"), "should not have option parsing error");
console.log("-q (quiet) flag is accepted with wait\n");
}
// Test 7: --json flag is accepted with wait
{
console.log("Test 7: --json flag is accepted with wait");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo --host localhost:${port} wait abc123 --json`.nothrow();
const output = result.stdout + result.stderr;
assert(!output.includes("unknown option"), "should accept --json flag");
assert(!output.includes("error: option"), "should not have option parsing error");
console.log("--json flag is accepted with wait\n");
}
// Test 8: --format yaml flag is accepted with wait
{
console.log("Test 8: --format yaml flag is accepted with wait");
const result =
await $`PASEO_HOME=${paseoHome} npx paseo --host localhost:${port} --format yaml wait abc123`.nothrow();
const output = result.stdout + result.stderr;
assert(!output.includes("unknown option"), "should accept --format yaml flag");
assert(!output.includes("error: option"), "should not have option parsing error");
console.log("--format yaml flag is accepted with wait\n");
}
// Test 9: paseo --help shows wait command
{
console.log("Test 9: paseo --help shows wait command");
const result = await $`npx paseo --help`.nothrow();
assert.strictEqual(result.exitCode, 0, "paseo --help should exit 0");
assert(result.stdout.includes("wait"), "help should mention wait command");
console.log("paseo --help shows wait command\n");
}
// Test 10: wait command description is helpful
{
console.log("Test 10: wait command description is helpful");
const result = await $`npx paseo wait --help`.nothrow();
assert.strictEqual(result.exitCode, 0, "wait --help should exit 0");
const hasDescription =
result.stdout.toLowerCase().includes("wait") || result.stdout.toLowerCase().includes("idle");
assert(hasDescription, "help should describe what wait does");
console.log("wait command description is helpful\n");
}
// Test 11: ID prefix syntax is mentioned in help
{
console.log("Test 11: wait command mentions ID");
const result = await $`npx paseo wait --help`.nothrow();
assert.strictEqual(result.exitCode, 0, "wait --help should exit 0");
const hasIdMention =
result.stdout.toLowerCase().includes("id") || result.stdout.toLowerCase().includes("prefix");
assert(hasIdMention, "help should mention ID or prefix");
console.log("wait command mentions ID\n");
}
// Test 12: timeout option documents no default limit
{
console.log("Test 12: timeout option documents no default limit");
const result = await $`npx paseo wait --help`.nothrow();
assert.strictEqual(result.exitCode, 0, "wait --help should exit 0");
assert(
result.stdout.toLowerCase().includes("default: no limit"),
"help should mention timeout default is no limit",
);
console.log("timeout option documents no default limit\n");
}
} finally {
// Clean up temp directory
await rm(paseoHome, { recursive: true, force: true });
}
console.log("=== All wait tests passed ===");