Files
plezy/test/utils/external_season_ref_test.dart
T
edde746 0eee9f688d fix(explore): match sequel catalog entries to their parent library show
MAL/AniList season entries never matched the library show they belong to.
Both backends use the catalog title as a server-side filter before verifying
external ids, and a title like "Mushoku Tensei: Jobless Reincarnation Season 2"
cannot reach a show stored as "Mushoku Tensei: Jobless Reincarnation". Measured
against a 267-show Plex library, 3 of 113 mapped sequel entries matched.

The reverse lookup now takes two ordered title candidates instead of one: the
entry's own title and its season-stripped form, with typographic punctuation
normalised because both servers miss on a curly apostrophe. That matches 77 of
113. Widening it further to romaji/native/synonym variants reached only 81, so
the cap stays at two rather than spending up to five more requests per lookup
that finds nothing.

A sequel's year is its own season's, not the parent show's, so the +/-1 year
window is dropped for one - it would exclude the very show being looked for.
That also keeps a miss at the two requests the single-title lookup already
spent. A Plex Discover item additionally skips the title search entirely by
filtering on the plex:// guid its own rating key already is, which costs no
extra request and needs no cloud lookup.

A season 2+ entry only matches when the server really has that season, which
costs one children fetch on a match. Only a season both TVDB and TMDB agree on
is gated: which provider a library numbers its seasons by is a server setting
no dataset supplies and none of it is inferable from the ids an item exposes,
so a disagreeing reference is left ungated rather than gated on a guess.

The match cache is keyed per source and per entry rather than by canonical id,
which every season of a series shares: all five Mushoku Tensei entries collapse
to imdb:tt13293588, so one season-gated result would have poisoned the rest.

Entries whose Fribb row carries no provider id at all remain unmatched. That is
an upstream mapping gap, not something to guess around with extra lookups.

close #1704
2026-07-29 01:35:35 +02:00

38 lines
1.8 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:plezy/utils/external_ids.dart';
void main() {
group('ExternalSeasonRef.agreedSeason', () {
test('resolves only when both providers mapped the season and agree', () {
expect(const ExternalSeasonRef(tvdb: 3, tmdb: 3).agreedSeason, 3);
// Fribb maps "You and I Are Polar Opposites Season 2" to TVDB season 2
// but TMDB season 1 (a continuation at an episode offset). Which one a
// library follows is a server setting, so there is no honest answer.
expect(const ExternalSeasonRef(tvdb: 2, tmdb: 1).agreedSeason, isNull);
});
test('a missing number is not agreement', () {
// Absence means Fribb has no mapping for that provider, so a server
// ordered by it would number the season by data we do not have.
expect(const ExternalSeasonRef(tvdb: 2).agreedSeason, isNull);
expect(const ExternalSeasonRef(tmdb: 2).agreedSeason, isNull);
expect(const ExternalSeasonRef().agreedSeason, isNull);
});
test('isSequel stays knowable even when the numbers disagree', () {
// The gate cannot resolve this ref, but the year window still must be
// dropped: a sequel's catalog year is its own, not the parent show's.
expect(const ExternalSeasonRef(tvdb: 2, tmdb: 1).isSequel, isTrue);
expect(const ExternalSeasonRef(tvdb: 1, tmdb: 1).isSequel, isFalse);
expect(const ExternalSeasonRef(tmdb: 4).isSequel, isTrue);
expect(const ExternalSeasonRef().isSequel, isFalse);
});
test('round-trips through JSON', () {
const ref = ExternalSeasonRef(tvdb: 2, tmdb: 1);
expect(ExternalSeasonRef.fromJson(ref.toJson()), ref);
expect(ExternalSeasonRef.fromJson(const ExternalSeasonRef().toJson()).hasAny, isFalse);
});
});
}