package main import ( "strings" "testing" "time" "github.com/stretchr/testify/require" "gitea.d-ma.be/mathias/tapir/internal/adapters/store" ) func TestFormatListColumnsAndOrdering(t *testing.T) { rows := []store.SummaryRow{ { VideoID: "vid-newer", Title: "Newer Title", Channel: "youtube", AIProvider: "anthropic", PublishedAt: time.Date(2026, 2, 1, 0, 0, 0, 0, time.UTC), }, { VideoID: "vid-older", Title: "Older Title", Channel: "youtube", AIProvider: "local", FallbackUsed: true, PublishedAt: time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC), }, } var b strings.Builder require.NoError(t, formatList(&b, rows)) out := b.String() require.Contains(t, out, "DATE") require.Contains(t, out, "TITLE") require.Contains(t, out, "CHANNEL") require.Contains(t, out, "FALLBACK") require.Contains(t, out, "Newer Title") require.Contains(t, out, "2026-02-01") require.Contains(t, out, "anthropic") // formatList preserves caller ordering (the store query sorts recent-first). require.Less(t, strings.Index(out, "Newer Title"), strings.Index(out, "Older Title")) // fallback flag rendered per row. older := lineContaining(t, out, "Older Title") require.Contains(t, older, "yes") newer := lineContaining(t, out, "Newer Title") require.Contains(t, newer, "no") } func TestFormatListFallsBackToVideoIDWhenNoTitle(t *testing.T) { rows := []store.SummaryRow{{VideoID: "raw-video-id", CreatedAt: time.Date(2026, 3, 1, 0, 0, 0, 0, time.UTC)}} var b strings.Builder require.NoError(t, formatList(&b, rows)) out := b.String() require.Contains(t, out, "raw-video-id", "missing title falls back to video id") require.Contains(t, out, "2026-03-01", "missing publish date falls back to created_at") } func TestFormatListEmpty(t *testing.T) { var b strings.Builder require.NoError(t, formatList(&b, nil)) require.Contains(t, b.String(), "no summaries yet") } func TestFormatShowFullSummary(t *testing.T) { row := store.SummaryRow{ VideoID: "vid-1", Title: "Deep Dive", Channel: "youtube", URL: "https://example/watch", PublishedAt: time.Date(2026, 5, 2, 0, 0, 0, 0, time.UTC), Summary: "The core argument.", Highlights: []string{"first point", "second point"}, Takeaways: []string{"do this"}, AIProvider: "local", AIModel: "qwen", FallbackUsed: true, } var b strings.Builder require.NoError(t, formatShow(&b, row)) out := b.String() require.Contains(t, out, "Deep Dive") require.Contains(t, out, "2026-05-02") require.Contains(t, out, "https://example/watch") require.Contains(t, out, "vid-1") require.Contains(t, out, "local/qwen") require.Contains(t, out, "fallback") require.Contains(t, out, "The core argument.") require.Contains(t, out, "first point") require.Contains(t, out, "second point") require.Contains(t, out, "do this") } func TestFormatShowOmitsEmptySections(t *testing.T) { row := store.SummaryRow{ VideoID: "vid-2", Summary: "Body only.", AIProvider: "local", } var b strings.Builder require.NoError(t, formatShow(&b, row)) out := b.String() require.Contains(t, out, "vid-2", "no title -> falls back to video id") require.Contains(t, out, "Body only.") require.NotContains(t, out, "Highlights:") require.NotContains(t, out, "Takeaways:") require.NotContains(t, out, "URL:") require.NotContains(t, out, "Channel:") } func lineContaining(t *testing.T, text, needle string) string { t.Helper() for _, ln := range strings.Split(text, "\n") { if strings.Contains(ln, needle) { return ln } } t.Fatalf("no line containing %q in:\n%s", needle, text) return "" }