unwrap-clothes/tests/test_ui.py
2026-09-10 23:28:59 +02:00

155 lines
6.5 KiB
Python

"""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 "<script" in html
# Drag and drop events
assert "dragover" in html
assert "drop" in html
# FileReader
assert "readAsDataURL" in html or "FileReader" in html
# API fetch
assert "/api/clean" in html
# Background presets
assert BACKGROUND_PRESETS["beige"] in html
assert BACKGROUND_PRESETS["white"] in html
# Clean download name suffix
assert "_clean." in html or "_clean" in html