fix(ui/ux): only lay out the import dialog while it is open
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
"""Browser checks for the dialogs.
|
||||
|
||||
pytest alone cannot catch CSS mistakes: a "#quick-dialog { display: flex }"
|
||||
overrides the browser's display:none for a closed <dialog> and leaves it stuck
|
||||
on screen. Skipped when playwright or its browsers are missing.
|
||||
"""
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
sync_api = pytest.importorskip("playwright.sync_api", reason="playwright not installed")
|
||||
|
||||
|
||||
def _free_port() -> int:
|
||||
with socket.socket() as s:
|
||||
s.bind(("127.0.0.1", 0))
|
||||
return s.getsockname()[1]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def server(tmp_path_factory):
|
||||
tmp = tmp_path_factory.mktemp("ui")
|
||||
downloads = tmp / "downloads"
|
||||
(downloads / "Eine Folge").mkdir(parents=True)
|
||||
for i in (1, 2):
|
||||
(downloads / "Eine Folge" / f"{i:02d}.mp3").write_bytes(b"")
|
||||
port = _free_port()
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-m", "uvicorn", "wordarr.main:app", "--port", str(port)],
|
||||
cwd=Path(__file__).resolve().parent.parent,
|
||||
env={"PATH": "/usr/bin:/bin", "WORDARR_CONFIG_DIR": str(tmp / "config"),
|
||||
"WORDARR_DOWNLOAD_DIR": str(downloads)},
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
url = f"http://127.0.0.1:{port}"
|
||||
for _ in range(100):
|
||||
if proc.poll() is not None:
|
||||
pytest.skip("uvicorn did not start")
|
||||
try:
|
||||
with socket.create_connection(("127.0.0.1", port), timeout=0.2):
|
||||
break
|
||||
except OSError:
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
proc.kill()
|
||||
pytest.skip("server did not come up")
|
||||
yield url
|
||||
proc.kill()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(server):
|
||||
with sync_api.sync_playwright() as pw:
|
||||
try:
|
||||
browser = pw.chromium.launch()
|
||||
except Exception as exc: # browsers not downloaded
|
||||
pytest.skip(f"no chromium: {exc}")
|
||||
page = browser.new_page(viewport={"width": 1200, "height": 900})
|
||||
errors = []
|
||||
page.on("pageerror", lambda e: errors.append(str(e)))
|
||||
page.goto(server, wait_until="networkidle")
|
||||
yield page
|
||||
assert not errors, errors
|
||||
browser.close()
|
||||
|
||||
|
||||
def test_dialogs_start_closed(page):
|
||||
for dialog in ("#quick-dialog", "#series-dialog", "#manual-dialog"):
|
||||
assert not page.locator(dialog).is_visible(), dialog
|
||||
# the import dialog lives inside the import section, so it can only be seen
|
||||
# once that tab is open - a reload would not have hidden a broken one
|
||||
page.click("nav button[data-view=import]")
|
||||
assert not page.locator("#quick-dialog").is_visible()
|
||||
|
||||
|
||||
def test_import_dialog_opens_and_closes(page):
|
||||
page.click("nav button[data-view=import]")
|
||||
page.click("#scan-btn")
|
||||
page.wait_for_selector("[data-quick]")
|
||||
|
||||
page.click("[data-quick='0']")
|
||||
page.wait_for_selector("#quick-dialog[open]")
|
||||
assert page.locator("#quick-dialog").is_visible()
|
||||
# everything reachable, nothing cut off at the bottom
|
||||
for sel in ("#quick-m-submit", "#quick-close"):
|
||||
box = page.locator(sel).bounding_box()
|
||||
assert box["y"] + box["height"] <= 900, sel
|
||||
|
||||
page.click("#quick-close")
|
||||
page.wait_for_timeout(150)
|
||||
assert not page.locator("#quick-dialog").is_visible()
|
||||
|
||||
page.click("[data-quick='0']")
|
||||
page.wait_for_selector("#quick-dialog[open]")
|
||||
page.keyboard.press("Escape")
|
||||
page.wait_for_timeout(150)
|
||||
assert not page.locator("#quick-dialog").is_visible()
|
||||
Reference in New Issue
Block a user