169 lines
5.0 KiB
Go
169 lines
5.0 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/ponzischeme89/memby/server/internal/config"
|
|
"github.com/ponzischeme89/memby/server/internal/library"
|
|
)
|
|
|
|
// recordingIngester stands in for the worker. The hook's whole job is to record, so what
|
|
// it recorded is the only thing worth asserting on here.
|
|
type recordingIngester struct {
|
|
sources []string
|
|
requests []library.IngestRequest
|
|
}
|
|
|
|
func (r *recordingIngester) Enqueue(
|
|
_ context.Context, source string, requests []library.IngestRequest,
|
|
) (int, error) {
|
|
r.sources = append(r.sources, source)
|
|
r.requests = append(r.requests, requests...)
|
|
return len(requests), nil
|
|
}
|
|
|
|
func sonarrHookRequest(body string) *http.Request {
|
|
return httptest.NewRequest(
|
|
http.MethodPost, "/hooks/sonarr?token=hook-secret", strings.NewReader(body))
|
|
}
|
|
|
|
func TestSonarrWebhookIsHiddenUntilATokenIsConfigured(t *testing.T) {
|
|
s := &Server{cfg: config.Config{}, log: discardLogger()}
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.handleSonarrWebhook(rec, sonarrHookRequest("{}"))
|
|
|
|
if rec.Code != http.StatusNotFound {
|
|
t.Fatalf("got %d, want 404 for an unconfigured hook", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestSonarrWebhookRejectsAWrongToken(t *testing.T) {
|
|
ingester := &recordingIngester{}
|
|
s := &Server{
|
|
cfg: config.Config{SonarrWebhookToken: "hook-secret"},
|
|
log: discardLogger(),
|
|
ingester: ingester,
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.handleSonarrWebhook(rec, httptest.NewRequest(
|
|
http.MethodPost, "/hooks/sonarr?token=guess", strings.NewReader("{}")))
|
|
|
|
if rec.Code != http.StatusUnauthorized {
|
|
t.Fatalf("got %d, want 401", rec.Code)
|
|
}
|
|
if len(ingester.requests) != 0 {
|
|
t.Fatal("an unauthorised delivery recorded work")
|
|
}
|
|
}
|
|
|
|
func TestSonarrWebhookRecordsAnImport(t *testing.T) {
|
|
ingester := &recordingIngester{}
|
|
s := &Server{
|
|
cfg: config.Config{SonarrWebhookToken: "hook-secret"},
|
|
log: discardLogger(),
|
|
ingester: ingester,
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.handleSonarrWebhook(rec, sonarrHookRequest(`{
|
|
"eventType":"Download",
|
|
"series":{"id":12,"title":"Blue Bloods","year":2010},
|
|
"episodes":[{"id":551,"seasonNumber":6,"episodeNumber":7}],
|
|
"episodeFile":{"id":8123}
|
|
}`))
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("got %d, want 200", rec.Code)
|
|
}
|
|
if len(ingester.requests) != 1 {
|
|
t.Fatalf("expected one recorded request, got %d", len(ingester.requests))
|
|
}
|
|
request := ingester.requests[0]
|
|
if request.Kind != library.KindEpisode || request.Episode != 7 || request.Season != 6 {
|
|
t.Fatalf("unexpected request: %+v", request)
|
|
}
|
|
if ingester.sources[0] != "sonarr" {
|
|
t.Fatalf("unexpected source: %q", ingester.sources[0])
|
|
}
|
|
}
|
|
|
|
// The Test button must answer without recording work about a series that does not exist.
|
|
func TestSonarrWebhookTestEventRecordsNothing(t *testing.T) {
|
|
ingester := &recordingIngester{}
|
|
s := &Server{
|
|
cfg: config.Config{SonarrWebhookToken: "hook-secret"},
|
|
log: discardLogger(),
|
|
ingester: ingester,
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.handleSonarrWebhook(rec, sonarrHookRequest(
|
|
`{"eventType":"Test","series":{"id":1,"title":"Test Title"}}`))
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("got %d, want 200", rec.Code)
|
|
}
|
|
if len(ingester.requests) != 0 {
|
|
t.Fatalf("the test event recorded work: %+v", ingester.requests)
|
|
}
|
|
}
|
|
|
|
// A Radarr upgrade is silent as news and still a reason to re-read the row. The two
|
|
// judgements are made in different places and this is what pins them apart.
|
|
func TestRadarrUpgradeIsRecordedThoughItIsNotAnnounced(t *testing.T) {
|
|
ingester := &recordingIngester{}
|
|
s := &Server{
|
|
cfg: config.Config{
|
|
RadarrWebhookToken: "hook-secret",
|
|
RadarrAlertWindow: 0, // no announcement is possible
|
|
},
|
|
log: discardLogger(),
|
|
ingester: ingester,
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.handleRadarrWebhook(rec, httptest.NewRequest(
|
|
http.MethodPost, "/hooks/radarr?token=hook-secret", strings.NewReader(`{
|
|
"eventType":"Download","isUpgrade":true,
|
|
"movie":{"id":44,"title":"Arrival","year":2016},
|
|
"movieFile":{"id":441,"quality":"Bluray-1080p"}
|
|
}`)))
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("got %d, want 200", rec.Code)
|
|
}
|
|
if len(ingester.requests) != 1 {
|
|
t.Fatalf("the upgrade was not recorded: %+v", ingester.requests)
|
|
}
|
|
if ingester.requests[0].Reason != library.ReasonUpgrade {
|
|
t.Fatalf("unexpected reason: %q", ingester.requests[0].Reason)
|
|
}
|
|
if ingester.requests[0].Action != library.ActionRefresh {
|
|
t.Fatalf("an upgrade must refresh, got %q", ingester.requests[0].Action)
|
|
}
|
|
}
|
|
|
|
// A grab is a real event and not a reason to re-read anything.
|
|
func TestSonarrGrabRecordsNothing(t *testing.T) {
|
|
ingester := &recordingIngester{}
|
|
s := &Server{
|
|
cfg: config.Config{SonarrWebhookToken: "hook-secret"},
|
|
log: discardLogger(),
|
|
ingester: ingester,
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
|
|
s.handleSonarrWebhook(rec, sonarrHookRequest(
|
|
`{"eventType":"Grab","series":{"id":12,"title":"Blue Bloods"}}`))
|
|
|
|
if rec.Code != http.StatusOK || len(ingester.requests) != 0 {
|
|
t.Fatalf("got %d with %d requests", rec.Code, len(ingester.requests))
|
|
}
|
|
}
|