"""Tests for single-page web UI in static/index.html.""" from bs4 import BeautifulSoup from fastapi.testclient import TestClient from app import app from cleaner import BACKGROUND_PRESETS, DEFAULT_MODEL, build_prompt def test_get_root_serves_html(): """GET / returns 200 OK and text/html.""" client = TestClient(app) response = client.get("/") assert response.status_code == 200 assert "text/html" in response.headers.get("content-type", "") def test_get_static_index_html_serves_html(): """GET /static/index.html returns 200 OK and text/html.""" client = TestClient(app) response = client.get("/static/index.html") assert response.status_code == 200 assert "text/html" in response.headers.get("content-type", "") def test_html_contains_upload_elements(): """HTML contains file input, drop zone, and preview image element.""" client = TestClient(app) response = client.get("/") soup = BeautifulSoup(response.text, "html.parser") file_input = soup.find("input", {"type": "file"}) assert file_input is not None, "File input element missing" assert file_input.get("id") or file_input.get("name") drop_zone = soup.find(id="drop-zone") or soup.find(class_="drop-zone") assert drop_zone is not None, "Drop zone container missing" # Preview elements for original image, name, and dimensions before_preview = soup.find(id="before-image") or soup.find(id="preview-img") or soup.find(id="before-preview") assert before_preview is not None, "Before preview image element missing" file_info = soup.find(id="file-info") or soup.find(class_="file-info") assert file_info is not None, "File info container for name and dimensions missing" def test_html_contains_prompt_controls(): """HTML contains textarea prefilled with beige prompt and preset buttons.""" client = TestClient(app) response = client.get("/") soup = BeautifulSoup(response.text, "html.parser") prompt_textarea = soup.find("textarea") assert prompt_textarea is not None, "Prompt textarea missing" expected_default = build_prompt("beige") assert expected_default in prompt_textarea.text or expected_default in prompt_textarea.get("value", "") # Preset buttons preset_beige = soup.find(id="preset-beige") or soup.find("button", {"data-preset": "beige"}) assert preset_beige is not None, "Warm beige preset button missing" preset_white = soup.find(id="preset-white") or soup.find("button", {"data-preset": "white"}) assert preset_white is not None, "Bright white preset button missing" def test_html_contains_model_and_option_inputs(): """HTML contains model input, API key input, and restore_resolution checkbox.""" client = TestClient(app) response = client.get("/") soup = BeautifulSoup(response.text, "html.parser") model_input = soup.find("input", {"name": "model"}) or soup.find(id="model") assert model_input is not None, "Model input missing" assert model_input.get("value") == DEFAULT_MODEL or model_input.get("placeholder") == DEFAULT_MODEL api_key_input = ( soup.find("input", {"type": "password", "name": "api_key"}) or soup.find("input", {"name": "api_key"}) or soup.find(id="api-key") ) assert api_key_input is not None, "API key input missing" placeholder = api_key_input.get("placeholder", "") assert "OPENROUTER_API_KEY" in placeholder restore_checkbox = ( soup.find("input", {"type": "checkbox", "name": "restore_resolution"}) or soup.find("input", {"type": "checkbox", "id": "restore-resolution"}) ) assert restore_checkbox is not None, "Restore resolution checkbox missing" assert restore_checkbox.has_attr("checked"), "Restore resolution should be checked by default" def test_html_contains_processing_and_error_elements(): """HTML contains submit button, loading spinner/message with timer, and error banner.""" client = TestClient(app) response = client.get("/") soup = BeautifulSoup(response.text, "html.parser") submit_btn = soup.find("button", {"type": "submit"}) or soup.find(id="submit-btn") assert submit_btn is not None, "Submit button missing" loading_container = soup.find(id="loading-container") or soup.find(id="loading") or soup.find(class_="loading") assert loading_container is not None, "Loading container missing" loading_text = loading_container.get_text() assert "Editing with Muse, usually takes ~15-20s" in loading_text or "15-20s" in loading_text timer = soup.find(id="elapsed-timer") or soup.find(class_="elapsed-timer") assert timer is not None, "Elapsed timer display missing" error_banner = soup.find(id="error-banner") or soup.find(class_="error-banner") or soup.find(id="error-container") assert error_banner is not None, "Error banner missing" def test_html_contains_results_and_comparison_elements(): """HTML contains before/after comparison, metrics (cost, dimensions), and download button.""" client = TestClient(app) response = client.get("/") soup = BeautifulSoup(response.text, "html.parser") results_container = soup.find(id="results-container") or soup.find(id="results") or soup.find(class_="results") assert results_container is not None, "Results container missing" after_image = soup.find(id="after-image") or soup.find(id="after-preview") assert after_image is not None, "After image display element missing" cost_display = soup.find(id="cost-display") or soup.find(class_="cost-display") assert cost_display is not None, "Cost display missing" res_display = soup.find(id="resolution-display") or soup.find(class_="resolution-display") assert res_display is not None, "Resolution display missing" download_btn = soup.find(id="download-btn") or soup.find(id="download-link") assert download_btn is not None, "Download button missing" def test_html_javascript_logic(): """HTML script contains drag-drop, FileReader, presets, /api/clean call, and download handler.""" client = TestClient(app) response = client.get("/") html = response.text # Script tag present assert "