openpencil/tests/app/settings/preferences/store.test.ts
Danila Poyarkov 2f79278df1
refactor: read stored settings and external responses with Valibot (#937)
* refactor(settings): read stored preferences with a Valibot schema

Each field falls back to its default on its own, so one bad value keeps the rest, as before. Tests pin the behavior; they pass against the previous implementation too.

* refactor(mcp): read stored MCP connections with a Valibot schema

A connection schema checks the ID, trimmed name, transport, and URL rule; a bearer token is kept only for the connection's own credential. A new test covers the credential check and normalization, and passes against the previous implementation.

* refactor(clipboard): read Figma's image batch response with a Valibot schema

* refactor(mcp): read tool descriptors with a Valibot schema

The descriptor type now follows the schema, and tests cover what a descriptor must contain.

* refactor(ai): read stored model settings with Valibot schemas

Connections and model profiles are schemas with their defaults and bounds; the thinking-level migration and the checks between connections, models, and role assignments stay as code. Characterization tests written against the previous implementation pin the behavior.
2026-10-07 09:28:42 +00:00

49 lines
1.8 KiB
TypeScript

import { describe, expect, test } from 'bun:test'
import { DEFAULT_APP_PREFERENCES, parseAppPreferences } from '@/app/settings/preferences/store'
describe('parseAppPreferences', () => {
test('starts from the defaults when nothing usable is stored', () => {
for (const stored of [undefined, null, 'preferences', [], {}]) {
expect(parseAppPreferences(stored)).toEqual(DEFAULT_APP_PREFERENCES)
}
})
test('keeps valid choices and defaults only the fields that are not', () => {
const preferences = parseAppPreferences({
appearance: { animations: 'off' },
chat: { reasoningDisplay: 'sometimes', changePreviewSize: 'large', maxAgentSteps: 'many' },
editing: { snapping: { geometry: false, objects: 'yes' } },
rendering: 'tiled'
})
expect(preferences.appearance.animations).toBe('off')
expect(preferences.chat).toEqual({
...DEFAULT_APP_PREFERENCES.chat,
changePreviewSize: 'large'
})
expect(preferences.editing.snapping).toEqual({
...DEFAULT_APP_PREFERENCES.editing.snapping,
geometry: false
})
expect(preferences.rendering).toEqual(DEFAULT_APP_PREFERENCES.rendering)
})
test('keeps each disabled design check rule once and drops what is not a rule name', () => {
const { designCheck } = parseAppPreferences({
designCheck: { preset: 'strict', disabledRules: ['contrast', 7, 'contrast', 'spacing'] }
})
expect(designCheck).toEqual({
showOnCanvas: true,
preset: 'strict',
disabledRules: ['contrast', 'spacing']
})
})
test('remembers that guided AI setup was finished or skipped', () => {
expect(parseAppPreferences({ onboarding: { aiSetup: 'done' } }).onboarding.aiSetup).toBe('done')
expect(parseAppPreferences({ onboarding: { aiSetup: 'later' } }).onboarding.aiSetup).toBe(
'pending'
)
})
})