Files
minstrel/internal/playlists/collage_test.go
T
bvandeusen 79bab14b30 feat(playlists): track operations + cover-collage generator
AppendTracks / RemoveTrack / Reorder run in single transactions and
update the denormalized rollups (track_count, duration_sec). Reorder
uses a +10000 offset to bump every row out of the position range
before writing the new positions, sidestepping PK conflicts during
rewrite.

GenerateCollage composes a 600x600 JPEG from the first 4 album
covers, with a slate-tinted fallback for missing cells. Synchronous,
called inline after every mutating operation. SVG-rasterized fallback
is a follow-up — slice 1 ships with a solid placeholder.
2026-05-03 10:25:20 -04:00

76 lines
1.8 KiB
Go

package playlists_test
import (
"context"
"image"
_ "image/jpeg"
"os"
"path/filepath"
"testing"
"github.com/jackc/pgx/v5/pgtype"
"git.fabledsword.com/bvandeusen/minstrel/internal/playlists"
)
func TestGenerateCollage_EmptyPlaylist(t *testing.T) {
pool := newPool(t)
user := seedUser(t, pool, "alice")
dir := t.TempDir()
svc := playlists.NewService(pool, nil, dir)
pl, err := svc.Create(context.Background(), user.ID, "Empty", "", false)
if err != nil {
t.Fatalf("Create: %v", err)
}
relPath, err := playlists.GenerateCollage(context.Background(), pool, pl.ID, dir)
if err != nil {
t.Fatalf("GenerateCollage: %v", err)
}
if relPath != "" {
t.Errorf("relPath = %q, want \"\" for empty playlist", relPath)
}
}
func TestGenerateCollage_OneTrack(t *testing.T) {
pool := newPool(t)
user := seedUser(t, pool, "alice")
tk := seedTrack(t, pool, "Roygbiv", "BoC")
dir := t.TempDir()
svc := playlists.NewService(pool, nil, dir)
pl, err := svc.Create(context.Background(), user.ID, "One", "", false)
if err != nil {
t.Fatalf("Create: %v", err)
}
if err := svc.AppendTracks(context.Background(), user.ID, pl.ID, []pgtype.UUID{tk.ID}); err != nil {
t.Fatalf("AppendTracks: %v", err)
}
got, err := svc.Get(context.Background(), user.ID, pl.ID)
if err != nil {
t.Fatalf("Get: %v", err)
}
if got.CoverPath == nil || *got.CoverPath == "" {
t.Fatalf("CoverPath empty after append")
}
full := filepath.Join(dir, *got.CoverPath)
f, err := os.Open(full)
if err != nil {
t.Fatalf("open collage: %v", err)
}
defer f.Close()
img, format, err := image.Decode(f)
if err != nil {
t.Fatalf("decode collage: %v", err)
}
if format != "jpeg" {
t.Errorf("format = %q, want jpeg", format)
}
if img.Bounds().Dx() != 600 || img.Bounds().Dy() != 600 {
t.Errorf("dimensions = %dx%d, want 600x600", img.Bounds().Dx(), img.Bounds().Dy())
}
}