Tests. Autocomplete. Few Fixes. Mocks for Electrum Service. Template-to-Json parser. Fix global paths. Use IO Dependency injection for logging from cli. Additional commands in CLI.
This commit is contained in:
162
tests/cli/mocks/command.ts
Normal file
162
tests/cli/mocks/command.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
import { vi, expect, type Mock } from "vitest";
|
||||
import type {
|
||||
BaseCommandDependencies,
|
||||
CommandDependencies,
|
||||
CommandIO,
|
||||
CommandPaths,
|
||||
} from "../../../src/cli/commands/types";
|
||||
import type { AppService } from "../../../src/services/app";
|
||||
|
||||
/**
|
||||
* Captured CLI IO buffers used by tests.
|
||||
*/
|
||||
export type MockIOCapture = {
|
||||
out: string[];
|
||||
err: string[];
|
||||
verbose: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Spy functions for each IO channel.
|
||||
*/
|
||||
export type MockIOSpies = {
|
||||
out: Mock;
|
||||
err: Mock;
|
||||
verbose: Mock;
|
||||
};
|
||||
|
||||
/**
|
||||
* Complete mock IO result including the IO adapter, capture buffers, and spies.
|
||||
*/
|
||||
export type MockIO = {
|
||||
io: CommandIO;
|
||||
capture: MockIOCapture;
|
||||
spies: MockIOSpies;
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines an expected log message for assertion.
|
||||
* At least one of out, err, or verbose should be specified.
|
||||
*/
|
||||
export type LogExpectation = {
|
||||
/** Expected substring (or exact match if exact=true) in io.out */
|
||||
out?: string;
|
||||
/** Expected substring (or exact match if exact=true) in io.err */
|
||||
err?: string;
|
||||
/** Expected substring (or exact match if exact=true) in io.verbose */
|
||||
verbose?: string;
|
||||
/** If true, match the string exactly instead of using contains (default: false) */
|
||||
exact?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a command IO adapter that records every message using vi.fn() spies.
|
||||
* This enables vitest's built-in matchers like toHaveBeenCalledWith.
|
||||
*/
|
||||
export const createMockIO = (): MockIO => {
|
||||
const capture: MockIOCapture = {
|
||||
out: [],
|
||||
err: [],
|
||||
verbose: [],
|
||||
};
|
||||
|
||||
const outSpy = vi.fn((message: string) => {
|
||||
capture.out.push(message);
|
||||
});
|
||||
const errSpy = vi.fn((message: string) => {
|
||||
capture.err.push(message);
|
||||
});
|
||||
const verboseSpy = vi.fn((message: string) => {
|
||||
capture.verbose.push(message);
|
||||
});
|
||||
|
||||
const io: CommandIO = {
|
||||
out: outSpy,
|
||||
err: errSpy,
|
||||
verbose: verboseSpy,
|
||||
};
|
||||
|
||||
return {
|
||||
io,
|
||||
capture,
|
||||
spies: {
|
||||
out: outSpy,
|
||||
err: errSpy,
|
||||
verbose: verboseSpy,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that the expected log messages were printed to the appropriate IO channels.
|
||||
* @param spies - The mock IO spies from createMockIO
|
||||
* @param logs - Array of log expectations to validate
|
||||
*/
|
||||
export const expectLogs = (spies: MockIOSpies, logs: LogExpectation[]): void => {
|
||||
for (const log of logs) {
|
||||
if (log.out !== undefined) {
|
||||
if (log.exact) {
|
||||
expect(spies.out).toHaveBeenCalledWith(log.out);
|
||||
} else {
|
||||
expect(spies.out).toHaveBeenCalledWith(expect.stringContaining(log.out));
|
||||
}
|
||||
}
|
||||
if (log.err !== undefined) {
|
||||
if (log.exact) {
|
||||
expect(spies.err).toHaveBeenCalledWith(log.err);
|
||||
} else {
|
||||
expect(spies.err).toHaveBeenCalledWith(expect.stringContaining(log.err));
|
||||
}
|
||||
}
|
||||
if (log.verbose !== undefined) {
|
||||
if (log.exact) {
|
||||
expect(spies.verbose).toHaveBeenCalledWith(log.verbose);
|
||||
} else {
|
||||
expect(spies.verbose).toHaveBeenCalledWith(expect.stringContaining(log.verbose));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates mock paths for testing.
|
||||
* @param tempDir - Optional temp directory to use as base for all paths
|
||||
*/
|
||||
export const createMockPaths = (tempDir?: string): CommandPaths => {
|
||||
const base = tempDir ?? "/tmp/xo-cli-test";
|
||||
return {
|
||||
mnemonicsDir: base,
|
||||
dataDir: base,
|
||||
walletConfigPath: `${base}/.wallet`,
|
||||
workingDir: base,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates base command dependencies for commands that do not require the app.
|
||||
* @param io - Command IO adapter
|
||||
* @param paths - Optional custom paths (defaults to mock paths)
|
||||
*/
|
||||
export const createBaseCommandDeps = (
|
||||
io: CommandIO,
|
||||
paths?: CommandPaths,
|
||||
): BaseCommandDependencies => ({
|
||||
io,
|
||||
paths: paths ?? createMockPaths(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates command dependencies for app-backed command handlers.
|
||||
* @param app - App service instance
|
||||
* @param io - Command IO adapter
|
||||
* @param paths - Optional custom paths (defaults to mock paths)
|
||||
*/
|
||||
export const createCommandDeps = (
|
||||
app: AppService,
|
||||
io: CommandIO,
|
||||
paths?: CommandPaths,
|
||||
): CommandDependencies => ({
|
||||
app,
|
||||
io,
|
||||
paths: paths ?? createMockPaths(),
|
||||
});
|
||||
Reference in New Issue
Block a user