- Список: серверные фильтр по группе состояний, поиск и пагинация (GET
f/q/page/all, по 25), сортировка по времени добавления в qBittorrent
(added_on) с фолбеком на created_at и tie-break по id.
- Заголовок загрузки = имя раздачи (display_name) → распознанное название →
усечённый источник; сырой magnet вынесен в блок «Информация о торренте».
- Матч метабазы показан ссылкой на запись (страница загрузки и ревью);
URL берётся у выбранного кандидата либо строится по provider+id и типу.
- Полировка вёрстки; клиентская JS-фильтрация убрана (всё серверное, без JS).
- Миграция 0005 (display_name, source_added_at); воркер однократно
фиксирует source_added_at при поллинге/усыновлении; ER-схема обновлена.
- OpenSpec: дельты влиты в specs/{web-ui,ingest}, change заархивирован.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
59 lines
2.3 KiB
Go
59 lines
2.3 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.vakhrushev.me/av/jellybit/internal/store"
|
|
"git.vakhrushev.me/av/jellybit/internal/worker"
|
|
)
|
|
|
|
func TestProviderURL(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
provider string
|
|
id string
|
|
mtype string
|
|
want string
|
|
}{
|
|
{"tmdb movie", "tmdb", "693134", "movie", "https://www.themoviedb.org/movie/693134"},
|
|
{"tmdb series", "tmdb", "60622", "series", "https://www.themoviedb.org/tv/60622"},
|
|
{"tvdb series", "tvdb", "269613", "series", "https://www.thetvdb.com/dereferrer/series/269613"},
|
|
{"tvdb movie", "tvdb", "12345", "movie", "https://www.thetvdb.com/dereferrer/movie/12345"},
|
|
{"imdb", "imdb", "tt0111161", "movie", "https://www.imdb.com/title/tt0111161"},
|
|
{"unknown provider → пусто", "kinopoisk", "42", "movie", ""},
|
|
{"пустой id → пусто", "tmdb", "", "movie", ""},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
if got := providerURL(c.provider, c.id, c.mtype); got != c.want {
|
|
t.Errorf("providerURL(%q,%q,%q) = %q, want %q", c.provider, c.id, c.mtype, got, c.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMatchURLNoLinkWhenUnbuildable — эффективный провайдер, для которого URL не
|
|
// строится и совпадающего кандидата нет, даёт пустую ссылку (транспорт покажет
|
|
// матч текстом — сценарий «URL записи неизвестен»).
|
|
func TestMatchURLNoLinkWhenUnbuildable(t *testing.T) {
|
|
rd := &worker.ReviewData{Provider: "kinopoisk", ProviderID: "42"}
|
|
if got := matchURL(rd, "movie"); got != "" {
|
|
t.Errorf("matchURL = %q, want пусто (URL не строится, кандидата нет)", got)
|
|
}
|
|
}
|
|
|
|
// TestMatchURLPrefersMatchingCandidate — URL берётся у выбранного кандидата,
|
|
// когда его provider+id совпадают с эффективными.
|
|
func TestMatchURLPrefersMatchingCandidate(t *testing.T) {
|
|
rd := &worker.ReviewData{
|
|
Provider: "tmdb", ProviderID: "693134",
|
|
Candidates: []store.MetadataCandidate{{
|
|
Provider: "tmdb", ProviderID: "693134", Chosen: true,
|
|
URL: store.NullString("https://custom.example/x"),
|
|
}},
|
|
}
|
|
if got := matchURL(rd, "movie"); got != "https://custom.example/x" {
|
|
t.Errorf("matchURL = %q, want URL выбранного кандидата", got)
|
|
}
|
|
}
|