mirror of
https://github.com/MrSleeps/jellyfin-scene-search.git
synced 2026-11-14 22:11:27 +00:00
Test multi-library selection and reconciliation
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
from scene_search.cli import make_parser
|
||||
from scene_search.database import connect, init_db
|
||||
from scene_search.jellyfin_index import _reconcile_library, resolve_libraries
|
||||
|
||||
|
||||
class FakeJellyfinClient:
|
||||
def media_folders(self) -> list[dict]:
|
||||
return [
|
||||
{"Id": "lib-movies", "Name": "Movies"},
|
||||
{"Id": "lib-tv", "Name": "TV"},
|
||||
{"Id": "lib-home", "Name": "Home Videos"},
|
||||
]
|
||||
|
||||
|
||||
class MultiLibrarySelectionTests(unittest.TestCase):
|
||||
def test_all_libraries_can_exclude_named_library(self) -> None:
|
||||
client = FakeJellyfinClient()
|
||||
|
||||
with patch(
|
||||
"scene_search.jellyfin_index.settings",
|
||||
SimpleNamespace(
|
||||
jellyfin_exclude_libraries=(),
|
||||
jellyfin_libraries=(),
|
||||
jellyfin_library="",
|
||||
),
|
||||
):
|
||||
libraries = resolve_libraries(
|
||||
client, # type: ignore[arg-type]
|
||||
None,
|
||||
all_libraries=True,
|
||||
excluded=["TV"],
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
[library["Name"] for library in libraries],
|
||||
["Home Videos", "Movies"],
|
||||
)
|
||||
|
||||
def test_repeated_library_arguments_select_multiple(self) -> None:
|
||||
parser = make_parser()
|
||||
args = parser.parse_args(
|
||||
[
|
||||
"jellyfin-index",
|
||||
"--library",
|
||||
"Movies",
|
||||
"--library",
|
||||
"TV",
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(args.library, ["Movies", "TV"])
|
||||
self.assertFalse(args.all_libraries)
|
||||
|
||||
def test_requested_library_names_are_case_insensitive(self) -> None:
|
||||
client = FakeJellyfinClient()
|
||||
|
||||
with patch(
|
||||
"scene_search.jellyfin_index.settings",
|
||||
SimpleNamespace(
|
||||
jellyfin_exclude_libraries=(),
|
||||
jellyfin_libraries=(),
|
||||
jellyfin_library="",
|
||||
),
|
||||
):
|
||||
libraries = resolve_libraries(
|
||||
client, # type: ignore[arg-type]
|
||||
["movies", "HOME VIDEOS"],
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
[library["Name"] for library in libraries],
|
||||
["Home Videos", "Movies"],
|
||||
)
|
||||
|
||||
|
||||
class LibraryReconciliationTests(unittest.TestCase):
|
||||
def test_reconcile_only_prunes_stale_items_from_target_library(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
root = Path(tmp)
|
||||
db_path = root / "scenes.sqlite3"
|
||||
thumbs_dir = root / "thumbs"
|
||||
init_db(db_path)
|
||||
|
||||
rows = [
|
||||
("keep", "Keep", "jf-keep", "lib-a"),
|
||||
("stale", "Stale", "jf-stale", "lib-a"),
|
||||
("other", "Other", "jf-other", "lib-b"),
|
||||
]
|
||||
with connect(db_path) as con:
|
||||
for media_id, title, jellyfin_id, library_id in rows:
|
||||
con.execute(
|
||||
"""
|
||||
INSERT INTO media (
|
||||
id, source_path, title, content_sha256, size_bytes,
|
||||
mtime_ns, interval_ms, model_id, embedding_dim,
|
||||
source_kind, jellyfin_item_id, jellyfin_library_id
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
media_id,
|
||||
f"jellyfin://{jellyfin_id}",
|
||||
title,
|
||||
"hash",
|
||||
0,
|
||||
0,
|
||||
10000,
|
||||
"model",
|
||||
2,
|
||||
"jellyfin",
|
||||
jellyfin_id,
|
||||
library_id,
|
||||
),
|
||||
)
|
||||
folder = thumbs_dir / media_id
|
||||
folder.mkdir(parents=True)
|
||||
(folder / "frame.jpg").write_bytes(b"x")
|
||||
|
||||
fake_settings = SimpleNamespace(
|
||||
db_path=db_path,
|
||||
thumbs_dir=thumbs_dir,
|
||||
)
|
||||
with patch("scene_search.jellyfin_index.settings", fake_settings):
|
||||
pruned = _reconcile_library("lib-a", {"jf-keep"})
|
||||
|
||||
self.assertEqual(pruned, 1)
|
||||
with connect(db_path) as con:
|
||||
remaining = {
|
||||
row["id"]
|
||||
for row in con.execute("SELECT id FROM media").fetchall()
|
||||
}
|
||||
|
||||
self.assertEqual(remaining, {"keep", "other"})
|
||||
self.assertFalse((thumbs_dir / "stale").exists())
|
||||
self.assertTrue((thumbs_dir / "keep").exists())
|
||||
self.assertTrue((thumbs_dir / "other").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user