chore: 官网拆分 homepage + 关于页瘦身 + 端口 5175(当前可用状态基线)
This commit is contained in:
1 parent
5eb11826db
commit
be151cb68f
85 files changed
+4420
-1530
No files matched your search
@@ -0,0 +1,71 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
function deferred<T>() {
|
||||
let resolve!: (value: T) => void
|
||||
const promise = new Promise<T>((done) => {
|
||||
resolve = done
|
||||
})
|
||||
return { promise, resolve }
|
||||
}
|
||||
|
||||
let store: typeof import('../../src/stores/settingsStore').useSettingsStore
|
||||
beforeEach(async () => {
|
||||
vi.resetModules()
|
||||
vi.mocked(window.opsxApi.settingsGet).mockReset().mockResolvedValue({ success: true })
|
||||
vi.mocked(window.opsxApi.settingsSet).mockReset().mockResolvedValue({ success: true })
|
||||
store = (await import('../../src/stores/settingsStore')).useSettingsStore
|
||||
})
|
||||
|
||||
describe('settings persistence', () => {
|
||||
it('serializes writes while keeping later edits visible', async () => {
|
||||
const first = deferred<{ success: boolean }>()
|
||||
vi.mocked(window.opsxApi.settingsSet).mockImplementationOnce(() => first.promise)
|
||||
const saveTheme = store.getState().setSetting('theme', 'light')
|
||||
const saveFont = store.getState().setSetting('fontSize', 20)
|
||||
expect(store.getState().settings).toMatchObject({ theme: 'light', fontSize: 20 })
|
||||
await Promise.resolve()
|
||||
expect(window.opsxApi.settingsSet).toHaveBeenCalledTimes(1)
|
||||
first.resolve({ success: true })
|
||||
await Promise.all([saveTheme, saveFont])
|
||||
expect(window.opsxApi.settingsSet).toHaveBeenLastCalledWith(
|
||||
'app-settings',
|
||||
expect.objectContaining({ theme: 'light', fontSize: 20 })
|
||||
)
|
||||
})
|
||||
|
||||
it('rolls back a rejected envelope without persisting the failed patch in the next write', async () => {
|
||||
vi.mocked(window.opsxApi.settingsSet).mockResolvedValueOnce({ success: false, error: 'disk full' })
|
||||
await Promise.all([store.getState().setSetting('theme', 'light'), store.getState().setSetting('fontSize', 20)])
|
||||
expect(store.getState().settings).toMatchObject({ theme: 'dark', fontSize: 20 })
|
||||
expect(window.opsxApi.settingsSet).toHaveBeenLastCalledWith(
|
||||
'app-settings',
|
||||
expect.objectContaining({ theme: 'dark', fontSize: 20 })
|
||||
)
|
||||
const { useToastStore } = await import('../../src/stores/toastStore')
|
||||
expect(useToastStore.getState().toasts.at(-1)).toMatchObject({
|
||||
type: 'error',
|
||||
message: expect.stringContaining('disk full'),
|
||||
})
|
||||
})
|
||||
|
||||
it('continues saving after a thrown IPC failure, including edits to the same field', async () => {
|
||||
vi.mocked(window.opsxApi.settingsSet).mockRejectedValueOnce(new Error('IPC unavailable'))
|
||||
await Promise.all([store.getState().setSetting('fontSize', 18), store.getState().setSetting('fontSize', 22)])
|
||||
expect(store.getState().settings.fontSize).toBe(22)
|
||||
expect(window.opsxApi.settingsSet).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
|
||||
it('merges edits made while initial settings are loading into the persisted snapshot', async () => {
|
||||
const read = deferred<{ success: boolean; value: unknown }>()
|
||||
vi.mocked(window.opsxApi.settingsGet).mockReturnValueOnce(read.promise)
|
||||
const load = store.getState().loadSettings()
|
||||
const save = store.getState().setSetting('fontSize', 22)
|
||||
read.resolve({ success: true, value: { theme: 'light', agentSafetyMode: 'relaxed' } })
|
||||
await Promise.all([load, save])
|
||||
expect(store.getState().settings).toMatchObject({ theme: 'light', fontSize: 22 })
|
||||
expect(window.opsxApi.settingsSet).toHaveBeenLastCalledWith(
|
||||
'app-settings',
|
||||
expect.objectContaining({ theme: 'light', fontSize: 22 })
|
||||
)
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user