mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
118 lines
4.3 KiB
TypeScript
118 lines
4.3 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { createCriticalConfigErrorHandler, createReloadConfigHandler } from './startup-config';
|
|
|
|
test('createReloadConfigHandler runs success flow with warnings', async () => {
|
|
const calls: string[] = [];
|
|
const refreshCalls: { force: boolean }[] = [];
|
|
|
|
const reloadConfig = createReloadConfigHandler({
|
|
reloadConfigStrict: () => ({
|
|
ok: true,
|
|
path: '/tmp/config.jsonc',
|
|
warnings: [
|
|
{
|
|
path: 'ankiConnect.pollingRate',
|
|
message: 'must be >= 50',
|
|
value: 10,
|
|
fallback: 250,
|
|
},
|
|
],
|
|
}),
|
|
logInfo: (message) => calls.push(`info:${message}`),
|
|
logWarning: (message) => calls.push(`warn:${message}`),
|
|
showDesktopNotification: (title, options) => calls.push(`notify:${title}:${options.body}`),
|
|
startConfigHotReload: () => calls.push('hotReload:start'),
|
|
refreshAnilistClientSecretState: async (options) => {
|
|
refreshCalls.push(options);
|
|
},
|
|
failHandlers: {
|
|
logError: (details) => calls.push(`error:${details}`),
|
|
showErrorBox: (title, details) => calls.push(`dialog:${title}:${details}`),
|
|
quit: () => calls.push('quit'),
|
|
},
|
|
});
|
|
|
|
reloadConfig();
|
|
await Promise.resolve();
|
|
|
|
assert.ok(calls.some((entry) => entry.startsWith('info:Using config file: /tmp/config.jsonc')));
|
|
assert.ok(calls.some((entry) => entry.startsWith('warn:[config] Validation found 1 issue(s)')));
|
|
assert.ok(
|
|
calls.some((entry) => entry.includes('notify:SubMiner:1 config validation issue(s) detected.')),
|
|
);
|
|
assert.ok(calls.some((entry) => entry.includes('1. ankiConnect.pollingRate: must be >= 50')));
|
|
assert.ok(calls.includes('hotReload:start'));
|
|
assert.deepEqual(refreshCalls, [{ force: true }]);
|
|
});
|
|
|
|
test('createReloadConfigHandler fails startup for parse errors', () => {
|
|
const calls: string[] = [];
|
|
const previousExitCode = process.exitCode;
|
|
process.exitCode = 0;
|
|
|
|
const reloadConfig = createReloadConfigHandler({
|
|
reloadConfigStrict: () => ({
|
|
ok: false,
|
|
path: '/tmp/config.jsonc',
|
|
error: 'unexpected token',
|
|
}),
|
|
logInfo: (message) => calls.push(`info:${message}`),
|
|
logWarning: (message) => calls.push(`warn:${message}`),
|
|
showDesktopNotification: (title, options) => calls.push(`notify:${title}:${options.body}`),
|
|
startConfigHotReload: () => calls.push('hotReload:start'),
|
|
refreshAnilistClientSecretState: async () => {
|
|
calls.push('refresh');
|
|
},
|
|
failHandlers: {
|
|
logError: (details) => calls.push(`error:${details}`),
|
|
showErrorBox: (title, details) => calls.push(`dialog:${title}:${details}`),
|
|
quit: () => calls.push('quit'),
|
|
},
|
|
});
|
|
|
|
assert.throws(() => reloadConfig(), /Failed to parse config file at:/);
|
|
assert.equal(process.exitCode, 1);
|
|
assert.ok(calls.some((entry) => entry.startsWith('error:Failed to parse config file at:')));
|
|
assert.ok(calls.some((entry) => entry.includes('/tmp/config.jsonc')));
|
|
assert.ok(calls.some((entry) => entry.includes('Error: unexpected token')));
|
|
assert.ok(calls.some((entry) => entry.includes('Fix the config file and restart SubMiner.')));
|
|
assert.ok(
|
|
calls.some((entry) =>
|
|
entry.startsWith('dialog:SubMiner config parse error:Failed to parse config file at:'),
|
|
),
|
|
);
|
|
assert.ok(calls.includes('quit'));
|
|
assert.equal(calls.includes('hotReload:start'), false);
|
|
|
|
process.exitCode = previousExitCode;
|
|
});
|
|
|
|
test('createCriticalConfigErrorHandler formats and fails', () => {
|
|
const calls: string[] = [];
|
|
const previousExitCode = process.exitCode;
|
|
process.exitCode = 0;
|
|
|
|
const handleCriticalErrors = createCriticalConfigErrorHandler({
|
|
getConfigPath: () => '/tmp/config.jsonc',
|
|
failHandlers: {
|
|
logError: (details) => calls.push(`error:${details}`),
|
|
showErrorBox: (title, details) => calls.push(`dialog:${title}:${details}`),
|
|
quit: () => calls.push('quit'),
|
|
},
|
|
});
|
|
|
|
assert.throws(
|
|
() => handleCriticalErrors(['foo invalid', 'bar invalid']),
|
|
/Critical config validation failed/,
|
|
);
|
|
|
|
assert.equal(process.exitCode, 1);
|
|
assert.ok(calls.some((entry) => entry.includes('/tmp/config.jsonc')));
|
|
assert.ok(calls.some((entry) => entry.includes('1. foo invalid')));
|
|
assert.ok(calls.some((entry) => entry.includes('2. bar invalid')));
|
|
assert.ok(calls.includes('quit'));
|
|
|
|
process.exitCode = previousExitCode;
|
|
});
|