package web import ( "bytes" "context" "gitea.d-ma.be/mathias/tapir/internal/adapters/store" "strings" "testing" ) func TestParseYouTubeVideoID(t *testing.T) { const id = "dQw4w9WgXcQ" ok := []struct { name, in string }{ {"watch", "https://www.youtube.com/watch?v=" + id}, {"watch no www", "https://youtube.com/watch?v=" + id}, {"watch m", "https://m.youtube.com/watch?v=" + id}, {"watch extra params", "https://www.youtube.com/watch?v=" + id + "&t=42s&list=PLxyz"}, {"watch param after", "https://www.youtube.com/watch?list=PLxyz&v=" + id}, {"short link", "https://youtu.be/" + id}, {"short link param", "https://youtu.be/" + id + "?si=abcd&t=1"}, {"shorts", "https://www.youtube.com/shorts/" + id}, {"embed", "https://www.youtube.com/embed/" + id}, {"bare id", id}, {"http scheme", "http://youtube.com/watch?v=" + id}, {"no scheme", "youtube.com/watch?v=" + id}, {"trailing space", " https://youtu.be/" + id + " "}, } for _, c := range ok { t.Run(c.name, func(t *testing.T) { got, err := parseYouTubeVideoID(c.in) if err != nil { t.Fatalf("parseYouTubeVideoID(%q) error: %v", c.in, err) } if got != id { t.Fatalf("parseYouTubeVideoID(%q) = %q, want %q", c.in, got, id) } }) } bad := []struct { name, in string }{ {"empty", ""}, {"blank", " "}, {"vimeo", "https://vimeo.com/123456789"}, {"other host", "https://example.com/watch?v=" + id}, {"watch no id", "https://www.youtube.com/watch?v="}, {"short id", "https://youtu.be/abc"}, {"long id", "https://youtu.be/" + id + "extra"}, {"bad chars", "https://youtu.be/dQw4w9Wg!cQ"}, {"not a url", "just some text"}, {"channel url", "https://www.youtube.com/@somechannel"}, } for _, c := range bad { t.Run("reject "+c.name, func(t *testing.T) { if got, err := parseYouTubeVideoID(c.in); err == nil { t.Fatalf("parseYouTubeVideoID(%q) = %q, want error", c.in, got) } }) } } func TestListPageShowsPasteFormOnlyWhenConnected(t *testing.T) { render := func(connected bool) string { var buf bytes.Buffer if err := ListPage(listBuckets{}, Filter{}, PipelineStats{}, "", connected, nil, true).Render(context.Background(), &buf); err != nil { t.Fatalf("render: %v", err) } return buf.String() } html := render(true) if !strings.Contains(html, `name="url"`) || !strings.Contains(html, `action="/paste"`) { t.Errorf("connected feed must show the paste form") } if strings.Contains(render(false), `name="url"`) { t.Errorf("disconnected feed must not show the paste form") } } func TestFilterMatchesMultipleChannels(t *testing.T) { f := Filter{Channels: []string{"Acme", "Zeta"}} row := func(ch string) store.SummaryRow { return store.SummaryRow{ChannelTitle: ch, Summarized: true} } rows := []store.SummaryRow{row("Acme"), row("Beta"), row("Zeta")} got := f.apply(rows) if len(got) != 2 || got[0].ChannelTitle != "Acme" || got[1].ChannelTitle != "Zeta" { t.Fatalf("multi-channel filter = %+v, want Acme+Zeta only", got) } // Empty selection = no channel constraint (all pass). if n := len(Filter{}.apply(rows)); n != 3 { t.Fatalf("no channel filter should pass all rows, got %d", n) } }