Files
waoowaoo/tests/unit/optimistic/ai-data-modal-state.test.ts

104 lines
2.9 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
createAIDataModalDraftState,
mergeAIDataModalDraftStateByDirty,
} from '@/app/[locale]/workspace/[projectId]/modes/novel-promotion/components/storyboard/hooks/useAIDataModalState'
describe('useAIDataModalState optimistic sync helpers', () => {
it('keeps dirty fields when server data refreshes', () => {
const localDraft = createAIDataModalDraftState({
initialShotType: 'Close-up',
initialCameraMove: 'Push in',
initialDescription: 'user typing draft',
initialVideoPrompt: 'prompt-a',
initialPhotographyRules: null,
initialActingNotes: null,
})
const serverDraft = createAIDataModalDraftState({
initialShotType: 'Wide',
initialCameraMove: 'Pan left',
initialDescription: 'server-updated-desc',
initialVideoPrompt: 'prompt-b',
initialPhotographyRules: null,
initialActingNotes: null,
})
const merged = mergeAIDataModalDraftStateByDirty(
localDraft,
serverDraft,
new Set(['description']),
)
expect(merged.description).toBe('user typing draft')
expect(merged.shotType).toBe('Wide')
expect(merged.cameraMove).toBe('Pan left')
expect(merged.videoPrompt).toBe('prompt-b')
})
it('syncs non-dirty nested fields from server', () => {
const localDraft = createAIDataModalDraftState({
initialShotType: 'A',
initialCameraMove: 'B',
initialDescription: 'C',
initialVideoPrompt: 'D',
initialPhotographyRules: {
scene_summary: 'local scene',
lighting: {
direction: 'front',
quality: 'soft',
},
characters: [{
name: 'hero',
screen_position: 'left',
posture: 'standing',
facing: 'camera',
}],
depth_of_field: 'deep',
color_tone: 'warm',
},
initialActingNotes: [{
name: 'hero',
acting: 'smile',
}],
})
const serverDraft = createAIDataModalDraftState({
initialShotType: 'A2',
initialCameraMove: 'B2',
initialDescription: 'C2',
initialVideoPrompt: 'D2',
initialPhotographyRules: {
scene_summary: 'server scene',
lighting: {
direction: 'back',
quality: 'hard',
},
characters: [{
name: 'hero',
screen_position: 'center',
posture: 'running',
facing: 'right',
}],
depth_of_field: 'shallow',
color_tone: 'cool',
},
initialActingNotes: [{
name: 'hero',
acting: 'angry',
}],
})
const merged = mergeAIDataModalDraftStateByDirty(
localDraft,
serverDraft,
new Set(['videoPrompt']),
)
expect(merged.videoPrompt).toBe('D')
expect(merged.photographyRules?.scene_summary).toBe('server scene')
expect(merged.photographyRules?.lighting.direction).toBe('back')
expect(merged.actingNotes[0]?.acting).toBe('angry')
})
})