src/server/internal/character/store_test.go
4,156 bytes · 159 lines · capsule://quake0day/[email protected]
raw on github
package character
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
)
func TestLoadLegacyCharacterStripsAvatarModelOnSave(t *testing.T) {
baseDir := t.TempDir()
charID := "123e4567-e89b-12d3-a456-426614174000"
charDir := filepath.Join(baseDir, charDirName("Legacy", charID))
if err := os.MkdirAll(charDir, 0755); err != nil {
t.Fatal(err)
}
legacy := map[string]any{
"id": charID,
"name": "Legacy",
"description": "legacy payload",
"avatar_image": "",
"use_face_crop": false,
"voice_provider": "doubao",
"voice_type": "温柔文雅",
"avatar_model": "flash_head",
"speaking_style": "平静",
"personality": "稳定",
"welcome_message": "你好",
"system_prompt": "legacy system prompt",
"tags": []string{"legacy"},
"images": []any{},
"active_image": "",
"image_mode": "fixed",
"created_at": "2026-04-18T00:00:00Z",
"updated_at": "2026-04-18T00:00:00Z",
}
data, err := json.MarshalIndent(legacy, "", " ")
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(charDir, "character.json"), data, 0644); err != nil {
t.Fatal(err)
}
store, err := NewStore(baseDir)
if err != nil {
t.Fatal(err)
}
char, err := store.Get(charID)
if err != nil {
t.Fatal(err)
}
if char.Name != "Legacy" {
t.Fatalf("expected Legacy, got %q", char.Name)
}
updated := &Character{
Name: char.Name,
Description: "updated legacy payload",
AvatarImage: char.AvatarImage,
UseFaceCrop: char.UseFaceCrop,
VoiceProvider: char.VoiceProvider,
VoiceType: char.VoiceType,
SpeakingStyle: char.SpeakingStyle,
Personality: char.Personality,
WelcomeMessage: char.WelcomeMessage,
SystemPrompt: char.SystemPrompt,
Tags: append([]string(nil), char.Tags...),
ImageMode: char.ImageMode,
}
if _, err := store.Update(charID, updated); err != nil {
t.Fatal(err)
}
saved, err := os.ReadFile(filepath.Join(charDir, "character.json"))
if err != nil {
t.Fatal(err)
}
if strings.Contains(string(saved), "\"avatar_model\"") {
t.Fatalf("expected saved character.json to omit avatar_model, got %s", string(saved))
}
var savedJSON map[string]any
if err := json.Unmarshal(saved, &savedJSON); err != nil {
t.Fatal(err)
}
if _, ok := savedJSON["avatar_model"]; ok {
t.Fatalf("expected avatar_model to be removed from saved JSON")
}
}
func TestIdleVideoFilenameIncludesResolutionVariant(t *testing.T) {
store, err := NewStore(t.TempDir())
if err != nil {
t.Fatal(err)
}
got := store.IdleVideoFilename("img_003.png", DefaultIdleVideoProfile)
want := "img_003__breathing10s_v1.mp4"
if got != want {
t.Fatalf("expected %q, got %q", want, got)
}
}
func TestActivateImageMovesImageFirstAndUpdatesAvatarCover(t *testing.T) {
store, err := NewStore(t.TempDir())
if err != nil {
t.Fatal(err)
}
char, err := store.Create(&Character{
Name: "Avatar Order",
VoiceType: "温柔文雅",
})
if err != nil {
t.Fatal(err)
}
for _, filename := range []string{"img_001.png", "img_002.png", "img_003.png"} {
if err := store.AddImage(char.ID, ImageInfo{
Filename: filename,
OrigName: filename,
AddedAt: "1",
}); err != nil {
t.Fatal(err)
}
}
if err := store.ActivateImage(char.ID, "img_003.png"); err != nil {
t.Fatal(err)
}
updated, err := store.Get(char.ID)
if err != nil {
t.Fatal(err)
}
if updated.ActiveImage != "img_003.png" {
t.Fatalf("expected active image img_003.png, got %q", updated.ActiveImage)
}
wantCover := "/api/v1/characters/" + char.ID + "/images/img_003.png"
if updated.AvatarImage != wantCover {
t.Fatalf("expected avatar cover %q, got %q", wantCover, updated.AvatarImage)
}
if len(updated.Images) == 0 || updated.Images[0].Filename != "img_003.png" {
t.Fatalf("expected active image first in stored order, got %#v", updated.Images)
}
imgs, err := store.ListImages(char.ID)
if err != nil {
t.Fatal(err)
}
if len(imgs) != 3 || imgs[0].Filename != "img_003.png" {
t.Fatalf("expected active image first in list response, got %#v", imgs)
}
}