84 lines
4.0 KiB
Python
84 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
STATIC_ROOT = PROJECT_ROOT / "arr_web" / "static"
|
|
|
|
|
|
class TaskLogStaticContractTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls) -> None:
|
|
cls.html = (STATIC_ROOT / "index.html").read_text(encoding="utf-8")
|
|
cls.styles = (STATIC_ROOT / "styles.css").read_text(encoding="utf-8")
|
|
cls.script = (STATIC_ROOT / "app.js").read_text(encoding="utf-8")
|
|
|
|
def test_header_utility_replaces_mobile_dashboard_entry(self) -> None:
|
|
self.assertIn('id="task-log-trigger"', self.html)
|
|
self.assertIn('<a class="task-log-link"', self.html)
|
|
self.assertIn('aria-haspopup="dialog"', self.html)
|
|
self.assertIn('aria-controls="task-log-dialog"', self.html)
|
|
self.assertNotIn("手机看板", self.html)
|
|
self.assertNotIn('class="h5-link"', self.html)
|
|
|
|
def test_console_is_outside_the_daily_panel_and_inside_one_dialog(self) -> None:
|
|
daily_start = self.html.index('id="panel-daily"')
|
|
daily_end = self.html.index('id="panel-monthly"')
|
|
daily_panel = self.html[daily_start:daily_end]
|
|
self.assertNotIn('id="process-log"', daily_panel)
|
|
self.assertEqual(self.html.count('id="process-log"'), 1)
|
|
self.assertEqual(self.html.count('id="task-log-dialog"'), 1)
|
|
self.assertGreater(
|
|
self.html.index('id="task-log-dialog"'),
|
|
self.html.index("</main>"),
|
|
)
|
|
for required_id in (
|
|
'id="process-title"',
|
|
'id="trace-live-state"',
|
|
'id="refresh-trace"',
|
|
'id="copy-trace"',
|
|
'id="close-task-log"',
|
|
):
|
|
self.assertIn(required_id, self.html)
|
|
|
|
def test_dialog_open_close_and_polling_contract(self) -> None:
|
|
self.assertIn('$("#task-log-trigger").addEventListener("click", (event) => {', self.script)
|
|
self.assertIn("event.preventDefault();", self.script)
|
|
self.assertIn("openTaskLog();", self.script)
|
|
self.assertIn('$("#close-task-log").addEventListener("click", closeTaskLog)', self.script)
|
|
self.assertIn('$("#task-log-dialog").addEventListener("close", clearTracePoll)', self.script)
|
|
self.assertIn("|| !taskLogIsOpen()", self.script)
|
|
self.assertIn("{ showLog: true }", self.script)
|
|
self.assertNotIn('{ scroll: true }', self.script)
|
|
|
|
def test_upload_keeps_progress_inline_without_opening_log(self) -> None:
|
|
self.assertIn('id="upload-progress"', self.html)
|
|
self.assertIn('id="upload-progress-track"', self.html)
|
|
self.assertIn('role="progressbar"', self.html)
|
|
self.assertIn("DAILY_UPLOAD_PROGRESS_STAGES", self.script)
|
|
self.assertIn("function startUploadProgress()", self.script)
|
|
self.assertIn("function finishUploadProgress(success, label)", self.script)
|
|
upload_start = self.script.index("async function handleUpload()")
|
|
upload_end = self.script.index("\n async function loadMonthsAndAnalytics", upload_start)
|
|
upload_handler = self.script[upload_start:upload_end]
|
|
self.assertIn("startUploadProgress()", upload_handler)
|
|
self.assertIn("finishUploadProgress", upload_handler)
|
|
self.assertNotIn("openTaskLog()", upload_handler)
|
|
self.assertNotIn("showLog: true", upload_handler)
|
|
|
|
def test_dialog_reuses_responsive_accessible_visual_system(self) -> None:
|
|
self.assertIn(".task-log-link:hover", self.styles)
|
|
self.assertIn(".task-log-link:active", self.styles)
|
|
self.assertIn(".task-log-dialog::backdrop", self.styles)
|
|
self.assertIn(".upload-progress-track", self.styles)
|
|
self.assertIn(".upload-progress.is-success", self.styles)
|
|
self.assertIn("max-height: calc(100dvh - 32px)", self.styles)
|
|
self.assertIn("@media (max-width: 700px)", self.styles)
|
|
self.assertIn("@media (prefers-reduced-motion: reduce)", self.styles)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|