owpengram-server/internal/store/memory/themes_test.go

109 lines
3.3 KiB
Go

package memory
import (
"context"
"errors"
"testing"
"telesrv/internal/domain"
)
func sampleTheme(id, creator int64, slug string) domain.Theme {
return domain.Theme{
ID: id,
AccessHash: id + 1,
CreatorUserID: creator,
Slug: slug,
Title: "T",
DocumentID: 9000 + id,
Settings: []domain.ThemeSettingsSpec{{
BaseTheme: domain.ThemeBaseDay,
AccentColor: 0x112233,
MessageColors: []int{0xaa, 0xbb},
Wallpaper: &domain.ThemeWallpaperSpec{BackgroundColors: []int{0x1, 0x2}},
}},
CreatedAt: 1700000000,
}
}
func TestMemoryThemeStoreContract(t *testing.T) {
ctx := context.Background()
s := NewThemeStore()
// 未命中读 → (zero,false,nil)。
if _, ok, err := s.GetThemeByID(ctx, 1); ok || err != nil {
t.Fatalf("get missing = ok %v err %v", ok, err)
}
a := sampleTheme(101, 7, "alpha")
if err := s.CreateTheme(ctx, a); err != nil {
t.Fatalf("create a: %v", err)
}
// slug 冲突。
if err := s.CreateTheme(ctx, sampleTheme(102, 7, "alpha")); !errors.Is(err, domain.ErrThemeSlugTaken) {
t.Fatalf("dup slug err = %v, want ErrThemeSlugTaken", err)
}
got, ok, err := s.GetThemeByID(ctx, 101)
if err != nil || !ok {
t.Fatalf("get a by id = ok %v err %v", ok, err)
}
if got.Slug != "alpha" || len(got.Settings) != 1 || got.Settings[0].BaseTheme != domain.ThemeBaseDay {
t.Fatalf("round-trip mismatch: %+v", got)
}
// Clone 隔离:改返回值不污染内部。
got.Settings[0].MessageColors[0] = 0xffff
if again, _, _ := s.GetThemeByID(ctx, 101); again.Settings[0].MessageColors[0] != 0xaa {
t.Fatalf("clone leak: internal mutated to %#x", again.Settings[0].MessageColors[0])
}
if bySlug, ok, _ := s.GetThemeBySlug(ctx, "alpha"); !ok || bySlug.ID != 101 {
t.Fatalf("get by slug = ok %v id %d", ok, bySlug.ID)
}
// update 不存在 → ErrThemeNotFound。
if err := s.UpdateTheme(ctx, sampleTheme(999, 7, "ghost")); !errors.Is(err, domain.ErrThemeNotFound) {
t.Fatalf("update missing err = %v, want ErrThemeNotFound", err)
}
// IncrementInstalls。
if err := s.IncrementInstalls(ctx, 101); err != nil {
t.Fatalf("increment: %v", err)
}
if got, _, _ := s.GetThemeByID(ctx, 101); got.InstallsCount != 1 {
t.Fatalf("installs = %d, want 1", got.InstallsCount)
}
// 安装列表顺序按安装先后。
b := sampleTheme(103, 7, "beta")
if err := s.CreateTheme(ctx, b); err != nil {
t.Fatalf("create b: %v", err)
}
const user = int64(55)
if err := s.SetInstalled(ctx, user, 103, false); err != nil {
t.Fatalf("install 103: %v", err)
}
if err := s.SetInstalled(ctx, user, 101, true); err != nil {
t.Fatalf("install 101: %v", err)
}
list, err := s.ListInstalledByUser(ctx, user)
if err != nil || len(list) != 2 {
t.Fatalf("list installed = %d err %v, want 2", len(list), err)
}
if list[0].ID != 103 || list[1].ID != 101 {
t.Fatalf("install order = [%d,%d], want [103,101]", list[0].ID, list[1].ID)
}
// 移除。
if err := s.RemoveInstalled(ctx, user, 103); err != nil {
t.Fatalf("remove: %v", err)
}
if list, _ := s.ListInstalledByUser(ctx, user); len(list) != 1 || list[0].ID != 101 {
t.Fatalf("after remove = %+v, want [101]", list)
}
// 安装不存在的主题 → ErrThemeNotFound。
if err := s.SetInstalled(ctx, user, 88888, false); !errors.Is(err, domain.ErrThemeNotFound) {
t.Fatalf("install missing theme err = %v, want ErrThemeNotFound", err)
}
}