5b: connected users get a 'Summarize any video' URL input on the feed; submit posts to /paste (HTMX) and swaps the resulting card / inline error into the feed. 7: the connect flash now sets expectations for the async onboarding burst — 'finding your subscriptions, your newest videos will appear below as summarized'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
2.4 KiB
Go
81 lines
2.4 KiB
Go
package web
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"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).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")
|
|
}
|
|
}
|