0.2.76 - Icon Packs
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
package library
|
||||
|
||||
import "testing"
|
||||
|
||||
func sonarrDownload(upgrade bool) SonarrWebhook {
|
||||
var payload SonarrWebhook
|
||||
payload.EventType = "Download"
|
||||
payload.IsUpgrade = upgrade
|
||||
payload.Series.ID = 12
|
||||
payload.Series.Title = "Blue Bloods"
|
||||
payload.Series.Year = 2010
|
||||
payload.EpisodeFile.ID = 8123
|
||||
payload.Episodes = append(payload.Episodes, struct {
|
||||
ID int `json:"id"`
|
||||
SeasonNumber int `json:"seasonNumber"`
|
||||
EpisodeNumber int `json:"episodeNumber"`
|
||||
}{ID: 551, SeasonNumber: 6, EpisodeNumber: 7})
|
||||
return payload
|
||||
}
|
||||
|
||||
func TestSonarrImportBecomesOneEpisodeRefresh(t *testing.T) {
|
||||
requests := SonarrRequests(sonarrDownload(false))
|
||||
if len(requests) != 1 {
|
||||
t.Fatalf("expected one request, got %d", len(requests))
|
||||
}
|
||||
request := requests[0]
|
||||
if request.Action != ActionRefresh || request.Kind != KindEpisode {
|
||||
t.Fatalf("unexpected shape: %+v", request)
|
||||
}
|
||||
if request.Reason != ReasonImport {
|
||||
t.Fatalf("expected an import, got %q", request.Reason)
|
||||
}
|
||||
if request.Series != "Blue Bloods" || request.Season != 6 || request.Episode != 7 {
|
||||
t.Fatalf("unexpected identity: %+v", request)
|
||||
}
|
||||
}
|
||||
|
||||
// An upgrade is silent as *news* and is still a reason to re-read the row: the file
|
||||
// genuinely changed. Conflating those two judgements is how a replaced file would keep a
|
||||
// catalogue entry describing the copy it replaced.
|
||||
func TestSonarrUpgradeStillRefreshes(t *testing.T) {
|
||||
requests := SonarrRequests(sonarrDownload(true))
|
||||
if len(requests) != 1 || requests[0].Reason != ReasonUpgrade {
|
||||
t.Fatalf("expected one upgrade refresh, got %+v", requests)
|
||||
}
|
||||
if requests[0].Action != ActionRefresh {
|
||||
t.Fatalf("an upgrade must refresh, got %q", requests[0].Action)
|
||||
}
|
||||
}
|
||||
|
||||
// The key names the file, so two deliveries of one import are one piece of work. Both
|
||||
// *arrs re-notify on retry and neither promises exactly-once.
|
||||
func TestRepeatedDeliveryKeepsOneKey(t *testing.T) {
|
||||
first := SonarrRequests(sonarrDownload(false))
|
||||
second := SonarrRequests(sonarrDownload(false))
|
||||
if first[0].Key != second[0].Key {
|
||||
t.Fatalf("the same import produced two keys: %q and %q", first[0].Key, second[0].Key)
|
||||
}
|
||||
// A different file for the same episode is different work, or a replacement would be
|
||||
// swallowed by the row its predecessor left behind.
|
||||
replaced := sonarrDownload(true)
|
||||
replaced.EpisodeFile.ID = 9001
|
||||
if SonarrRequests(replaced)[0].Key == first[0].Key {
|
||||
t.Fatal("a replacement file must not reuse the previous file's key")
|
||||
}
|
||||
}
|
||||
|
||||
// A multi-episode file names several episodes and each is its own row, because each may
|
||||
// well be delivered again on its own.
|
||||
func TestSonarrMultiEpisodeFileProducesOneRequestEach(t *testing.T) {
|
||||
payload := sonarrDownload(false)
|
||||
payload.Episodes = append(payload.Episodes, struct {
|
||||
ID int `json:"id"`
|
||||
SeasonNumber int `json:"seasonNumber"`
|
||||
EpisodeNumber int `json:"episodeNumber"`
|
||||
}{ID: 552, SeasonNumber: 6, EpisodeNumber: 8})
|
||||
requests := SonarrRequests(payload)
|
||||
if len(requests) != 2 {
|
||||
t.Fatalf("expected two requests, got %d", len(requests))
|
||||
}
|
||||
if requests[0].Key == requests[1].Key {
|
||||
t.Fatal("two episodes of one file collapsed onto one key")
|
||||
}
|
||||
}
|
||||
|
||||
// A rename is series-wide because Sonarr does not say which episode each moved file held,
|
||||
// and it is a refresh rather than an invalidation: the Emby id survives a move.
|
||||
func TestSonarrRenameRefreshesTheSeries(t *testing.T) {
|
||||
var payload SonarrWebhook
|
||||
payload.EventType = "Rename"
|
||||
payload.Series.ID = 12
|
||||
payload.Series.Title = "Blue Bloods"
|
||||
requests := SonarrRequests(payload)
|
||||
if len(requests) != 1 {
|
||||
t.Fatalf("expected one request, got %d", len(requests))
|
||||
}
|
||||
if requests[0].Kind != KindSeries || requests[0].Action != ActionRefresh {
|
||||
t.Fatalf("unexpected shape: %+v", requests[0])
|
||||
}
|
||||
if requests[0].Reason != ReasonRename {
|
||||
t.Fatalf("expected a rename, got %q", requests[0].Reason)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSonarrEpisodeDeleteRemovesThatEpisode(t *testing.T) {
|
||||
payload := sonarrDownload(false)
|
||||
payload.EventType = "EpisodeFileDelete"
|
||||
requests := SonarrRequests(payload)
|
||||
if len(requests) != 1 || requests[0].Action != ActionRemove {
|
||||
t.Fatalf("expected one removal, got %+v", requests)
|
||||
}
|
||||
if requests[0].Season != 6 || requests[0].Episode != 7 {
|
||||
t.Fatalf("unexpected position: %+v", requests[0])
|
||||
}
|
||||
}
|
||||
|
||||
// A series removed from Sonarr's list while its files stay on disk is still in the
|
||||
// library. Only a delete that took the media with it removes anything.
|
||||
func TestSonarrSeriesDeleteOnlyCountsWhenFilesWent(t *testing.T) {
|
||||
var payload SonarrWebhook
|
||||
payload.EventType = "SeriesDelete"
|
||||
payload.Series.ID = 12
|
||||
payload.Series.Title = "Blue Bloods"
|
||||
|
||||
if requests := SonarrRequests(payload); len(requests) != 0 {
|
||||
t.Fatalf("an unfollowed series must not be removed: %+v", requests)
|
||||
}
|
||||
payload.DeletedFiles = true
|
||||
requests := SonarrRequests(payload)
|
||||
if len(requests) != 1 || requests[0].Action != ActionRemove || requests[0].Kind != KindSeries {
|
||||
t.Fatalf("expected a series removal, got %+v", requests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSonarrIgnoresEventsThatChangeNothing(t *testing.T) {
|
||||
for _, event := range []string{"Grab", "Health", "ApplicationUpdate", "", "ManualInteractionRequired"} {
|
||||
var payload SonarrWebhook
|
||||
payload.EventType = event
|
||||
payload.Series.Title = "Blue Bloods"
|
||||
if requests := SonarrRequests(payload); len(requests) != 0 {
|
||||
t.Fatalf("%q produced work: %+v", event, requests)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func radarrDownload(upgrade bool) RadarrWebhook {
|
||||
var payload RadarrWebhook
|
||||
payload.EventType = "Download"
|
||||
payload.IsUpgrade = upgrade
|
||||
payload.Movie.ID = 44
|
||||
payload.Movie.Title = "Arrival"
|
||||
payload.Movie.Year = 2016
|
||||
payload.MovieFile.ID = 441
|
||||
return payload
|
||||
}
|
||||
|
||||
func TestRadarrImportAndUpgradeBothRefresh(t *testing.T) {
|
||||
imported := RadarrRequests(radarrDownload(false))
|
||||
if len(imported) != 1 || imported[0].Reason != ReasonImport || imported[0].Kind != KindMovie {
|
||||
t.Fatalf("unexpected import: %+v", imported)
|
||||
}
|
||||
upgraded := RadarrRequests(radarrDownload(true))
|
||||
if len(upgraded) != 1 || upgraded[0].Reason != ReasonUpgrade {
|
||||
t.Fatalf("unexpected upgrade: %+v", upgraded)
|
||||
}
|
||||
// The two are separate work: an upgrade of a file already imported must not be
|
||||
// swallowed by the settled row its import left behind.
|
||||
if imported[0].Key == upgraded[0].Key {
|
||||
t.Fatal("an upgrade reused the import's key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRadarrDeleteReadsTheTopLevelFileID(t *testing.T) {
|
||||
var payload RadarrWebhook
|
||||
payload.EventType = "MovieFileDelete"
|
||||
payload.Movie.ID = 44
|
||||
payload.Movie.Title = "Arrival"
|
||||
payload.MovieFileID = 441
|
||||
requests := RadarrRequests(payload)
|
||||
if len(requests) != 1 || requests[0].Action != ActionRemove {
|
||||
t.Fatalf("expected one removal, got %+v", requests)
|
||||
}
|
||||
if requests[0].Key != "radarr:moviefile:441:delete" {
|
||||
t.Fatalf("unexpected key: %q", requests[0].Key)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRadarrMovieDeleteOnlyCountsWhenFilesWent(t *testing.T) {
|
||||
var payload RadarrWebhook
|
||||
payload.EventType = "MovieDelete"
|
||||
payload.Movie.ID = 44
|
||||
payload.Movie.Title = "Arrival"
|
||||
if requests := RadarrRequests(payload); len(requests) != 0 {
|
||||
t.Fatalf("an unmonitored film must not be removed: %+v", requests)
|
||||
}
|
||||
payload.DeletedFiles = true
|
||||
if requests := RadarrRequests(payload); len(requests) != 1 {
|
||||
t.Fatalf("expected a removal, got %+v", requests)
|
||||
}
|
||||
}
|
||||
|
||||
// The Test button must be answered without recording work about something that does not
|
||||
// exist, which is what makes it mean "reachable".
|
||||
func TestTestEventIsRecognisedFromEitherArr(t *testing.T) {
|
||||
if !IsTestEvent("Test") || !IsTestEvent(" test ") {
|
||||
t.Fatal("a test event was not recognised")
|
||||
}
|
||||
if IsTestEvent("Download") {
|
||||
t.Fatal("an import was read as a test")
|
||||
}
|
||||
var sonarrTest SonarrWebhook
|
||||
sonarrTest.EventType = "Test"
|
||||
sonarrTest.Series.Title = "Test Title"
|
||||
if requests := SonarrRequests(sonarrTest); len(requests) != 0 {
|
||||
t.Fatalf("the test event produced work: %+v", requests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizedTitleIgnoresPunctuationAndCase(t *testing.T) {
|
||||
if NormalizedTitle("Marvel's Daredevil") != NormalizedTitle("Marvels Daredevil") {
|
||||
t.Fatal("punctuation changed the answer")
|
||||
}
|
||||
if NormalizedTitle("The Pitt") != "thepitt" {
|
||||
t.Fatalf("unexpected normalisation: %q", NormalizedTitle("The Pitt"))
|
||||
}
|
||||
if NormalizedTitle(" ") != "" {
|
||||
t.Fatal("a blank title must normalise to nothing")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user