88 lines
3.1 KiB
TypeScript
88 lines
3.1 KiB
TypeScript
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')
|
|
})
|
|
})
|