Switch to double quotes and reformat codebase with Biome
This commit is contained in:
+65
-67
@@ -9,57 +9,57 @@
|
||||
* 5. Cleanup: Kill daemon and remove temp dirs after each test
|
||||
*/
|
||||
|
||||
import { $, ProcessPromise, sleep } from 'zx'
|
||||
import { mkdtemp, rm } from 'fs/promises'
|
||||
import { tmpdir } from 'os'
|
||||
import { join } from 'path'
|
||||
import { $, ProcessPromise, sleep } from "zx";
|
||||
import { mkdtemp, rm } from "fs/promises";
|
||||
import { tmpdir } from "os";
|
||||
import { join } from "path";
|
||||
|
||||
const TEST_ENV_DEFAULTS = {
|
||||
PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD: process.env.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD ?? '0',
|
||||
PASEO_DICTATION_ENABLED: process.env.PASEO_DICTATION_ENABLED ?? '0',
|
||||
PASEO_VOICE_MODE_ENABLED: process.env.PASEO_VOICE_MODE_ENABLED ?? '0',
|
||||
}
|
||||
PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD: process.env.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD ?? "0",
|
||||
PASEO_DICTATION_ENABLED: process.env.PASEO_DICTATION_ENABLED ?? "0",
|
||||
PASEO_VOICE_MODE_ENABLED: process.env.PASEO_VOICE_MODE_ENABLED ?? "0",
|
||||
};
|
||||
|
||||
function killPidTree(pid: number, signal: NodeJS.Signals): void {
|
||||
if (!Number.isInteger(pid) || pid <= 0) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
if (process.platform !== "win32") {
|
||||
try {
|
||||
process.kill(-pid, signal)
|
||||
return
|
||||
process.kill(-pid, signal);
|
||||
return;
|
||||
} catch (error) {
|
||||
const code = (error as NodeJS.ErrnoException).code
|
||||
if (code === 'ESRCH') {
|
||||
return
|
||||
const code = (error as NodeJS.ErrnoException).code;
|
||||
if (code === "ESRCH") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
process.kill(pid, signal)
|
||||
process.kill(pid, signal);
|
||||
} catch (error) {
|
||||
const code = (error as NodeJS.ErrnoException).code
|
||||
if (code !== 'ESRCH') {
|
||||
throw error
|
||||
const code = (error as NodeJS.ErrnoException).code;
|
||||
if (code !== "ESRCH") {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestContext {
|
||||
/** Random port for test daemon (never 6767) */
|
||||
port: number
|
||||
port: number;
|
||||
/** Temp directory for PASEO_HOME */
|
||||
paseoHome: string
|
||||
paseoHome: string;
|
||||
/** Temp directory for agent working directory */
|
||||
workDir: string
|
||||
workDir: string;
|
||||
/** Running daemon process */
|
||||
daemon: ProcessPromise | null
|
||||
daemon: ProcessPromise | null;
|
||||
/** Run a paseo CLI command against the test daemon */
|
||||
paseo: (args: string[]) => ProcessPromise
|
||||
paseo: (args: string[]) => ProcessPromise;
|
||||
/** Clean up all resources */
|
||||
cleanup: () => Promise<void>
|
||||
cleanup: () => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,16 +67,16 @@ export interface TestContext {
|
||||
* NEVER uses 6767 (user's running daemon)
|
||||
*/
|
||||
export function getRandomPort(): number {
|
||||
return 10000 + Math.floor(Math.random() * 50000)
|
||||
return 10000 + Math.floor(Math.random() * 50000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create isolated temp directories for testing
|
||||
*/
|
||||
export async function createTempDirs(): Promise<{ paseoHome: string; workDir: string }> {
|
||||
const paseoHome = await mkdtemp(join(tmpdir(), 'paseo-test-home-'))
|
||||
const workDir = await mkdtemp(join(tmpdir(), 'paseo-test-work-'))
|
||||
return { paseoHome, workDir }
|
||||
const paseoHome = await mkdtemp(join(tmpdir(), "paseo-test-home-"));
|
||||
const workDir = await mkdtemp(join(tmpdir(), "paseo-test-work-"));
|
||||
return { paseoHome, workDir };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,58 +84,56 @@ export async function createTempDirs(): Promise<{ paseoHome: string; workDir: st
|
||||
* Uses `paseo agent ls` which connects via WebSocket
|
||||
*/
|
||||
export async function waitForDaemon(port: number, timeout = 30000): Promise<void> {
|
||||
const start = Date.now()
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < timeout) {
|
||||
try {
|
||||
const result = await $`PASEO_HOST=localhost:${port} paseo agent ls`.nothrow()
|
||||
if (result.exitCode === 0) return
|
||||
const result = await $`PASEO_HOST=localhost:${port} paseo agent ls`.nothrow();
|
||||
if (result.exitCode === 0) return;
|
||||
} catch {
|
||||
// Connection failed, keep trying
|
||||
}
|
||||
await sleep(100)
|
||||
await sleep(100);
|
||||
}
|
||||
throw new Error(`Daemon failed to start on port ${port} within ${timeout}ms`)
|
||||
throw new Error(`Daemon failed to start on port ${port} within ${timeout}ms`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an isolated test daemon
|
||||
*/
|
||||
export async function startDaemon(
|
||||
port: number,
|
||||
paseoHome: string
|
||||
): Promise<ProcessPromise> {
|
||||
$.verbose = false
|
||||
const daemon = $`PASEO_HOME=${paseoHome} PASEO_LISTEN=127.0.0.1:${port} PASEO_RELAY_ENABLED=false PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${TEST_ENV_DEFAULTS.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${TEST_ENV_DEFAULTS.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${TEST_ENV_DEFAULTS.PASEO_VOICE_MODE_ENABLED} CI=true paseo daemon start --foreground`.nothrow()
|
||||
return daemon
|
||||
export async function startDaemon(port: number, paseoHome: string): Promise<ProcessPromise> {
|
||||
$.verbose = false;
|
||||
const daemon =
|
||||
$`PASEO_HOME=${paseoHome} PASEO_LISTEN=127.0.0.1:${port} PASEO_RELAY_ENABLED=false PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${TEST_ENV_DEFAULTS.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${TEST_ENV_DEFAULTS.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${TEST_ENV_DEFAULTS.PASEO_VOICE_MODE_ENABLED} CI=true paseo daemon start --foreground`.nothrow();
|
||||
return daemon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full test context with daemon, temp dirs, and helpers
|
||||
*/
|
||||
export async function createTestContext(): Promise<TestContext> {
|
||||
const port = getRandomPort()
|
||||
const { paseoHome, workDir } = await createTempDirs()
|
||||
const port = getRandomPort();
|
||||
const { paseoHome, workDir } = await createTempDirs();
|
||||
|
||||
// Helper to run CLI commands against test daemon
|
||||
const paseo = (args: string[]): ProcessPromise => {
|
||||
$.verbose = false
|
||||
return $`PASEO_HOST=localhost:${port} PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${TEST_ENV_DEFAULTS.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${TEST_ENV_DEFAULTS.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${TEST_ENV_DEFAULTS.PASEO_VOICE_MODE_ENABLED} paseo ${args}`.nothrow()
|
||||
}
|
||||
$.verbose = false;
|
||||
return $`PASEO_HOST=localhost:${port} PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD=${TEST_ENV_DEFAULTS.PASEO_LOCAL_SPEECH_AUTO_DOWNLOAD} PASEO_DICTATION_ENABLED=${TEST_ENV_DEFAULTS.PASEO_DICTATION_ENABLED} PASEO_VOICE_MODE_ENABLED=${TEST_ENV_DEFAULTS.PASEO_VOICE_MODE_ENABLED} paseo ${args}`.nothrow();
|
||||
};
|
||||
|
||||
// Cleanup function
|
||||
const cleanup = async (): Promise<void> => {
|
||||
if (ctx.daemon) {
|
||||
if (typeof ctx.daemon.pid === 'number') {
|
||||
killPidTree(ctx.daemon.pid, 'SIGTERM')
|
||||
await sleep(250)
|
||||
killPidTree(ctx.daemon.pid, 'SIGKILL')
|
||||
if (typeof ctx.daemon.pid === "number") {
|
||||
killPidTree(ctx.daemon.pid, "SIGTERM");
|
||||
await sleep(250);
|
||||
killPidTree(ctx.daemon.pid, "SIGKILL");
|
||||
} else {
|
||||
ctx.daemon.kill()
|
||||
ctx.daemon.kill();
|
||||
}
|
||||
}
|
||||
await rm(paseoHome, { recursive: true, force: true })
|
||||
await rm(workDir, { recursive: true, force: true })
|
||||
}
|
||||
await rm(paseoHome, { recursive: true, force: true });
|
||||
await rm(workDir, { recursive: true, force: true });
|
||||
};
|
||||
|
||||
const ctx: TestContext = {
|
||||
port,
|
||||
@@ -144,9 +142,9 @@ export async function createTestContext(): Promise<TestContext> {
|
||||
daemon: null,
|
||||
paseo,
|
||||
cleanup,
|
||||
}
|
||||
};
|
||||
|
||||
return ctx
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,10 +152,10 @@ export async function createTestContext(): Promise<TestContext> {
|
||||
* Use this for tests that need a running daemon
|
||||
*/
|
||||
export async function createTestContextWithDaemon(): Promise<TestContext> {
|
||||
const ctx = await createTestContext()
|
||||
ctx.daemon = await startDaemon(ctx.port, ctx.paseoHome)
|
||||
await waitForDaemon(ctx.port)
|
||||
return ctx
|
||||
const ctx = await createTestContext();
|
||||
ctx.daemon = await startDaemon(ctx.port, ctx.paseoHome);
|
||||
await waitForDaemon(ctx.port);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,13 +163,13 @@ export async function createTestContextWithDaemon(): Promise<TestContext> {
|
||||
*/
|
||||
export function registerCleanupHandlers(cleanup: () => Promise<void>): void {
|
||||
const handler = async () => {
|
||||
await cleanup()
|
||||
process.exit(0)
|
||||
}
|
||||
await cleanup();
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
process.on('exit', () => {
|
||||
process.on("exit", () => {
|
||||
// Can't await in exit handler, but at least try to kill daemon
|
||||
})
|
||||
process.on('SIGINT', handler)
|
||||
process.on('SIGTERM', handler)
|
||||
});
|
||||
process.on("SIGINT", handler);
|
||||
process.on("SIGTERM", handler);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user