114 lines
4.5 KiB
TypeScript
114 lines
4.5 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import {
|
|
DEFAULT_MEMORY_PREFERENCES,
|
|
mergeMemoryPreferences,
|
|
normalizeMemoryPreferences
|
|
} from '../src/shared/memory'
|
|
import {
|
|
buildPersonalizationPrompt,
|
|
DEFAULT_PERSONA,
|
|
normalizePersonalization
|
|
} from '../src/shared/personalization'
|
|
import { storageUsagePresentation } from '../src/renderer/src/components/GeneralSettingsPanel'
|
|
import {
|
|
LOADING_TIPS_EVENT,
|
|
LOADING_TIPS_STORAGE_KEY,
|
|
loadingTipsEnabled,
|
|
setLoadingTipsEnabled,
|
|
subscribeLoadingTips
|
|
} from '../src/renderer/src/personalization-prefs'
|
|
|
|
assert.deepEqual(normalizeMemoryPreferences(undefined), DEFAULT_MEMORY_PREFERENCES)
|
|
assert.deepEqual(
|
|
mergeMemoryPreferences(undefined, { conversationMemory: false }),
|
|
{ conversationMemory: false, localMemorySkills: false },
|
|
'changing conversation memory must not change local memory skills'
|
|
)
|
|
assert.deepEqual(
|
|
mergeMemoryPreferences(undefined, { localMemorySkills: true }),
|
|
{ conversationMemory: true, localMemorySkills: true },
|
|
'changing local memory skills must not change conversation memory'
|
|
)
|
|
assert.deepEqual(
|
|
mergeMemoryPreferences({ conversationMemory: false }, undefined),
|
|
{ conversationMemory: false, localMemorySkills: false },
|
|
'a partial stored view must inherit the declared default for its omitted key'
|
|
)
|
|
|
|
const gib = 1024 ** 3
|
|
const exactStorage = storageUsagePresentation({
|
|
dataBytes: gib,
|
|
dataUsagePartial: false,
|
|
diskTotal: 100 * gib,
|
|
diskFree: 50 * gib
|
|
})
|
|
assert.equal(exactStorage.usageText, '已用 1.00 GB / 共 100.0 GB')
|
|
assert.equal(exactStorage.cacheLabel, '系统缓存')
|
|
assert.equal(exactStorage.otherLabel, '磁盘已用')
|
|
assert.equal(exactStorage.cachePercentLowerBound, 1)
|
|
assert.equal(exactStorage.otherPercentUpperBound, 49)
|
|
assert.equal(exactStorage.freePercent, 50)
|
|
assert.equal(exactStorage.partial, false)
|
|
|
|
const partialStorage = storageUsagePresentation({
|
|
dataBytes: gib,
|
|
dataUsagePartial: true,
|
|
diskTotal: 100 * gib,
|
|
diskFree: 50 * gib
|
|
})
|
|
assert.equal(partialStorage.usageText, '统计未完成 · 至少已扫描 1.00 GB')
|
|
assert.equal(partialStorage.cacheLabel, '系统缓存(至少)')
|
|
assert.equal(partialStorage.otherLabel, '其他磁盘数据(至多)')
|
|
assert.equal(partialStorage.partial, true)
|
|
|
|
const overCountedStorage = storageUsagePresentation({
|
|
dataBytes: 80 * gib,
|
|
dataUsagePartial: true,
|
|
diskTotal: 100 * gib,
|
|
diskFree: 70 * gib
|
|
})
|
|
assert.equal(overCountedStorage.cachePercentLowerBound, 30, 'cache must not exceed the mounted disk used ratio')
|
|
assert.equal(overCountedStorage.otherPercentUpperBound, 0)
|
|
assert.equal(overCountedStorage.freePercent, 70)
|
|
|
|
const defaultPrompt = buildPersonalizationPrompt(normalizePersonalization(undefined))
|
|
assert.ok(defaultPrompt.includes(`### 人设设定\n${DEFAULT_PERSONA}`))
|
|
assert.equal(buildPersonalizationPrompt(normalizePersonalization({ persona: '' })), '')
|
|
|
|
const storage = new Map<string, string>()
|
|
const fakeLocalStorage = {
|
|
get length(): number { return storage.size },
|
|
clear(): void { storage.clear() },
|
|
getItem(key: string): string | null { return storage.get(key) ?? null },
|
|
key(index: number): string | null { return [...storage.keys()][index] ?? null },
|
|
removeItem(key: string): void { storage.delete(key) },
|
|
setItem(key: string, value: string): void { storage.set(key, value) }
|
|
}
|
|
const fakeWindow = new EventTarget()
|
|
Object.defineProperty(globalThis, 'localStorage', { value: fakeLocalStorage, configurable: true })
|
|
Object.defineProperty(globalThis, 'window', { value: fakeWindow, configurable: true })
|
|
|
|
assert.equal(loadingTipsEnabled(), true)
|
|
let notifications = 0
|
|
const unsubscribe = subscribeLoadingTips(() => { notifications++ })
|
|
setLoadingTipsEnabled(false)
|
|
assert.equal(storage.get(LOADING_TIPS_STORAGE_KEY), '0')
|
|
assert.equal(notifications, 1, 'same-window custom event should update immediately')
|
|
|
|
const unrelatedStorage = new Event('storage')
|
|
Object.defineProperty(unrelatedStorage, 'key', { value: 'unrelated' })
|
|
fakeWindow.dispatchEvent(unrelatedStorage)
|
|
assert.equal(notifications, 1, 'unrelated storage keys must be ignored')
|
|
|
|
const matchingStorage = new Event('storage')
|
|
Object.defineProperty(matchingStorage, 'key', { value: LOADING_TIPS_STORAGE_KEY })
|
|
fakeWindow.dispatchEvent(matchingStorage)
|
|
assert.equal(notifications, 2, 'another window storage event should update the subscriber')
|
|
|
|
unsubscribe()
|
|
fakeWindow.dispatchEvent(new Event(LOADING_TIPS_EVENT))
|
|
fakeWindow.dispatchEvent(matchingStorage)
|
|
assert.equal(notifications, 2, 'unsubscribe must clean up both local and storage listeners')
|
|
|
|
console.log('remediation-pure-regression: all checks passed')
|