release: opensource snapshot 2026-02-27 19:25:00
This commit is contained in:
87
tests/unit/optimistic/panel-ai-data-sync.test.ts
Normal file
87
tests/unit/optimistic/panel-ai-data-sync.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
serializeStructuredJsonField,
|
||||
syncPanelCharacterDependentJson,
|
||||
} from '@/lib/novel-promotion/panel-ai-data-sync'
|
||||
|
||||
describe('panel ai data sync helpers', () => {
|
||||
it('removes deleted character from acting notes and photography rules', () => {
|
||||
const synced = syncPanelCharacterDependentJson({
|
||||
characters: [
|
||||
{ name: '楚江锴/当朝皇帝', appearance: '初始形象' },
|
||||
{ name: '燕画乔/魏画乔', appearance: '初始形象' },
|
||||
],
|
||||
removeIndex: 0,
|
||||
actingNotesJson: JSON.stringify([
|
||||
{ name: '楚江锴/当朝皇帝', acting: '紧握手腕' },
|
||||
{ name: '燕画乔/魏画乔', acting: '本能后退' },
|
||||
]),
|
||||
photographyRulesJson: JSON.stringify({
|
||||
lighting: {
|
||||
direction: '侧逆光',
|
||||
quality: '硬光',
|
||||
},
|
||||
characters: [
|
||||
{ name: '楚江锴/当朝皇帝', screen_position: 'left' },
|
||||
{ name: '燕画乔/魏画乔', screen_position: 'right' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
|
||||
expect(synced.characters).toEqual([{ name: '燕画乔/魏画乔', appearance: '初始形象' }])
|
||||
expect(JSON.parse(synced.actingNotesJson || 'null')).toEqual([
|
||||
{ name: '燕画乔/魏画乔', acting: '本能后退' },
|
||||
])
|
||||
expect(JSON.parse(synced.photographyRulesJson || 'null')).toEqual({
|
||||
lighting: {
|
||||
direction: '侧逆光',
|
||||
quality: '硬光',
|
||||
},
|
||||
characters: [
|
||||
{ name: '燕画乔/魏画乔', screen_position: 'right' },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps notes by character name when another appearance of same name remains', () => {
|
||||
const synced = syncPanelCharacterDependentJson({
|
||||
characters: [
|
||||
{ name: '顾娘子/顾盼之', appearance: '素衣' },
|
||||
{ name: '顾娘子/顾盼之', appearance: '华服' },
|
||||
],
|
||||
removeIndex: 1,
|
||||
actingNotesJson: JSON.stringify([
|
||||
{ name: '顾娘子/顾盼之', acting: '抬眼看向窗外' },
|
||||
]),
|
||||
photographyRulesJson: JSON.stringify({
|
||||
characters: [
|
||||
{ name: '顾娘子/顾盼之', screen_position: 'center' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
|
||||
expect(JSON.parse(synced.actingNotesJson || 'null')).toEqual([
|
||||
{ name: '顾娘子/顾盼之', acting: '抬眼看向窗外' },
|
||||
])
|
||||
expect(JSON.parse(synced.photographyRulesJson || 'null')).toEqual({
|
||||
characters: [
|
||||
{ name: '顾娘子/顾盼之', screen_position: 'center' },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it('supports double-serialized JSON string inputs', () => {
|
||||
const actingNotes = JSON.stringify([{ name: '甲', acting: '动作' }])
|
||||
const doubleSerialized = JSON.stringify(actingNotes)
|
||||
expect(serializeStructuredJsonField(doubleSerialized, 'actingNotes')).toBe(actingNotes)
|
||||
})
|
||||
|
||||
it('throws on malformed acting notes to avoid silent fallback', () => {
|
||||
expect(() => syncPanelCharacterDependentJson({
|
||||
characters: [{ name: '甲', appearance: '初始形象' }],
|
||||
removeIndex: 0,
|
||||
actingNotesJson: '[{"name":"甲","acting":"动作"}, {"acting":"缺少名字"}]',
|
||||
photographyRulesJson: null,
|
||||
})).toThrowError('actingNotes item.name must be a non-empty string')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user