fix(macos): show full config warning details

This commit is contained in:
2026-02-27 18:33:36 -08:00
parent 9e4e588f33
commit cc2f9ef325
4 changed files with 49 additions and 0 deletions

View File

@@ -2,6 +2,7 @@ import test from 'node:test';
import assert from 'node:assert/strict';
import {
buildConfigParseErrorDetails,
buildConfigWarningDialogDetails,
buildConfigWarningNotificationBody,
buildConfigWarningSummary,
failStartupFromConfig,
@@ -53,6 +54,22 @@ test('buildConfigWarningNotificationBody includes concise warning details', () =
);
});
test('buildConfigWarningDialogDetails includes full warning details', () => {
const details = buildConfigWarningDialogDetails('/tmp/config.jsonc', [
{
path: 'ankiConnect.pollingRate',
message: 'must be >= 50',
value: 10,
fallback: 250,
},
]);
assert.match(details, /SubMiner detected config validation issues\./);
assert.match(details, /File: \/tmp\/config\.jsonc/);
assert.match(details, /1\. ankiConnect\.pollingRate: must be >= 50/);
assert.match(details, /actual=10 fallback=250/);
});
test('buildConfigParseErrorDetails includes path error and restart guidance', () => {
const details = buildConfigParseErrorDetails('/tmp/config.jsonc', 'unexpected token at line 1');

View File

@@ -61,6 +61,25 @@ export function buildConfigWarningNotificationBody(
].join('\n');
}
export function buildConfigWarningDialogDetails(
configPath: string,
warnings: ConfigValidationWarning[],
): string {
const lines = warnings.map(
(warning, index) =>
`${index + 1}. ${warning.path}: ${warning.message} actual=${formatConfigValue(warning.value)} fallback=${formatConfigValue(warning.fallback)}`,
);
return [
'SubMiner detected config validation issues.',
`File: ${configPath}`,
'',
...lines,
'',
'Defaults were applied where possible.',
].join('\n');
}
export function buildConfigParseErrorDetails(configPath: string, parseError: string): string {
return [
'Failed to parse config file at:',

View File

@@ -42,6 +42,12 @@ test('createReloadConfigHandler runs success flow with warnings', async () => {
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.some((entry) =>
entry.includes('dialog:SubMiner config validation warning:SubMiner detected config validation issues.'),
),
);
assert.ok(calls.some((entry) => entry.includes('actual=10 fallback=250')));
assert.ok(calls.includes('hotReload:start'));
assert.deepEqual(refreshCalls, [{ force: true }]);
});

View File

@@ -1,5 +1,6 @@
import type { ConfigValidationWarning } from '../../types';
import {
buildConfigWarningDialogDetails,
buildConfigParseErrorDetails,
buildConfigWarningNotificationBody,
buildConfigWarningSummary,
@@ -60,6 +61,12 @@ export function createReloadConfigHandler(deps: ReloadConfigRuntimeDeps): () =>
deps.showDesktopNotification('SubMiner', {
body: buildConfigWarningNotificationBody(result.path, result.warnings),
});
if (process.platform === 'darwin') {
deps.failHandlers.showErrorBox(
'SubMiner config validation warning',
buildConfigWarningDialogDetails(result.path, result.warnings),
);
}
}
deps.startConfigHotReload();