Why: Raw identifiers and mixed settings scopes made project administration difficult and hid authorization boundaries. Evidence: SELF receipts /tmp/project-settings-frontend-full-green-20261014-973d52c1.json and /tmp/project-settings-browser-fixture-final-20261014-973d52c1.json record 284 tests, typecheck, build and 15 real React browser fixture flows. Live composition and formal acceptance remain NOT_RUN. Impact: Add searchable member and document selectors, role filters, versioned duty changes, removal impact review and shared permission details/matrix. Consume server capabilities and settings scopes, preserve personal preferences and default restoration, and discard late responses. Refs: P3/P4/P5/P6/P7, docs/records/2026-10-14-rdm-settings-completion-contract.md
27 lines
1.6 KiB
TypeScript
27 lines
1.6 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { personalSettingsMutation, settingsMutation } from '../src/components/SettingsFields'
|
|
import type { SettingDesc } from '../src/contracts'
|
|
|
|
const schema: SettingDesc[] = [
|
|
{ key: 'tools.limit', group: 'tools', label: '上限', type: 'number', effect: 'new-run', scope: 'system' },
|
|
{ key: 'models.chat.apiKey', group: 'models', label: '密钥', type: 'secret', secret: true, effect: 'hot', scope: 'system' },
|
|
]
|
|
describe('settings merge patch behavior', () => {
|
|
it('omits unchanged masked credentials and removes a numeric override without storing its default', () => {
|
|
expect(settingsMutation({ 'tools.limit': 20, 'models.chat.apiKey': '••••••' }, { 'tools.limit': undefined, 'models.chat.apiKey': '••••••' }, schema))
|
|
.toEqual({ values: {}, unset: ['tools.limit'] })
|
|
})
|
|
it('sends explicit secret revocation as an empty string rather than losing it through flattening', () => {
|
|
expect(settingsMutation({ 'models.chat.apiKey': '••••••' }, { 'models.chat.apiKey': '' }, schema))
|
|
.toEqual({ values: { models: { chat: { apiKey: '' } } }, unset: [] })
|
|
})
|
|
it('does not forward fields outside the visible scoped schema', () => {
|
|
expect(settingsMutation({}, { 'tools.limit': 0, 'project.create': true }, schema))
|
|
.toEqual({ values: { tools: { limit: 0 } }, unset: [] })
|
|
})
|
|
it('uses explicit null deletion for personal inheritance instead of omitting a merged field', () => {
|
|
expect(personalSettingsMutation({ 'tools.limit': 20 }, { 'tools.limit': undefined }, schema))
|
|
.toEqual({ tools: { limit: null } })
|
|
})
|
|
})
|