73 lines
3.3 KiB
TypeScript
73 lines
3.3 KiB
TypeScript
import { describe, test } from 'node:test';
|
|||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import { SETTINGS_REGISTRY_FIELDS, filterPersistableSettingsChanges, withoutSecretSettings, type SettingsRegistryGateFields } from './settings-registry-gate';
|
||
|
|
|
||
|
|
const fields: SettingsRegistryGateFields = {
|
||
|
|
themeId: { scope: 'profile' },
|
||
|
|
smallModelOverride: { scope: 'profile' },
|
||
|
|
hasDesktopSettings: { scope: 'instance', computed: true },
|
||
|
|
sidebarWidth: { scope: 'device', local: true },
|
||
|
|
windowBounds: { scope: 'instance', owner: 'desktop-shell' },
|
||
|
|
desktopUiPassword: { scope: 'instance', secret: true },
|
||
|
|
};
|
||
|
|
|
||
|
|
describe('withoutSecretSettings', () => {
|
||
|
|
test('withholds secret keys and keeps everything else', () => {
|
||
|
|
assert.deepEqual(withoutSecretSettings({ desktopUiPassword: 'pw', themeId: 'a' }, fields), { themeId: 'a' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('the real registry marks the UI password and tunnel tokens secret', () => {
|
||
|
|
const stripped = withoutSecretSettings({
|
||
|
|
desktopUiPassword: 'pw',
|
||
|
|
managedRemoteTunnelToken: 't',
|
||
|
|
managedRemoteTunnelPresetTokens: { a: 't' },
|
||
|
|
themeId: 'a',
|
||
|
|
}, SETTINGS_REGISTRY_FIELDS);
|
||
|
|
assert.deepEqual(stripped, { themeId: 'a' });
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('filterPersistableSettingsChanges', () => {
|
||
|
|
test('keeps stored shared fields and preserves their values as sent', () => {
|
||
|
|
const result = filterPersistableSettingsChanges(
|
||
|
|
{ themeId: 'nord', smallModelOverride: '', unrelated: 1 },
|
||
|
|
fields,
|
||
|
|
);
|
||
|
|
assert.deepEqual(result, { themeId: 'nord', smallModelOverride: '' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('drops keys the registry does not know', () => {
|
||
|
|
assert.deepEqual(filterPersistableSettingsChanges({ gitProviderId: 'zen', gitModelId: 'x' }, fields), {});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('drops computed, local, and desktop-shell owned keys', () => {
|
||
|
|
const result = filterPersistableSettingsChanges(
|
||
|
|
{ hasDesktopSettings: true, sidebarWidth: 320, windowBounds: { x: 0 }, themeId: 'a' },
|
||
|
|
fields,
|
||
|
|
);
|
||
|
|
assert.deepEqual(result, { themeId: 'a' });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('ignores prototype keys that are not registry fields', () => {
|
||
|
|
assert.deepEqual(filterPersistableSettingsChanges({ constructor: 'x', toString: 'y' }, fields), {});
|
||
|
|
});
|
||
|
|
|
||
|
|
test('the checked-in snapshot drops derived-at-read and desktop-shell keys but keeps profile settings', () => {
|
||
|
|
const result = filterPersistableSettingsChanges({
|
||
|
|
themeId: 'nord',
|
||
|
|
smallModelUseDefault: false,
|
||
|
|
smallModelOverride: 'zen/gpt-5-nano',
|
||
|
|
gitProviderId: 'zen',
|
||
|
|
gitModelId: 'gpt-5-nano',
|
||
|
|
});
|
||
|
|
assert.deepEqual(result, { themeId: 'nord', smallModelUseDefault: false, smallModelOverride: 'zen/gpt-5-nano' });
|
||
|
|
|
||
|
|
const computedKeys = Object.entries(SETTINGS_REGISTRY_FIELDS).filter(([, field]) => field.computed).map(([key]) => key);
|
||
|
|
const localKeys = Object.entries(SETTINGS_REGISTRY_FIELDS).filter(([, field]) => field.local).map(([key]) => key);
|
||
|
|
const shellKeys = Object.entries(SETTINGS_REGISTRY_FIELDS).filter(([, field]) => field.owner === 'desktop-shell').map(([key]) => key);
|
||
|
|
assert.ok(computedKeys.length > 0 && localKeys.length > 0 && shellKeys.length > 0, 'snapshot exercises every gate branch');
|
||
|
|
const blocked = Object.fromEntries([...computedKeys, ...localKeys, ...shellKeys].map((key) => [key, 'value']));
|
||
|
|
assert.deepEqual(filterPersistableSettingsChanges(blocked), {});
|
||
|
|
});
|
||
|
|
});
|