121 lines
3.5 KiB
Go
121 lines
3.5 KiB
Go
package skills
|
|
|
|
import (
|
|
"encoding/json"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"infinite-canvas/backend/internal/model"
|
|
"infinite-canvas/backend/internal/repository"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestBuiltinSeedSyncPreservesUserState(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "skills.db")), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sqlDB, err := db.DB()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() {
|
|
if err := sqlDB.Close(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
if err := db.AutoMigrate(&model.Skill{}, &model.UserSkillState{}, &model.SkillVersion{}, &model.SkillFile{}, &model.User{}, &model.UserIdentity{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
svc := New(repository.New(db), t.TempDir(), nil)
|
|
var definitions []builtinSkillDefinition
|
|
if err := json.Unmarshal(builtinSkillsJSON, &definitions); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
community := 0
|
|
for _, def := range definitions {
|
|
if def.OwnerUID == "" || def.OwnerUID != def.EffectiveUser.UID {
|
|
t.Fatalf("invalid author identity: %s", def.SkillID)
|
|
}
|
|
for _, stamp := range []int64{def.CreateTime, def.UpdateTime} {
|
|
if time.UnixMilli(stamp).Year() < 2020 || time.UnixMilli(stamp).After(time.Now().Add(24*time.Hour)) {
|
|
t.Fatalf("invalid millisecond timestamp for %s: %d", def.SkillID, stamp)
|
|
}
|
|
}
|
|
if def.OwnerUID == "community-itswyatt-k" {
|
|
community++
|
|
}
|
|
}
|
|
if community != 72 {
|
|
t.Fatalf("community skills = %d, want 72", community)
|
|
}
|
|
if err := svc.EnsureBuiltinSkills(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := svc.EnsureSkillPackages(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
state := model.UserSkillState{ID: "test-state", UserID: "test-user", SkillID: "16000000000001", Added: true, Liked: true}
|
|
if err := db.Create(&state).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := svc.EnsureBuiltinSkills(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := svc.EnsureSkillPackages(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var count int64
|
|
if err := db.Model(&model.Skill{}).Count(&count).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if want := int64(len(definitions) + len(builtinImageEditingSkillDefinitions())); count != want {
|
|
t.Fatalf("seed count = %d, want %d", count, want)
|
|
}
|
|
var saved model.UserSkillState
|
|
if err := db.First(&saved, "id = ?", state.ID).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !saved.Added || !saved.Liked {
|
|
t.Fatalf("user state lost: %#v", saved)
|
|
}
|
|
var skill model.Skill
|
|
if err := db.First(&skill, "id = ?", state.SkillID).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if skill.OwnerID != "community-itswyatt-k" || skill.CreatedAt.Year() != 2026 {
|
|
t.Fatalf("invalid persisted seed: %#v", skill)
|
|
}
|
|
var persisted []model.Skill
|
|
if err := db.Find(&persisted).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, item := range persisted {
|
|
if item.CurrentVersionID == "" || item.FileCount != 1 {
|
|
t.Fatalf("skill %s has no initialized package", item.ID)
|
|
}
|
|
assertSkillVersionCount(t, db, item.ID, 1)
|
|
version, err := svc.repo.SkillVersion(item.CurrentVersionID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
body, err := svc.readSkillArchiveEntry(version, "SKILL.md")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if string(body) != item.Instruction {
|
|
t.Fatalf("skill %s package instruction was changed", item.ID)
|
|
}
|
|
}
|
|
list, err := svc.Skills("test-user", SkillListRequest{Scope: "public", Search: "freestyle-template-match"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if list.TotalCount != 1 || len(list.Skills) != 1 || list.Skills[0].SkillID != "16000000000003" {
|
|
t.Fatalf("community skill not visible in public search: %#v", list)
|
|
}
|
|
}
|