test: 存储真链集成测试(MetonaSqlark memory 方言——非 mock)——save/load/export/slot 管理 6 种子全链
此前所有存量测试用 SaveDbDriver mock——真实 SQL 方言链从未被 vitest 覆盖(唯一 GUI 冒烟因环境不可用); 本测试直接注入 MeSqlark memory 后端:saveState→list→loadState→resume advance→exportAll→slot 管理面/remove; 为 0.1.36 三问题(推进崩溃/存档丢失)提供真实存储链防线;+1 套件
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { MeSqlark } from '@metona-team/metona-sqlark'
|
||||
import { setSqlarkBackend } from '../src/renderer/game/storage/db'
|
||||
import { getSaveSlot } from '../src/renderer/game/storage/db'
|
||||
import { World } from '../src/renderer/game/engine/runtime/World'
|
||||
import { metaFromState } from '../src/renderer/ui/storeHelper'
|
||||
import type { GameState } from '../src/renderer/game/types/domain'
|
||||
import type { SaveDbDriver } from '../src/renderer/game/storage/slots'
|
||||
|
||||
function memoryBackend(): void {
|
||||
setSqlarkBackend({
|
||||
create: async (cfg: { name: string }) => {
|
||||
const db = new MeSqlark({
|
||||
name: `it-${cfg.name}-${Math.random().toString(36).slice(2)}`,
|
||||
mode: 'hybrid',
|
||||
diskEngine: 'memory',
|
||||
aria: {}
|
||||
})
|
||||
await db.init()
|
||||
return { query: (sql: string, params?: unknown[]) => db.query(sql, params) }
|
||||
}
|
||||
} as never)
|
||||
}
|
||||
|
||||
function saveClone(w: World): GameState {
|
||||
return JSON.parse(JSON.stringify(w.state)) as GameState
|
||||
}
|
||||
|
||||
describe('0.1.36 存储真链(MetonaSqlark memory 方言——非 mock)', () => {
|
||||
it('save→list→load→resume→save 全链 12 种子不崩', async () => {
|
||||
memoryBackend()
|
||||
for (let k = 0; k < 6; k++) {
|
||||
const slot = (k % 4) + 1
|
||||
const w = World.create({ seed: `real-${k}`, surname: '钟', familyName: '钟家', motto: 'm', difficulty: 'normal' })
|
||||
for (let i = 0; i < 12; i++) w.advanceMonth()
|
||||
const file = await getSaveSlot(slot)
|
||||
const file2 = await getSaveSlot(slot)
|
||||
await file.open()
|
||||
await file.saveState(saveClone(w), '自动')
|
||||
const meta = metaFromState(w.state, slot)
|
||||
await file.setMeta(meta)
|
||||
const loaded = await file2.loadState()
|
||||
expect(loaded).toBeTruthy()
|
||||
expect(loaded!.year).toBeGreaterThan(0)
|
||||
const y = new World(loaded!)
|
||||
for (let i = 0; i < 8; i++) y.advanceMonth()
|
||||
const exportStr = await file.exportAll()
|
||||
expect(exportStr.length).toBeGreaterThan(100)
|
||||
}
|
||||
// slot 管理面
|
||||
const { getSlotManager } = await import('../src/renderer/game/storage/db')
|
||||
const mgr = getSlotManager()
|
||||
const metas = await mgr.listSlotMetas()
|
||||
expect(metas.length).toBe(4)
|
||||
await mgr.updateSlotMeta(1, { slot: 1, surname: '钟', name: '钟家', estate: '青云庄', year: 3, month: 4, generation: 1, members: 5, reputation: 5, updatedAt: 'x', version: '0.1.35' })
|
||||
await mgr.removeSlotMeta(1)
|
||||
expect((await mgr.listSlotMetas())[0]).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user