train_utility/tests/test_frontend.py
2026-08-04 14:00:46 +04:00

78 lines
2.7 KiB
Python
Executable file

from __future__ import annotations
from html.parser import HTMLParser
from pathlib import Path
import shutil
import subprocess
import pytest
NODE = shutil.which("node")
APP_JS = Path("src/yolo_webui/static/app.js")
INDEX_HTML = Path("src/yolo_webui/static/index.html")
STYLE_CSS = Path("src/yolo_webui/static/style.css")
class _MarkupCollector(HTMLParser):
def __init__(self) -> None:
super().__init__()
self.by_id: dict[str, dict[str, str | None]] = {}
self.options: dict[str, str] = {}
self._option_value: str | None = None
def handle_starttag(
self,
tag: str,
attrs: list[tuple[str, str | None]],
) -> None:
attributes = dict(attrs)
if element_id := attributes.get("id"):
self.by_id[element_id] = attributes
if tag == "option":
self._option_value = attributes.get("value")
def handle_data(self, data: str) -> None:
if self._option_value is not None:
self.options[self._option_value] = (
self.options.get(self._option_value, "") + data
).strip()
def handle_endtag(self, tag: str) -> None:
if tag == "option":
self._option_value = None
@pytest.mark.skipif(NODE is None, reason="Node.js is required for frontend checks")
def test_frontend_javascript_syntax() -> None:
subprocess.run([NODE, "--check", str(APP_JS)], check=True)
@pytest.mark.skipif(NODE is None, reason="Node.js is required for frontend checks")
def test_frontend_interactions_smoke() -> None:
subprocess.run([NODE, "tests/frontend_smoke.js"], check=True)
def test_export_controls_have_correct_formats_constraints_and_styles() -> None:
parser = _MarkupCollector()
parser.feed(INDEX_HTML.read_text(encoding="utf-8"))
assert parser.options["saved_model"].startswith("TensorFlow SavedModel")
assert parser.options["pb"] == "TensorFlow GraphDef (.pb)"
assert "triton" not in parser.options
assert parser.by_id["export-imgsz"]["min"] == "32"
assert parser.by_id["export-imgsz"]["max"] == "8192"
assert parser.by_id["export-imgsz"]["step"] == "1"
assert parser.by_id["export-batch"]["min"] == "1"
assert parser.by_id["export-batch"]["max"] == "1024"
assert parser.by_id["export-batch"]["step"] == "1"
assert parser.by_id["export-workspace"]["min"] == "1"
assert parser.by_id["export-workspace"]["max"] == "64"
assert parser.by_id["export-workspace"]["step"] == "0.5"
css = STYLE_CSS.read_text(encoding="utf-8")
assert "#export-config-pane" in css
assert "#export-run-pane" in css
assert "#export-log-container::-webkit-scrollbar" in css
assert "#export-status-card.status-exporting" in css
assert "#export-status-card.status-failed" in css