Files
Genarrative/src/persistence/runtimeSnapshot.test.ts
2026-04-10 15:37:02 +08:00

76 lines
2.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import type { GameState, StoryMoment } from '../types';
import {
resolveHydratedSnapshotState,
} from './runtimeSnapshot';
function createStory(
text: string,
streaming = false,
): StoryMoment {
return {
text,
options: [],
streaming,
};
}
describe('runtimeSnapshot', () => {
it('keeps server-hydrated snapshots unchanged', () => {
const snapshot = {
gameState: {
playerCharacter: {
id: 'sword-princess',
},
playerEquipment: {
weapon: null,
armor: null,
relic: null,
},
runtimeActionVersion: 3,
runtimeSessionId: 'runtime-main',
} as GameState,
currentStory: createStory('服务端恢复故事'),
bottomTab: 'inventory',
};
expect(resolveHydratedSnapshotState(snapshot)).toBe(snapshot);
});
it('only applies minimal local shape hydration for non-hydrated legacy snapshots', () => {
const snapshot = {
gameState: {
worldType: 'WUXIA',
customWorldProfile: null,
playerCharacter: {
id: 'sword-princess',
},
playerHp: 999,
playerMaxHp: 12,
playerMana: 999,
playerMaxMana: 12,
runtimeActionVersion: undefined,
runtimeSessionId: undefined,
playerEquipment: null,
} as unknown as GameState,
currentStory: createStory('旧快照故事', true),
bottomTab: 'unknown',
};
const hydrated = resolveHydratedSnapshotState(snapshot);
expect(hydrated.bottomTab).toBe('adventure');
expect(hydrated.currentStory?.streaming).toBe(false);
expect(hydrated.gameState.playerEquipment).toEqual({
weapon: null,
armor: null,
relic: null,
});
expect(hydrated.gameState.playerMaxHp).toBe(12);
expect(hydrated.gameState.playerHp).toBe(12);
expect(hydrated.gameState.playerMaxMana).toBe(12);
expect(hydrated.gameState.playerMana).toBe(12);
});
});