"""Unit tests for GalleryDLService._extract_errors_warnings and _truncate_log. These are the save-time log transforms that feed the Downloads modal's errors-only panel and prevent multi-MB stderr blobs from landing in JSONB. """ from app.services.gallery_dl import GalleryDLService def test_extract_errors_warnings_filters_debug_and_info(): stderr = ( "[gallery-dl][debug] Version 1.31.10\n" "[patreon][info] campaign_id: 548223\n" "[urllib3.connectionpool][debug] https://example.com 'HEAD /' 200 0\n" "[download][error] Failed to download 01.part\n" "[downloader.http][warning] '404 OK' for 'https://example.com'\n" "[patreon][debug] skipping https://example.com/x\n" ) result = GalleryDLService._extract_errors_warnings(stderr) lines = result.splitlines() assert len(lines) == 2 assert "[download][error]" in lines[0] assert "[downloader.http][warning]" in lines[1] def test_extract_errors_warnings_empty_when_clean_run(): stderr = ( "[gallery-dl][debug] Version 1.31.10\n" "[patreon][debug] skipping https://example.com/x\n" ) assert GalleryDLService._extract_errors_warnings(stderr) == "" def test_extract_errors_warnings_handles_empty_input(): assert GalleryDLService._extract_errors_warnings("") == "" assert GalleryDLService._extract_errors_warnings(None) == "" def test_truncate_log_passthrough_when_under_limit(): small = "line\n" * 100 assert GalleryDLService._truncate_log(small, max_bytes=10_000) == small def test_truncate_log_elides_middle_when_oversized(): large = ("x" * 100 + "\n") * 2000 # ~200KB truncated = GalleryDLService._truncate_log(large, max_bytes=10_000) assert len(truncated.encode("utf-8")) < len(large.encode("utf-8")) assert "lines elided" in truncated assert "bytes" in truncated # Head and tail preserved assert truncated.startswith("x") assert truncated.rstrip().endswith("x") def test_truncate_log_handles_empty_and_none(): assert GalleryDLService._truncate_log("") == "" assert GalleryDLService._truncate_log(None) is None