Files
SubMiner/launcher/commands/command-modules.test.ts

91 lines
2.5 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { parseArgs } from '../config.js';
import type { ProcessAdapter } from '../process-adapter.js';
import type { LauncherCommandContext } from './context.js';
import { runConfigCommand } from './config-command.js';
import { runDoctorCommand } from './doctor-command.js';
import { runMpvPreAppCommand } from './mpv-command.js';
class ExitSignal extends Error {
code: number;
constructor(code: number) {
super(`exit:${code}`);
this.code = code;
}
}
function createContext(overrides: Partial<LauncherCommandContext> = {}): LauncherCommandContext {
const args = parseArgs([], 'subminer', {});
const adapter: ProcessAdapter = {
platform: () => 'linux',
onSignal: () => {},
writeStdout: () => {},
exit: (code) => {
throw new ExitSignal(code);
},
setExitCode: () => {},
};
return {
args,
scriptPath: '/tmp/subminer',
scriptName: 'subminer',
mpvSocketPath: '/tmp/subminer.sock',
appPath: '/tmp/subminer.app',
launcherJellyfinConfig: {},
processAdapter: adapter,
...overrides,
};
}
test('config command writes newline-terminated path via process adapter', () => {
const writes: string[] = [];
const context = createContext();
context.args.configPath = true;
context.processAdapter = {
...context.processAdapter,
writeStdout: (text) => writes.push(text),
};
const handled = runConfigCommand(context, {
existsSync: () => true,
readFileSync: () => '',
resolveMainConfigPath: () => '/tmp/SubMiner/config.jsonc',
});
assert.equal(handled, true);
assert.deepEqual(writes, ['/tmp/SubMiner/config.jsonc\n']);
});
test('doctor command exits non-zero for missing hard dependencies', () => {
const context = createContext({ appPath: null });
context.args.doctor = true;
assert.throws(
() =>
runDoctorCommand(context, {
commandExists: () => false,
configExists: () => true,
resolveMainConfigPath: () => '/tmp/SubMiner/config.jsonc',
}),
(error: unknown) => error instanceof ExitSignal && error.code === 1,
);
});
test('mpv pre-app command exits non-zero when socket is not ready', async () => {
const context = createContext();
context.args.mpvStatus = true;
await assert.rejects(
async () => {
await runMpvPreAppCommand(context, {
waitForUnixSocketReady: async () => false,
launchMpvIdleDetached: async () => {},
});
},
(error: unknown) => error instanceof ExitSignal && error.code === 1,
);
});