test(stores): cover settings merge/clamp + notification sanitizer (29→42 tests)
Extract two pure helpers so they're testable without zustand/expo: - settings-merge.ts: clampPageSize + forward-compatible mergeStoredSettings (the upgrade path where stored data predates a new notification category must yield the default, not undefined). stores/settings.ts now delegates. - notify-format.ts: sanitizeBody (strip C0/DEL control chars, trim, cap at 200) used for server-supplied notification text. stores/events.ts now imports it. Behavior unchanged; typecheck clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,7 @@ import { create } from "zustand"
|
||||
import { useConnections } from "./connections"
|
||||
import { useSessions } from "./sessions"
|
||||
import { send as notify } from "../lib/notifications"
|
||||
|
||||
const MAX_NOTIF_BODY = 200
|
||||
const sanitizeBody = (s: string | undefined, fallback: string): string =>
|
||||
(s ? s.replace(/[\x00-\x1f\x7f]/g, " ").trim().slice(0, MAX_NOTIF_BODY) : "") || fallback
|
||||
import { sanitizeBody } from "../lib/notify-format"
|
||||
import { addBreadcrumb } from "../lib/sentry"
|
||||
import type { Client, Part, Session, Message } from "../lib/sdk"
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { create } from "zustand"
|
||||
import * as SecureStore from "expo-secure-store"
|
||||
import { type Category, defaultPreferences } from "../lib/notifications"
|
||||
import { clampPageSize, mergeStoredSettings } from "../lib/settings-merge"
|
||||
|
||||
const SETTINGS_KEY = "opencode_settings"
|
||||
|
||||
@@ -37,16 +38,15 @@ export const useSettings = create<SettingsState>((set, get) => ({
|
||||
const raw = await SecureStore.getItemAsync(SETTINGS_KEY)
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw) as Partial<Settings>
|
||||
// Merge stored notifications with defaults so new categories get their default
|
||||
const notifications = { ...DEFAULTS.notifications, ...parsed.notifications }
|
||||
set({ ...DEFAULTS, ...parsed, notifications, loaded: true })
|
||||
// Merge stored settings with defaults so new fields/categories get their default
|
||||
set({ ...mergeStoredSettings(DEFAULTS, parsed), loaded: true })
|
||||
return
|
||||
}
|
||||
set({ loaded: true })
|
||||
},
|
||||
|
||||
setPageSize: async (size) => {
|
||||
const clamped = Math.max(10, Math.min(200, size))
|
||||
const clamped = clampPageSize(size)
|
||||
set({ pageSize: clamped })
|
||||
await persist({ ...snapshot(get), pageSize: clamped })
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user