video manage-workers modal: TVDB defaults to Shows, not an empty Movies view

TVDB enriches shows only, but selectWorker hardcoded state.kind='movie', so
picking TVDB queried tvdb+movie (always empty) and rendered a bogus Movies
view. Each worker now declares its kinds (tmdb: movie+show, tvdb: show) and the
panel defaults to the worker's first kind. Backend was already safe (returns
empty for unsupported service+kind); pinned that invariant with a seam test.
This commit is contained in:
BoulderBadgeDad 2026-06-14 13:50:49 -07:00
parent a62e59dd3a
commit daecf9dfae
3 changed files with 33 additions and 3 deletions

View file

@ -394,6 +394,17 @@ def test_enrichment_breakdown_unmatched_retry(db):
assert db.enrichment_breakdown("tmdb")["movie"]["pending"] == 1
def test_tvdb_is_shows_only(db):
# TVDB enriches shows, never movies. The breakdown must not advertise a
# movie bucket, and asking for tvdb movies returns empty (never garbage) —
# this is what keeps the Manage-Workers modal from showing a Movies view
# for TVDB.
assert "movie" not in db.enrichment_breakdown("tvdb")
assert "show" in db.enrichment_breakdown("tvdb")
db.upsert_movie("plex", {"server_id": "m1", "title": "A"})
assert db.enrichment_unmatched("tvdb", "movie") == {"items": [], "total": 0}
# ── isolation: the video DB imports nothing from music ───────────────────────
def test_video_db_module_imports_nothing_from_music():

View file

@ -280,6 +280,13 @@ def test_video_enrichment_manager_isolated():
assert "enrichment-manager-modal" in src and "em-rail" in src
# Its own overlay id (not music's) so the two never collide.
assert "vem-overlay" in src and "enrichment-manager-overlay" not in src
# TVDB is shows-only: each worker declares its kinds and the panel defaults
# to the worker's first kind — never a hardcoded 'movie' (which would show a
# bogus empty Movies view for TVDB).
assert "kinds: ['show']" in src # tvdb
assert "kinds: ['movie', 'show']" in src # tmdb
assert "state.kind = defaultKind(id)" in src
assert "state.kind = 'movie'" not in src
def test_video_settings_module_referenced_and_isolated():

View file

@ -11,10 +11,22 @@
(function () {
'use strict';
// `kinds` = the entity kinds each service actually enriches (must match the
// backend's _ENRICH map). TVDB is shows-only, so it must NOT default to the
// Movies view — it would query tvdb+movie (always empty) and look broken.
var WORKERS = [
{ id: 'tmdb', name: 'TMDB', color: '#38bdf8', rgb: '56, 189, 248' },
{ id: 'tvdb', name: 'TVDB', color: '#a855f7', rgb: '168, 85, 247' },
{ id: 'tmdb', name: 'TMDB', color: '#38bdf8', rgb: '56, 189, 248', kinds: ['movie', 'show'] },
{ id: 'tvdb', name: 'TVDB', color: '#a855f7', rgb: '168, 85, 247', kinds: ['show'] },
];
function workerDef(id) {
for (var i = 0; i < WORKERS.length; i++) { if (WORKERS[i].id === id) return WORKERS[i]; }
return null;
}
function defaultKind(id) {
var w = workerDef(id);
return (w && w.kinds && w.kinds[0]) || 'movie';
}
var LOGOS = {
tmdb: 'https://www.themoviedb.org/assets/2/v4/logos/v2/blue_square_2-d537fb228cf3ded904ef09b136fe3fec72548ebc1fea3fbbd1ad9e36364db38b.svg',
tvdb: 'https://www.svgrepo.com/show/443500/brand-tvdb.svg',
@ -224,7 +236,7 @@
// ── selection / actions ────────────────────────────────────────────────────
function selectWorker(id) {
state.selected = id; state.breakdown = null; state.unmatched = null;
state.kind = 'movie'; state.page = 0;
state.kind = defaultKind(id); state.page = 0;
renderRail(); renderPanel();
Promise.all([loadBreakdown(id), loadUnmatched()]).then(function () { renderPanel(); });
}