def test_health_contains_build_info(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main payload = main.health() assert payload["status"] == "ok" assert payload["name"] == "Importarr" assert payload["version"] def test_build_date_is_rendered_in_local_time(monkeypatch): import importarr.build_info as build_info monkeypatch.setenv("TZ", "Europe/Copenhagen") import time time.tzset() monkeypatch.setenv("IMPORTARR_BUILD_DATE", "2026-07-29T12:00:00Z") assert build_info.build_info()["build_date"] == "2026-07-29T14:00:00+02:00" def test_status_contains_service_configuration(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main payload = main.status() assert payload["build"]["name"] == "Importarr" assert "download_root" in payload assert "movies_root" in payload assert "tv_root" in payload assert "auth_enabled" in payload def test_index_renders_queue_controls(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient response = TestClient(main.app).get("/") assert response.status_code == 200 assert "Queue controls" in response.text assert "cancel-current" in response.text def test_index_packs_secondary_controls_into_menu(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient response = TestClient(main.app).get("/") assert response.status_code == 200 assert 'class="menu"' in response.text assert 'data-dialog="service-info-dialog"' in response.text assert 'data-dialog="queue-controls-dialog"' in response.text assert 'data-dialog="manual-batches-dialog"' in response.text assert "Service info and build details" in response.text assert "Queue and history" in response.text assert "Current import" in response.text assert "current-progress" in response.text assert "theme-toggle" in response.text assert "setInterval(refresh, 2000)" in response.text assert "details.menu[open]" in response.text assert "e.target===e.currentTarget" in response.text assert "function readiness" in response.text assert 'title="${esc(j.reason||j.state)}"' in response.text def test_stylesheet_includes_theme_and_progress_rules(): from pathlib import Path css = Path("importarr/static/importarr.css").read_text() assert 'html[data-theme="light"]' in css assert 'html[data-theme="dark"]' in css assert ".current-panel progress" in css assert ".top-controls>button,.menu summary" in css def test_index_renders_settings_dialog(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient response = TestClient(main.app).get("/") assert response.status_code == 200 assert "settings-dialog" in response.text assert "SABnzbd" in response.text assert "Radarr" in response.text assert "Sonarr" in response.text assert "Test SABnzbd connection" in response.text assert "Test Radarr connection" in response.text assert "Test Sonarr connection" in response.text def test_index_renders_responsive_table_wrappers(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient response = TestClient(main.app).get("/") assert response.status_code == 200 assert 'class="table-scroll"' in response.text assert "job-cards" in response.text assert "job-card" in response.text assert '' in response.text def test_stylesheet_includes_mobile_responsive_rules(): from pathlib import Path css = Path("importarr/static/importarr.css").read_text() assert "@media (max-width:640px)" in css assert ".table-scroll" in css assert "overflow-x:auto" in css assert "flex-direction:column" in css assert ".jobs-table{display:none}" in css assert ".job-cards{display:block}" in css assert "word-break:break-word" in css assert "max-width:1280px" in css assert ".jobs-table table{table-layout:fixed;min-width:0}" in css assert ".jobs-table th:nth-child(1){width:66%}" in css assert ".row-actions button{width:1.85rem" in css assert ".summary-strip" in css assert ".menu-panel" in css assert "@media (prefers-color-scheme:dark)" in css assert "--primary:#4b42b8" in css assert "--cyan:#50dce5" in css assert "--bg:#fff" in css assert "--bg:#2f3d55" in css assert "--danger:#a56af0" in css def test_settings_endpoint_persists_arr_connection_values(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient response = TestClient(main.app).post( "/api/settings", json={ "sab_url": "http://sab:8080", "sab_api_key": "sab-secret", "radarr_url": "http://radarr:7878", "radarr_api_key": "radarr-secret", "sonarr_url": "http://sonarr:8989", "sonarr_api_key": "sonarr-secret", }, ) assert response.status_code == 200 assert response.json() == { "sab_url": "http://sab:8080", "sab_api_key_configured": True, "radarr_url": "http://radarr:7878", "radarr_api_key_configured": True, "sonarr_url": "http://sonarr:8989", "sonarr_api_key_configured": True, } assert main.settings.sab_api_key == "sab-secret" assert main.state.get_app_state("radarr_api_key") == "radarr-secret" def test_sab_connection_test_reports_success(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient async def fake_queue(self): return {"queue": {"slots": [{"name": "one"}, {"name": "two"}]}} monkeypatch.setattr(main.SabnzbdClient, "queue", fake_queue) response = TestClient(main.app).post( "/api/settings/test-connection", json={"service": "sabnzbd", "url": "http://sab:8080", "api_key": "secret"}, ) assert response.status_code == 200 assert response.json() == {"ok": True, "service": "sabnzbd", "message": "Connected to SABnzbd; 2 queued jobs visible."} def test_connection_test_rejects_unknown_service(tmp_path, monkeypatch): monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db")) import importarr.main as main from fastapi.testclient import TestClient response = TestClient(main.app).post( "/api/settings/test-connection", json={"service": "lidarr", "url": "http://lidarr:8686"}, ) assert response.status_code == 400