Migrate UI to React and Tailwind Refs #32

This commit is contained in:
2026-07-30 14:54:46 +02:00
parent fb955adaf8
commit 65c96bbc4b
23 changed files with 6061 additions and 545 deletions
+17 -95
View File
@@ -33,7 +33,7 @@ def test_status_contains_service_configuration(tmp_path, monkeypatch):
assert "auth_enabled" in payload
def test_index_renders_queue_controls(tmp_path, monkeypatch):
def test_index_serves_react_application(tmp_path, monkeypatch):
monkeypatch.setenv("IMPORTARR_STATE_PATH", str(tmp_path / "state.db"))
import importarr.main as main
@@ -42,109 +42,31 @@ def test_index_renders_queue_controls(tmp_path, monkeypatch):
response = TestClient(main.app).get("/")
assert response.status_code == 200
assert "Queue controls" in response.text
assert "cancel-current" in response.text
assert '<div id="root"></div>' in response.text
assert '/static/assets/app.js' in response.text
assert '/static/assets/app.css' 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
assert "update-banner" in response.text
assert "checkForUpdates()" in response.text
assert "/api/control/update-check" in response.text
assert "update-now" in response.text
def test_stylesheet_includes_theme_and_progress_rules():
def test_frontend_uses_required_stack_and_capabilities():
from pathlib import Path
css = Path("importarr/static/importarr.css").read_text()
app = Path("frontend/src/main.jsx").read_text()
package = Path("frontend/package.json").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" in css
assert ".update-banner" in css
assert "#ff9f0a" in css
assert "lucide-react" in package
assert "@radix-ui/react-dialog" in package
assert "tailwindcss" in package
for endpoint in ("/api/jobs", "/api/settings", "/api/manual-batches", "/api/control/update", "/api/import/run-now"):
assert endpoint in app
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 '<meta name="viewport" content="width=device-width, initial-scale=1">' in response.text
def test_stylesheet_includes_mobile_responsive_rules():
def test_frontend_defines_exact_light_and_dark_tokens():
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: hidden" 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 "table-layout: fixed" 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
css = Path("frontend/src/globals.css").read_text()
for value in ("#F8FAFC", "#FFFFFF", "#4A43EC", "#7171FF", "#2AD1ED", "#1A1D2E", "#64748B", "#E2E8F0", "#252B42", "#303753", "#23283B", "#42ECF5", "#8B95B7", "#3D4668"):
assert value in css
assert ".dark" in css
def test_settings_endpoint_persists_arr_connection_values(tmp_path, monkeypatch):