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 assert from 'node:assert/strict';
import { import {
buildConfigParseErrorDetails, buildConfigParseErrorDetails,
buildConfigWarningDialogDetails,
buildConfigWarningNotificationBody, buildConfigWarningNotificationBody,
buildConfigWarningSummary, buildConfigWarningSummary,
failStartupFromConfig, 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', () => { test('buildConfigParseErrorDetails includes path error and restart guidance', () => {
const details = buildConfigParseErrorDetails('/tmp/config.jsonc', 'unexpected token at line 1'); const details = buildConfigParseErrorDetails('/tmp/config.jsonc', 'unexpected token at line 1');

View File

@@ -61,6 +61,25 @@ export function buildConfigWarningNotificationBody(
].join('\n'); ].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 { export function buildConfigParseErrorDetails(configPath: string, parseError: string): string {
return [ return [
'Failed to parse config file at:', '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.')), 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('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.ok(calls.includes('hotReload:start'));
assert.deepEqual(refreshCalls, [{ force: true }]); assert.deepEqual(refreshCalls, [{ force: true }]);
}); });

View File

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