155 lines
6.5 KiB
Python
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
|