Files
waoowaoo/tests/unit/optimistic/panel-save-coordinator.test.ts

90 lines
2.7 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import type { PanelEditData } from '@/app/[locale]/workspace/[projectId]/modes/novel-promotion/components/PanelEditForm'
import {
PanelSaveCoordinator,
type PanelSaveState,
} from '@/app/[locale]/workspace/[projectId]/modes/novel-promotion/components/storyboard/hooks/panel-save-coordinator'
function buildSnapshot(description: string): PanelEditData {
return {
id: 'panel-1',
panelIndex: 0,
panelNumber: 1,
shotType: 'close-up',
cameraMove: 'push',
description,
location: null,
characters: [],
srtStart: null,
srtEnd: null,
duration: null,
videoPrompt: null,
}
}
describe('PanelSaveCoordinator', () => {
it('keeps single-flight and only flushes the latest snapshot after burst edits', async () => {
const savedDescriptions: string[] = []
let releaseFirstAttempt: () => void = () => {}
const firstAttemptGate = new Promise<void>((resolve) => {
releaseFirstAttempt = () => resolve()
})
let attempts = 0
const coordinator = new PanelSaveCoordinator({
onSavingChange: () => {},
onStateChange: () => {},
runSave: async ({ snapshot }) => {
attempts += 1
if (attempts === 1) {
await firstAttemptGate
}
savedDescriptions.push(snapshot.description ?? '')
},
resolveErrorMessage: () => 'save failed',
})
const firstRun = coordinator.queue('panel-1', 'storyboard-1', buildSnapshot('v1'))
coordinator.queue('panel-1', 'storyboard-1', buildSnapshot('v2'))
coordinator.queue('panel-1', 'storyboard-1', buildSnapshot('v3'))
releaseFirstAttempt()
await firstRun
expect(savedDescriptions).toEqual(['v1', 'v3'])
})
it('marks error on failure and clears unsaved state after retry success', async () => {
const stateByPanel = new Map<string, PanelSaveState>()
let attemptCount = 0
const coordinator = new PanelSaveCoordinator({
onSavingChange: () => {},
onStateChange: (panelId, state) => {
stateByPanel.set(panelId, state)
},
runSave: async () => {
attemptCount += 1
if (attemptCount === 1) {
throw new Error('network timeout')
}
},
resolveErrorMessage: (error) => (error instanceof Error ? error.message : 'unknown'),
})
const firstRun = coordinator.queue('panel-1', 'storyboard-1', buildSnapshot('draft text'))
await firstRun
expect(stateByPanel.get('panel-1')).toEqual({
status: 'error',
errorMessage: 'network timeout',
})
const retryRun = coordinator.retry('panel-1', buildSnapshot('draft text'))
await retryRun
expect(stateByPanel.get('panel-1')).toEqual({
status: 'idle',
errorMessage: null,
})
})
})