feat: integrate NFO repair into scheduled folder scan

- Add FolderScanService.run_folder_scan() calling perform_nfo_repair_scan()
- Remove startup-time NFO repair from fastapi_app lifespan
- Update docs/NFO_GUIDE.md: repair now runs as part of daily scan
- Update tests to verify integration wiring
- Update ARCHITECTURE.md and scheduler_service for scan scheduling
This commit is contained in:
2026-05-12 20:15:32 +02:00
parent c39ae9d0fc
commit eb2fc3c5ab
7 changed files with 144 additions and 38 deletions

View File

@@ -1,46 +1,45 @@
"""Integration tests verifying perform_nfo_repair_scan is wired into app startup.
"""Integration tests verifying perform_nfo_repair_scan is wired into folder scan.
These tests confirm that:
1. The lifespan calls perform_nfo_repair_scan after perform_media_scan_if_needed.
2. Series with incomplete NFO files are queued via the background_loader.
1. FolderScanService.run_folder_scan calls perform_nfo_repair_scan.
2. Series with incomplete NFO files are queued via asyncio.create_task.
"""
from unittest.mock import AsyncMock, MagicMock, call, patch
import pytest
class TestNfoRepairScanCalledOnStartup:
"""Verify perform_nfo_repair_scan is invoked during the FastAPI lifespan."""
class TestNfoRepairScanCalledInFolderScan:
"""Verify perform_nfo_repair_scan is invoked from FolderScanService."""
def test_perform_nfo_repair_scan_imported_in_lifespan(self):
"""fastapi_app.py lifespan imports perform_nfo_repair_scan."""
def test_perform_nfo_repair_scan_imported_in_folder_scan_service(self):
"""folder_scan_service.py imports perform_nfo_repair_scan."""
import importlib
import src.server.fastapi_app as app_module
source = importlib.util.find_spec("src.server.fastapi_app").origin
source = importlib.util.find_spec("src.server.services.folder_scan_service").origin
with open(source, "r", encoding="utf-8") as fh:
content = fh.read()
assert "perform_nfo_repair_scan" in content, (
"perform_nfo_repair_scan must be imported and called in fastapi_app.py"
"perform_nfo_repair_scan must be imported in folder_scan_service.py"
)
def test_perform_nfo_repair_scan_called_after_media_scan(self):
"""perform_nfo_repair_scan must appear after perform_media_scan_if_needed."""
def test_perform_nfo_repair_scan_called_in_run_folder_scan(self):
"""perform_nfo_repair_scan must be called inside run_folder_scan."""
import importlib
source = importlib.util.find_spec("src.server.fastapi_app").origin
source = importlib.util.find_spec("src.server.services.folder_scan_service").origin
with open(source, "r", encoding="utf-8") as fh:
content = fh.read()
media_scan_pos = content.find("perform_media_scan_if_needed(background_loader)")
repair_scan_pos = content.find("perform_nfo_repair_scan(background_loader)")
run_folder_scan_pos = content.find("def run_folder_scan")
# Find the call inside the method body (after the import line)
repair_scan_call_pos = content.find("await perform_nfo_repair_scan(background_loader=None)")
assert media_scan_pos != -1, "perform_media_scan_if_needed call not found"
assert repair_scan_pos != -1, "perform_nfo_repair_scan call not found"
assert repair_scan_pos > media_scan_pos, (
"perform_nfo_repair_scan must be called AFTER perform_media_scan_if_needed"
assert run_folder_scan_pos != -1, "run_folder_scan method not found"
assert repair_scan_call_pos != -1, "perform_nfo_repair_scan call not found"
assert repair_scan_call_pos > run_folder_scan_pos, (
"perform_nfo_repair_scan must be called INSIDE run_folder_scan"
)