#!/usr/bin/env python3 """web panel — static and contract tests (stdlib unittest). No port is bound, no browser is opened and no server process is started: the whole HTTP surface is covered through ``web.panel.route()``, which is a pure function, and every rendering claim is checked on the rendered bytes. What these tests defend (the things that could silently regress): * the Turkish status vocabulary still matches docs/DESIGN.md exactly, so the device console and the central panel cannot drift apart; * every user-visible string is non-empty, Turkish and free of placeholders; * no external URL, no webfont, no hex colour and no new colour token anywhere in the templates or stylesheets: colour comes from tokens.css only; * the panel imports nothing outside the standard library and can therefore be installed on the air-gapped fleet it manages; * only GET/HEAD are served, static assets are allow-listed, and a full sweep over every endpoint leaves the filesystem untouched; * the first viewport is ordered and populated as docs/DESIGN.md requires. Run: python3 tests/test_web_static.py -v """ from __future__ import annotations import ast import contextlib import io import json import re import sys import tempfile import unittest from pathlib import Path from typing import Any REPO_ROOT = Path(__file__).resolve().parents[1] WEB_DIR = REPO_ROOT / "web" TEMPLATES_DIR = WEB_DIR / "templates" STATIC_DIR = WEB_DIR / "static" TOKENS_CSS = STATIC_DIR / "tokens.css" DESIGN_DOC = REPO_ROOT / "docs" / "DESIGN.md" if str(REPO_ROOT) not in sys.path: sys.path.insert(0, str(REPO_ROOT)) import web # noqa: E402 (path set above) from web import fleet_data, panel, render, server # noqa: E402 # The panel must be the one in this checkout, not some unrelated "web" package. assert Path(web.__file__).resolve().parent == WEB_DIR, f"yanlis paket: {web.__file__}" NOW = "2026-09-16T22:00:00+03:00" STATE_WORDS = ("KURULDU", "KAYITLI", "HAZIR", "HATA", "YOK") # Everything an air-gapped, framework-free surface must never contain. FORBIDDEN_ASSET_MARKERS = ( "http://", "https://", "//cdn", "cdn.jsdelivr", "cdnjs", "unpkg", "fonts.googleapis", "fonts.gstatic", "@import", "@font-face", "src=", "xlink:href=", ) FORBIDDEN_IMPORT_ROOTS = ("fastapi", "flask", "jinja2", "uvicorn", "django", "werkzeug", "starlette", "requests") FORBIDDEN_IMPORTS = ("urllib.request", "http.client", "socket", "subprocess", "shutil", "ftplib") FORBIDDEN_SOURCE_MARKERS = ("os.system(", "subprocess.", "urllib.request", "requests.", "eval(", "exec(") HEX_COLOUR = re.compile(r"#[0-9a-fA-F]{3,8}\b") CUSTOM_PROPERTY = re.compile(r"^\s*--[A-Za-z0-9-]+\s*:", re.M) # A custom-property declaration, e.g. `--state-ready: var(--ok);` CUSTOM_PROPERTY_DECL = re.compile(r"^\s*--([A-Za-z0-9-]+)\s*:\s*([^;]+);", re.M) # A single `var(--name)` reference inside a value. VAR_REFERENCE = re.compile(r"var\(\s*--([A-Za-z0-9-]+)\s*\)") DEFINED_TOKEN = re.compile(r"^\s*(--[a-z0-9-]+)\s*:", re.M) USED_TOKEN = re.compile(r"var\((--[a-z0-9-]+)\)") TEXT_TAGS = ("td", "th", "span", "h1", "h2", "h3", "p", "li", "option", "dd", "dt", "button", "a", "caption", "label") ELEMENT = re.compile(r"<(%s)\b[^>]*>(.*?)" % "|".join(TEXT_TAGS), re.S) ROW_BADGE = re.compile(r']*>([^<]*)') # -------------------------------------------------------------------------- # helpers # -------------------------------------------------------------------------- def token_values(text: str) -> dict[str, str]: """Every custom-property declaration in a stylesheet, name -> raw value.""" return { name: value.strip() for name, value in CUSTOM_PROPERTY_DECL.findall(text) } def resolved_colour(name: str, values: dict[str, str], limit: int = 12) -> str | None: """Follow ``var(--x)`` aliases to the colour a token actually paints. Comparing raw declarations is not enough to prove two tokens differ: a mutation writing ``--state-provisioned: var(--accent)`` leaves the strings unequal while painting exactly the same blue. Only the resolved value is evidence. """ seen: set[str] = set() while limit > 0: value = values.get(name) if value is None: return None reference = VAR_REFERENCE.fullmatch(value) if reference is None: return value name = reference.group(1) if name in seen: return value # a cycle: report what was declared rather than loop seen.add(name) limit -= 1 return values.get(name) def design_vocabulary() -> list[tuple[str, str]]: """Read the status vocabulary table out of docs/DESIGN.md.""" text = DESIGN_DOC.read_text(encoding="utf-8") row = re.compile(r"^\|\s*`([^`]+)`\s*\|\s*`(--state-[a-z-]+)`\s*\|", re.M) return row.findall(text) def text_files() -> list[Path]: """Templates and stylesheets: everything the browser receives from disk.""" return sorted(TEMPLATES_DIR.glob("*.html")) + sorted(STATIC_DIR.glob("*.css")) def empty_elements(markup: str) -> list[str]: """Visible elements that carry no text at all (an empty label is a bug).""" problems: list[str] = [] for match in ELEMENT.finditer(markup): inner = re.sub(r"<[^>]+>", "", match.group(2)) if not inner.strip(): problems.append(match.group(0)[:140]) return problems def tree_fingerprint(root: Path) -> tuple: """Sizes and mtimes of every source file, ignoring interpreter caches.""" entries = [] for path in sorted(root.rglob("*")): if "__pycache__" in path.parts or not path.is_file(): continue stat = path.stat() entries.append((str(path.relative_to(root)), stat.st_size, stat.st_mtime_ns)) return tuple(entries) class PanelCase(unittest.TestCase): """Shared fixture: the labelled demo snapshot and both privilege levels.""" @classmethod def setUpClass(cls) -> None: cls.snapshot = fleet_data.demo_snapshot(NOW) cls.read_only = render.privilege_from_level("read-only") cls.full = render.privilege_from_level("full") cls.info = render.ServerInfo( host="127.0.0.1", port=8787, privilege=cls.read_only, python_version="3.13.0", started_at=NOW, ) cls.context = panel.PanelContext( snapshot=cls.snapshot, privilege=cls.read_only, server_info=cls.info ) full_info = render.ServerInfo( host="127.0.0.1", port=8787, privilege=cls.full, python_version="3.13.0", started_at=NOW, ) cls.full_context = panel.PanelContext( snapshot=cls.snapshot, privilege=cls.full, server_info=full_info ) # -- request helpers --------------------------------------------------- def get(self, target: str, method: str = "GET", context: panel.PanelContext | None = None): return panel.route(context or self.context, method, target) def page(self, target: str = "/", method: str = "GET", context: panel.PanelContext | None = None) -> str: response = self.get(target, method, context) self.assertEqual(response.status, 200, f"{target}: {response.status} (beklenen 200)") return response.body.decode("utf-8") def list_region(self, page: str) -> str: """The device table only, so about/detail badges never leak into a scan.""" start = page.index('data-region="list"') end = page.index('data-region="detail"') return page[start:end] def row_words(self, page: str) -> list[str]: return [word for _, word in ROW_BADGE.findall(self.list_region(page))] def snapshot_from(self, document: object, *, now: str = NOW, filename: str = "fleet.json"): """Write a temporary inventory document and load it through the loader.""" directory = tempfile.TemporaryDirectory(prefix="bf-panel-test-") self.addCleanup(directory.cleanup) path = Path(directory.name) / filename if isinstance(document, str): path.write_text(document, encoding="utf-8") else: path.write_text(json.dumps(document, ensure_ascii=False), encoding="utf-8") return fleet_data.load_fleet(path, env={}, now=now) # -------------------------------------------------------------------------- # vocabulary and design contract # -------------------------------------------------------------------------- class TestVocabularyMatchesDesign(PanelCase): def test_vocabulary_matches_docs_design_exactly(self) -> None: """One word per state, shared with the device console; no fifth word.""" self.assertEqual( design_vocabulary(), [(spec.word, spec.token) for spec in fleet_data.STATE_VOCABULARY], ) def test_design_document_still_has_the_five_words(self) -> None: words = [word for word, _ in design_vocabulary()] self.assertEqual(words, list(STATE_WORDS)) def test_every_word_is_upper_case_turkish_and_non_empty(self) -> None: for spec in fleet_data.STATE_VOCABULARY: with self.subTest(state=spec.state): self.assertTrue(spec.word.strip(), spec.state) self.assertEqual(spec.word, spec.word.upper()) self.assertTrue(spec.meaning.strip(), spec.word) self.assertNotIn("None", spec.meaning) def test_tokens_exist_in_tokens_css(self) -> None: css = TOKENS_CSS.read_text(encoding="utf-8") for spec in fleet_data.STATE_VOCABULARY: with self.subTest(state=spec.state): self.assertIn(f"{spec.token}:", css) self.assertIn(f"{spec.soft_token}:", css) def test_non_ready_states_sort_before_ready(self) -> None: self.assertEqual(fleet_data.STATE_ORDER[-1], "READY") self.assertEqual(set(fleet_data.STATE_ORDER), set(fleet_data.STATE_BY_NAME)) def test_demo_data_exercises_every_state_word(self) -> None: counts = self.snapshot.counts self.assertEqual(list(counts), list(STATE_WORDS)) for word, count in counts.items(): with self.subTest(word=word): self.assertGreaterEqual(count, 1, f"{word} demo veride yok; sözlük test edilemez") def test_demo_data_exercises_every_wave(self) -> None: counts = fleet_data.wave_counts(self.snapshot.devices) self.assertEqual(list(counts), [wave.code for wave in fleet_data.WAVES]) for code, count in counts.items(): with self.subTest(wave=code): self.assertGreaterEqual(count, 1) def test_waves_match_the_rollout_document(self) -> None: """docs/18: LAB(2) -> P1(5) -> P2(20) -> W1(50) -> W2(100) -> PROD.""" self.assertEqual( [(wave.code, wave.target) for wave in fleet_data.WAVES], [("LAB", 2), ("P1", 5), ("P2", 20), ("W1", 50), ("W2", 100), ("PROD", 523)], ) def test_four_documented_channels(self) -> None: self.assertEqual( [channel.label for channel in fleet_data.CHANNELS], ["SSH-over-WG", "xRDP", "RustDesk", "MeshCentral"], ) self.assertEqual( [channel.key for channel in fleet_data.CHANNELS], ["ssh_over_wg", "xrdp", "rustdesk", "meshcentral"], ) def test_channel_status_words_are_turkish_and_non_empty(self) -> None: for status, word in fleet_data.CHANNEL_STATUS_WORDS.items(): with self.subTest(status=status): self.assertTrue(word.strip()) self.assertNotIn("None", word) self.assertEqual(set(fleet_data.CHANNEL_STATUS_WORDS), set(fleet_data.CHANNEL_STATUSES)) # -------------------------------------------------------------------------- # no external assets, no invented colour # -------------------------------------------------------------------------- class TestAssetsAndColour(PanelCase): def test_no_external_url_or_remote_asset_in_any_template_or_stylesheet(self) -> None: for path in text_files(): text = path.read_text(encoding="utf-8").lower() for marker in FORBIDDEN_ASSET_MARKERS: with self.subTest(file=path.name, marker=marker): self.assertNotIn(marker, text) def test_no_javascript_ships_with_the_panel(self) -> None: for path in text_files(): text = path.read_text(encoding="utf-8").lower() with self.subTest(file=path.name): self.assertNotIn(" None: for path in text_files(): text = path.read_text(encoding="utf-8") if path == TOKENS_CSS: self.assertTrue(HEX_COLOUR.search(text), "tokens.css palet içermiyor") continue with self.subTest(file=path.name): self.assertEqual(HEX_COLOUR.findall(text), [], f"{path.name} hex renk içeriyor") def test_templates_and_app_css_declare_no_custom_property(self) -> None: for path in text_files(): if path == TOKENS_CSS: continue text = path.read_text(encoding="utf-8") with self.subTest(file=path.name): self.assertEqual(CUSTOM_PROPERTY.findall(text), [], f"{path.name} belirteç tanımlıyor") def test_every_colour_token_used_is_defined_in_tokens_css(self) -> None: defined = set(DEFINED_TOKEN.findall(TOKENS_CSS.read_text(encoding="utf-8"))) self.assertTrue(defined) used: dict[str, str] = {} for path in text_files(): if path == TOKENS_CSS: continue for token in USED_TOKEN.findall(path.read_text(encoding="utf-8")): used[token] = path.name unknown = {token: name for token, name in used.items() if token not in defined} self.assertEqual(unknown, {}, f"tokens.css'te tanımsız belirteç: {unknown}") self.assertTrue(used, "hiç belirteç kullanılmıyor") def test_the_action_accent_is_not_a_device_state_colour(self) -> None: """The accent means "the action you came to take" and "the selected row". A state that borrows it makes a KURULDU badge and a selected row the same blue, so the list can no longer say which of the two it is showing. Aliases are resolved before comparing: a token may chain (``--state-ready`` to ``--ok``), and ``var(--accent)`` is the accent whatever the string says. """ values = token_values(TOKENS_CSS.read_text(encoding="utf-8")) self.assertIn("accent", values, "tokens.css'te --accent yok") accent = resolved_colour("accent", values) states = {n: v for n, v in values.items() if n.startswith("state-")} self.assertTrue(states, "tokens.css'te cihaz durumu belirteci yok") for name in states: with self.subTest(token=name): resolved = resolved_colour(name, values) self.assertIsNotNone(resolved, f"--{name} çözümlenemedi") self.assertNotEqual( resolved, accent, f"--{name} ile --accent aynı rengi veriyor ({resolved}); " "seçili satır ile durum rozeti ayırt edilemez", ) def test_wave_is_rendered_once_and_not_as_the_bare_code_plus_full_label(self) -> None: """``detail.html`` printed ``$wave_code`` and then ``$wave_label``, and the label already begins with the code, so one device read "P2 P2 — PILOT-2" (the list row was the same). A wave cell must name each wave once. """ device = next( d for d in self.snapshot.devices if d.wave_code == "P2" ) target = f"/?cihaz={device.device_id}" body = panel.route(self.context, "GET", target).body.decode("utf-8") self.assertNotIn("$wave_name", body, "şablon değişkeni değiştirilmedi") self.assertNotIn("$wave_code", body, "şablon değişkeni değiştirilmedi") self.assertNotIn(device.wave_code * 2, body, f"dalga kodu iki kez basılıyor: {device.wave_code}") self.assertIn(device.wave_label, body, "dalga tam etiketi görünmüyor") def test_only_local_stylesheets_are_linked(self) -> None: base = (TEMPLATES_DIR / "base.html").read_text(encoding="utf-8") linked = re.findall(r']*href="([^"]+)"', base) self.assertEqual(linked, ["/static/tokens.css", "/static/app.css"]) def test_templates_are_utf8_with_turkish_characters(self) -> None: for path in sorted(TEMPLATES_DIR.glob("*.html")): text = path.read_text(encoding="utf-8") with self.subTest(file=path.name): self.assertTrue(text.strip()) base = (TEMPLATES_DIR / "base.html").read_text(encoding="utf-8") self.assertIn('', base) def test_state_badge_styles_use_the_shared_tokens(self) -> None: css = (STATIC_DIR / "app.css").read_text(encoding="utf-8") for spec in fleet_data.STATE_VOCABULARY: with self.subTest(state=spec.state): self.assertIn(f".badge--state-{spec.token_suffix}", css) self.assertIn("var(--accent-soft)", css) self.assertIn(".fleet-row--selected", css) # -------------------------------------------------------------------------- # standard library only: the fleet installs offline # -------------------------------------------------------------------------- class TestStdlibOnly(PanelCase): def web_sources(self) -> list[Path]: return sorted(WEB_DIR.glob("*.py")) def test_web_modules_exist(self) -> None: names = {path.name for path in self.web_sources()} self.assertEqual( names, {"__init__.py", "fleet_data.py", "render.py", "panel.py", "server.py"} ) def test_every_import_resolves_to_the_standard_library(self) -> None: stdlib = set(sys.stdlib_module_names) for path in self.web_sources(): tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) for node in ast.walk(tree): if isinstance(node, ast.Import): roots = [alias.name.split(".")[0] for alias in node.names] elif isinstance(node, ast.ImportFrom): if node.level: continue roots = [(node.module or "").split(".")[0]] else: continue for root in roots: with self.subTest(file=path.name, module=root): self.assertIn(root, stdlib | {"web"}) def test_no_third_party_web_framework_is_referenced(self) -> None: for path in self.web_sources(): text = path.read_text(encoding="utf-8").lower() for marker in FORBIDDEN_IMPORT_ROOTS: with self.subTest(file=path.name, marker=marker): self.assertNotIn(f"import {marker}", text) self.assertNotIn(f"from {marker}", text) def test_no_outbound_client_and_no_process_execution(self) -> None: for path in self.web_sources(): text = path.read_text(encoding="utf-8") for marker in FORBIDDEN_IMPORTS: with self.subTest(file=path.name, marker=marker): self.assertNotIn(f"import {marker}", text) lowered = text.lower() for marker in FORBIDDEN_SOURCE_MARKERS: with self.subTest(file=path.name, marker=marker): self.assertNotIn(marker, lowered) def test_route_is_a_pure_function_with_a_small_signature(self) -> None: import inspect signature = inspect.signature(panel.route) self.assertEqual(list(signature.parameters), ["context", "method", "target"]) def test_server_module_takes_host_and_port_from_the_command_line(self) -> None: args = server.parse_args([]) self.assertEqual(args.host, "127.0.0.1") self.assertEqual(args.host, web.DEFAULT_HOST) self.assertEqual(args.port, web.DEFAULT_PORT) self.assertEqual(args.privilege, "read-only") self.assertEqual(args.data, None) def test_check_mode_reports_without_binding_a_port(self) -> None: buffer = io.StringIO() with contextlib.redirect_stdout(buffer): code = server.main(["--check"]) self.assertEqual(code, 0) output = buffer.getvalue() self.assertIn(web.PANEL_VERSION, output) self.assertIn("Veri kaynağı", output) self.assertIn("Yetki", output) self.assertIn("sunucu başlatılmadı", output) def test_version_and_privilege_flags(self) -> None: with contextlib.redirect_stdout(io.StringIO()): with self.assertRaises(SystemExit) as raised: server.parse_args(["--version"]) self.assertEqual(raised.exception.code, 0) with contextlib.redirect_stderr(io.StringIO()): with self.assertRaises(SystemExit): server.parse_args(["--privilege", "root"]) def test_data_flag_selects_the_inventory_file(self) -> None: snapshot = self.snapshot_from(self.example_document()) with tempfile.TemporaryDirectory() as directory: path = Path(directory) / "fleet.json" path.write_text(self.example_document(), encoding="utf-8") context = server.build_context(server.parse_args(["--data", str(path)])) self.assertTrue(context.snapshot.is_file) self.assertEqual(context.snapshot.total, snapshot.total) self.assertEqual(context.server_info.data_path, str(path)) def example_document(self) -> str: return (WEB_DIR / "data" / "fleet.example.json").read_text(encoding="utf-8") def test_example_document_matches_the_panel_schema(self) -> None: """The shipped example must load cleanly, or it teaches the wrong schema.""" snapshot = self.snapshot_from(self.example_document()) self.assertTrue(snapshot.is_file, snapshot.error or "örnek belge okunamadı") self.assertEqual(snapshot.invalid, ()) self.assertGreaterEqual(snapshot.total, 5) self.assertGreater(snapshot.ready_count, 0) # -------------------------------------------------------------------------- # loader: state machines, refusal paths, provenance # -------------------------------------------------------------------------- class TestLoader(PanelCase): READY_RECORD: dict[str, Any] = { "dealer_id": "12010193", "wave": "P1", "state": "READY", "channels": { "ssh_over_wg": "verified", "xrdp": "verified", "rustdesk": "verified", "meshcentral": "verified", }, } def document(self, *records: object) -> dict: return {"schema_version": 1, "generated_at": NOW, "devices": list(records)} def test_missing_default_file_falls_back_to_labelled_demo(self) -> None: snapshot = fleet_data.load_fleet(None, env={}, now=NOW, default_path="/yok/fleet.json") self.assertTrue(snapshot.is_demo) self.assertEqual(snapshot.total, len(fleet_data.DEMO_DEVICES)) self.assertIn("demo", snapshot.source_label.lower()) self.assertEqual(snapshot.banner_word, "DEMO VERİ") self.assertIn("sentetik", snapshot.banner_text) def test_missing_explicit_file_is_an_error_and_does_not_become_demo(self) -> None: snapshot = fleet_data.load_fleet("/yok/boyle/bir/dosya.json", env={}, now=NOW) self.assertTrue(snapshot.is_error) self.assertEqual(snapshot.total, 0) self.assertEqual(snapshot.banner_word, "VERİ YOK") self.assertIn("bulunamadı", snapshot.error or "") self.assertIn("Demo veriye düşülmedi", snapshot.banner_text) def test_environment_variable_selects_the_document(self) -> None: document = json.dumps(self.document(self.READY_RECORD)) with tempfile.TemporaryDirectory() as directory: path = Path(directory) / "fleet.json" path.write_text(document, encoding="utf-8") snapshot = fleet_data.load_fleet(None, env={fleet_data.DATA_PATH_ENV: str(path)}, now=NOW) self.assertTrue(snapshot.is_file) self.assertEqual(snapshot.total, 1) def test_identity_is_derived_from_the_dealer_number(self) -> None: snapshot = self.snapshot_from(self.document(self.READY_RECORD)) device = snapshot.devices[0] self.assertEqual(device.device_id, "BF-12010193") self.assertEqual(device.hostname, "bf-12010193") self.assertEqual(device.dealer_id, "12010193") self.assertEqual(snapshot.schema_version, 1) self.assertEqual(snapshot.generated_at, NOW) def test_wave_aliases_resolve_to_the_rollout_codes(self) -> None: for raw, expected in ( ("pilot_1", "P1"), ("LAB", "LAB"), ("wave_2", "W2"), ("production", "PROD"), ): with self.subTest(wave=raw): record = dict(self.READY_RECORD, wave=raw) snapshot = self.snapshot_from(self.document(record)) self.assertEqual(snapshot.devices[0].wave_code, expected) def test_turkish_state_words_are_accepted_as_input(self) -> None: for raw, expected in (("HAZIR", "READY"), ("Hazır", "READY"), ("hazir", "READY")): with self.subTest(state=raw): record = dict(self.READY_RECORD, state=raw) snapshot = self.snapshot_from(self.document(record)) self.assertEqual(snapshot.devices[0].state, expected) def test_broken_json_is_an_error_that_names_the_document(self) -> None: snapshot = self.snapshot_from('{"schema_version": 1, "devices": [') self.assertTrue(snapshot.is_error) self.assertIn("JSON", snapshot.error or "") def test_unsupported_schema_version_is_refused(self) -> None: for version in (2, 99): with self.subTest(version=version): document = {"schema_version": version, "devices": []} snapshot = self.snapshot_from(document) self.assertTrue(snapshot.is_error) self.assertIn("şema sürümü", snapshot.error or "") def test_missing_schema_version_or_devices_list_is_refused(self) -> None: for document in ({"devices": []}, {"schema_version": 1}): with self.subTest(document=document): snapshot = self.snapshot_from(document) self.assertTrue(snapshot.is_error) def test_bad_dealer_number_is_shown_not_dropped(self) -> None: record = dict(self.READY_RECORD, dealer_id="1201019") snapshot = self.snapshot_from(self.document(record)) self.assertEqual(snapshot.total, 0) self.assertEqual(len(snapshot.invalid), 1) reason = snapshot.invalid[0].reason self.assertIn("8 hane", reason) self.assertIn("1201019", reason) def test_duplicate_dealer_number_is_refused(self) -> None: snapshot = self.snapshot_from(self.document(self.READY_RECORD, dict(self.READY_RECORD))) self.assertEqual(snapshot.total, 1) self.assertEqual(len(snapshot.invalid), 1) self.assertIn("Yinelenen", snapshot.invalid[0].reason) def test_unknown_wave_is_refused_with_a_turkish_reason(self) -> None: record = dict(self.READY_RECORD, wave="WAVE-9") snapshot = self.snapshot_from(self.document(record)) self.assertEqual(snapshot.total, 0) self.assertIn("Bilinmeyen dalga", snapshot.invalid[0].reason) def test_mismatching_device_id_is_refused(self) -> None: record = dict(self.READY_RECORD, device_id="BF-12010999") snapshot = self.snapshot_from(self.document(record)) self.assertEqual(snapshot.total, 0) self.assertIn("kurala uymuyor", snapshot.invalid[0].reason) def test_unknown_state_becomes_hata_with_the_reason(self) -> None: record = dict(self.READY_RECORD, state="BOZUK") snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertEqual(device.state_label, "HATA") self.assertEqual(device.claimed_state, "BOZUK") self.assertIn("tanınmıyor", device.reason or "") def test_missing_state_becomes_hata_and_is_never_invented(self) -> None: record = {key: value for key, value in self.READY_RECORD.items() if key != "state"} snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertEqual(device.state_label, "HATA") self.assertIn("Durum alanı yok", device.reason or "") def test_ready_claim_without_verified_channels_is_refused(self) -> None: """docs/27: READY is refused unless every channel reports verified.""" record = dict(self.READY_RECORD) record["channels"] = dict(self.READY_RECORD["channels"], xrdp="pending") snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertEqual(device.state_label, "HATA") self.assertEqual(device.claimed_state, "READY") self.assertIn("HAZIR iddiası reddedildi", device.reason or "") self.assertIn("xRDP", device.reason or "") self.assertIn("xRDP", device.unverified_channels) def test_ready_claim_with_every_channel_verified_is_ready(self) -> None: snapshot = self.snapshot_from(self.document(self.READY_RECORD)) device = snapshot.devices[0] self.assertEqual(device.state_label, "HAZIR") self.assertEqual(device.verified_channel_count, 4) self.assertEqual(device.unverified_channels, ()) self.assertIn("dört kanalın dördü de doğrulandı", device.ready_gate_note) def test_failed_channel_marks_the_device_hata(self) -> None: record = dict(self.READY_RECORD, state="ENROLLED") record["channels"] = dict(self.READY_RECORD["channels"], rustdesk="failed") snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertEqual(device.state_label, "HATA") self.assertIn("başarısız", device.reason or "") def test_panel_never_promotes_a_device(self) -> None: record = dict(self.READY_RECORD, state="ENROLLED") snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertEqual(device.state_label, "KAYITLI") self.assertTrue(any("yükseltmez" in note for note in device.notes), device.notes) def test_missing_channels_are_all_reported_as_missing(self) -> None: record = {"dealer_id": "12010193", "wave": "P1", "state": "PROVISIONED_OFFLINE"} snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertEqual(len(device.channels), 4) self.assertEqual({check.status for check in device.channels}, {"missing"}) self.assertEqual({check.status_word for check in device.channels}, {"yok"}) self.assertTrue(any("Kanallar bildirilmemiş" in note for note in device.notes)) def test_unknown_channel_keys_are_reported_not_silently_ignored(self) -> None: record = dict(self.READY_RECORD) record["channels"] = dict(self.READY_RECORD["channels"], telnet="verified") snapshot = self.snapshot_from(self.document(record)) device = snapshot.devices[0] self.assertTrue(any("telnet" in note for note in device.notes), device.notes) self.assertEqual(len(device.channels), 4) def test_loader_is_deterministic(self) -> None: document = self.document(self.READY_RECORD) first = self.snapshot_from(document) second = self.snapshot_from(document) self.assertEqual(first.devices, second.devices) # -------------------------------------------------------------------------- # ordering and filtering # -------------------------------------------------------------------------- class TestOrderingAndFiltering(PanelCase): def sorted_demo(self): return fleet_data.sort_devices(self.snapshot.devices) def test_non_ready_devices_come_first(self) -> None: flags = [device.is_ready for device in self.sorted_demo()] self.assertEqual(flags, sorted(flags), "hazır cihaz hazır olmayanın önünde") self.assertIn(True, flags) self.assertIn(False, flags) def test_failed_devices_are_at_the_top(self) -> None: ordered = self.sorted_demo() self.assertEqual(ordered[0].state_label, "HATA") def test_sort_keeps_every_device_exactly_once(self) -> None: ordered = self.sorted_demo() self.assertEqual(len(ordered), self.snapshot.total) self.assertEqual( {device.device_id for device in ordered}, {device.device_id for device in self.snapshot.devices}, ) def test_query_filter_matches_identity_hostname_and_dealer(self) -> None: for needle in ("BF-12010193", "bf-12010193", "12010193"): with self.subTest(needle=needle): criteria, warnings = fleet_data.parse_filter({"q": [needle]}) shown = fleet_data.filter_devices(self.snapshot.devices, criteria) self.assertEqual(len(shown), 1, needle) self.assertEqual(shown[0].device_id, "BF-12010193") self.assertEqual(warnings, ()) def test_filter_query_is_case_insensitive(self) -> None: criteria, _ = fleet_data.parse_filter({"q": ["bf-1201019"]}) shown = fleet_data.filter_devices(self.snapshot.devices, criteria) self.assertEqual( {device.device_id for device in shown}, {"BF-12010193", "BF-12010194", "BF-12010195"}, ) def test_state_filter_accepts_word_machine_name_and_folded_input(self) -> None: for raw in ("HAZIR", "ready", "hazir", "Hazır"): with self.subTest(raw=raw): criteria, warnings = fleet_data.parse_filter({"durum": [raw]}) self.assertEqual(criteria.state, "READY") self.assertEqual(warnings, ()) shown = fleet_data.filter_devices(self.snapshot.devices, criteria) self.assertTrue(shown) self.assertEqual({device.state_label for device in shown}, {"HAZIR"}) def test_wave_filter_accepts_repo_group_names(self) -> None: for raw, code in (("pilot_1", "P1"), ("W1", "W1"), ("production", "PROD")): with self.subTest(raw=raw): criteria, _ = fleet_data.parse_filter({"dalga": [raw]}) self.assertEqual(criteria.wave, code) shown = fleet_data.filter_devices(self.snapshot.devices, criteria) self.assertTrue(shown) self.assertEqual({device.wave_code for device in shown}, {code}) def test_unknown_filter_values_are_ignored_with_a_turkish_warning(self) -> None: criteria, warnings = fleet_data.parse_filter({"durum": ["MOR"], "dalga": ["W9"]}) self.assertEqual(criteria.state, "") self.assertEqual(criteria.wave, "") self.assertEqual(len(warnings), 2) for warning in warnings: self.assertIn("yok sayıldı", warning) page = self.page("/?durum=MOR&dalga=W9") self.assertIn("yok sayıldı", page) self.assertIn("Uyarılar", page) def test_only_not_ready_filter(self) -> None: criteria, _ = fleet_data.parse_filter({"hazir_degil": ["1"]}) shown = fleet_data.filter_devices(self.snapshot.devices, criteria) self.assertTrue(shown) self.assertTrue(all(not device.is_ready for device in shown)) def test_counts_are_zero_filled_and_add_up(self) -> None: counts = fleet_data.state_counts(self.snapshot.devices) self.assertEqual(list(counts), list(STATE_WORDS)) self.assertEqual(sum(counts.values()), self.snapshot.total) self.assertEqual(counts, self.snapshot.counts) self.assertEqual(self.snapshot.ready_count + self.snapshot.not_ready_count, self.snapshot.total) def test_filter_matches_the_rendered_count(self) -> None: criteria, _ = fleet_data.parse_filter({"durum": ["YOK"]}) shown = fleet_data.filter_devices(self.snapshot.devices, criteria) page = self.page("/?durum=YOK") self.assertEqual(len(self.row_words(page)), len(shown)) self.assertTrue(all(word == "YOK" for word in self.row_words(page))) # -------------------------------------------------------------------------- # the first viewport # -------------------------------------------------------------------------- class TestFleetPage(PanelCase): def test_served_as_utf8_turkish_html(self) -> None: response = self.get("/") self.assertEqual(response.status, 200) self.assertEqual(response.content_type, "text/html; charset=utf-8") markup = response.body.decode("utf-8") self.assertIn('', markup) # Turkish characters must survive the byte round trip, not just the string. self.assertIn("doğrulandı".encode("utf-8"), response.body) self.assertEqual(response.content_length, len(response.body)) def test_first_viewport_regions_are_ordered(self) -> None: page = self.page("/") positions = [ page.index('data-region="header"'), page.index('data-region="summary"'), page.index('data-region="list"'), page.index('data-region="detail"'), ] self.assertEqual(positions, sorted(positions), "bölge sırası DESIGN.md'ye uymuyor") def test_header_carries_product_target_and_privilege(self) -> None: page = self.page("/") header = page[: page.index('data-region="summary"')] self.assertIn(web.PANEL_NAME, header) self.assertIn(web.PANEL_SURFACE, header) self.assertIn("Hedef", header) self.assertIn(f"Tüm filo · {self.snapshot.total} cihaz", header) self.assertIn("Yetki", header) self.assertIn("Salt-okunur", header) self.assertIn(self.read_only.reason, header) def test_privilege_level_is_the_right_most_header_readout(self) -> None: """docs/DESIGN.md: 'privilege level on the right -- never a buried sentence'.""" page = self.page("/") header = page[: page.index('data-region="summary"')] privilege = header.index("app-header__privilege") self.assertGreater(privilege, header.index("app-header__identity")) self.assertGreater(privilege, header.index("app-header__target")) self.assertGreater(privilege, header.index("app-header__actions")) def test_primary_action_sits_in_the_header_not_below_the_fold(self) -> None: page = self.page("/") self.assertLess( page.index("Filo durumunu yenile"), page.index('data-region="summary"'), "birincil eylem başlık bandında değil", ) self.assertIn('class="button button--primary"', page) def test_unprivileged_write_action_is_disabled_with_the_reason_on_the_control(self) -> None: page = self.page("/") self.assertIn('disabled aria-disabled="true" aria-describedby="gated-reason"', page) self.assertIn('id="gated-reason"', page) self.assertIn(self.read_only.reason, page) def test_every_state_word_appears_in_the_summary_strip(self) -> None: page = self.page("/") summary = page[page.index('data-region="summary"') : page.index('data-region="list"')] for word in STATE_WORDS: with self.subTest(word=word): self.assertIn(word, summary) def test_summary_strip_has_exactly_one_large_figure(self) -> None: page = self.page("/") self.assertEqual(page.count("summary__lead-figure"), 1) self.assertEqual( page.count("summary__cell-value"), len(fleet_data.STATE_VOCABULARY) ) counts = self.snapshot.counts summary = page[page.index('data-region="summary"') : page.index('data-region="list"')] self.assertIn(f'>{counts["HAZIR"]}<', summary) def test_every_row_carries_a_state_word_in_monospace_columns(self) -> None: page = self.page("/") self.assertEqual(len(self.row_words(page)), self.snapshot.total) for device in self.snapshot.devices: with self.subTest(device=device.device_id): self.assertIn( f'' f"{device.device_id}", page, ) self.assertIn(f'class="badge badge--state-{device.state_token_suffix}"', page) self.assertIn(f'{device.hostname}', page) def test_wave_column_names_the_wave_once_in_monospace(self) -> None: """The Dalga column is a data cell, and it names each wave exactly once.""" region = self.list_region(self.page("/")) rows = re.findall(r'(BF-[0-9]{8})", row) if match is None: self.fail(f"satırda cihaz kimliği yok: {row[:120]}") device = by_id[match.group(1)] cells = re.findall(r"]*>(.*?)", row, flags=re.S) self.assertEqual(len(cells), 5, row[:200]) self.assertEqual( cells[3], f'{device.wave_label}', row[:200] ) def test_rows_are_sorted_non_ready_first(self) -> None: words = self.row_words(self.page("/")) ready_flags = [ fleet_data.STATE_BY_WORD[word].state == "READY" for word in words ] self.assertEqual(ready_flags, sorted(ready_flags)) self.assertEqual(ready_flags[0], False) self.assertEqual(ready_flags[-1], True) def test_selected_row_uses_the_accent_soft_fill(self) -> None: page = self.page("/") self.assertEqual(page.count("fleet-row--selected"), 1) selected_row = page[page.index("fleet-row--selected") :] selected_row = selected_row[: selected_row.index("")] detail = page[page.index('data-region="detail"') :] device_id = re.search(r">(BF-[0-9]{8})", selected_row).group(1) self.assertIn(device_id, detail) css = (STATIC_DIR / "app.css").read_text(encoding="utf-8") self.assertIn(".fleet-row--selected td { background: var(--accent-soft); }", css) def test_default_selection_is_the_first_row_of_the_list(self) -> None: page = self.page("/") first_row = self.list_region(page) first_row = first_row[first_row.index("") :] device_id = re.search(r">(BF-[0-9]{8})", first_row).group(1) detail = page[page.index('data-region="detail"') :] self.assertIn(device_id, detail) self.assertIn("Hedef kimliği", detail) def test_detail_region_shows_state_identity_wave_and_channels(self) -> None: page = self.page("/?cihaz=BF-12010193") detail = page[page.index('data-region="detail"') :] device = next(d for d in self.snapshot.devices if d.device_id == "BF-12010193") self.assertIn(device.state_label, detail) self.assertIn(device.device_id, detail) self.assertIn(device.hostname, detail) self.assertIn(device.wave_code, detail) self.assertIn("Kanal doğrulaması", detail) for channel in fleet_data.CHANNELS: with self.subTest(channel=channel.label): self.assertIn(channel.label, detail) self.assertIn("Doğrulanan kanal: 4/4", detail) self.assertIn("doğrulandı", detail) def test_channel_status_words_are_shown_in_turkish(self) -> None: """Every channel status word reaches the screen, not only a colour.""" cases = { "BF-12010193": ("doğrulandı",), # all four verified "BF-12010194": ("bekliyor",), # RustDesk pending "BF-12010205": ("başarısız", "bilinmiyor"), # failed + unknown "BF-12010195": ("yok",), # never checked } for device_id, words in cases.items(): with self.subTest(device=device_id): page = self.page(f"/?cihaz={device_id}") detail = page[page.index('data-region="detail"') :] for word in words: self.assertIn(f">{word}", detail) def test_ready_device_detail_confirms_the_gate(self) -> None: page = self.page("/?cihaz=BF-12010193") self.assertIn("dört kanalın dördü de doğrulandı", page) self.assertNotIn("HAZIR için eksik kanallar", page) def test_not_ready_device_detail_names_the_blocking_channels(self) -> None: page = self.page("/?cihaz=BF-12010194") self.assertIn("HAZIR için eksik kanallar: RustDesk", page) self.assertIn("Doğrulanan kanal: 3/4", page) def test_hostname_selects_the_same_device_as_device_id(self) -> None: by_id = self.page("/?cihaz=BF-12010193") by_host = self.page("/?cihaz=bf-12010193") self.assertEqual(self.row_words(by_id), self.row_words(by_host)) self.assertIn("BF-12010193", by_host[by_host.index('data-region="detail"') :]) def test_unknown_device_id_is_reported_and_not_invented(self) -> None: page = self.page("/?cihaz=BF-99999999") detail = page[page.index('data-region="detail"') :] self.assertIn("BF-99999999", detail) self.assertIn("envanterde yok", detail.lower()) self.assertIn("uydurmaz", detail) def test_filter_is_reflected_in_the_list_and_the_header(self) -> None: page = self.page("/?durum=HAZIR") self.assertEqual(set(self.row_words(page)), {"HAZIR"}) self.assertIn("Durum HAZIR", page) self.assertIn(f"Gösterilen: {self.snapshot.ready_count}", page) def test_selection_outside_the_filter_is_flagged_not_hidden(self) -> None: page = self.page("/?durum=HAZIR&cihaz=BF-12010205") detail = page[page.index('data-region="detail"') :] self.assertIn("BF-12010205", detail) self.assertIn("geçerli filtreye uymuyor", detail) def test_empty_result_gets_a_turkish_note_and_keeps_the_header(self) -> None: page = self.page("/?durum=YOK&dalga=PROD") self.assertEqual(self.row_words(page), []) self.assertIn("Bu filtreye uyan cihaz yok", page) self.assertIn("Filtreyi temizle", page) self.assertIn('data-region="header"', page) def test_wave_strip_shows_every_wave_against_its_target(self) -> None: page = self.page("/") counts = fleet_data.wave_counts(self.snapshot.devices) for wave in fleet_data.WAVES: with self.subTest(wave=wave.code): self.assertIn( f'{wave.code} {counts[wave.code]}/{wave.target}', page, ) def test_demo_data_is_labelled_on_the_page(self) -> None: page = self.page("/") self.assertIn("DEMO VERİ", page) self.assertIn("sentetik", page) self.assertIn("hiçbir cihazı temsil etmez", page) self.assertIn("Veri kaynağı: sentetik demo veri", page) def test_inventory_file_source_is_labelled_on_the_page(self) -> None: document = { "schema_version": 1, "generated_at": NOW, "devices": [ { "dealer_id": "12010193", "wave": "P1", "state": "ENROLLED", "channels": {"ssh_over_wg": "verified"}, } ], } snapshot = self.snapshot_from(document) context = panel.PanelContext( snapshot=snapshot, privilege=self.read_only, server_info=self.info ) page = self.page("/", context=context) self.assertIn("ENVANTER", page) self.assertIn(snapshot.source_path, page) self.assertNotIn("DEMO VERİ", page) def test_error_source_says_veri_yok_and_never_shows_demo_data(self) -> None: snapshot = fleet_data.load_fleet("/yok/boyle/bir/dosya.json", env={}, now=NOW) context = panel.PanelContext( snapshot=snapshot, privilege=self.read_only, server_info=self.info ) page = self.page("/", context=context) self.assertIn("VERİ YOK", page) self.assertIn("Demo veriye düşülmedi", page) self.assertNotIn("DEMO VERİ", page) self.assertEqual(self.row_words(page), []) self.assertIn("Envanterde gösterilecek cihaz yok", page) def test_invalid_records_are_surfaced_with_their_reason(self) -> None: document = { "schema_version": 1, "devices": [{"dealer_id": "1201019", "wave": "P1", "state": "READY"}], } snapshot = self.snapshot_from(document) context = panel.PanelContext( snapshot=snapshot, privilege=self.read_only, server_info=self.info ) page = self.page("/", context=context) self.assertIn("Geçersiz kayıtlar", page) self.assertIn("8 hane", page) def test_every_visible_string_is_non_empty(self) -> None: for target in ("/", "/?durum=HAZIR", "/?cihaz=BF-99999999", "/hakkinda"): with self.subTest(target=target): self.assertEqual(empty_elements(self.page(target)), []) def test_error_pages_keep_the_frame_and_stay_readable(self) -> None: for target, status in (("/yok", 404),): with self.subTest(target=target): response = self.get(target) self.assertEqual(response.status, status) markup = response.body.decode("utf-8") self.assertEqual(empty_elements(markup), []) self.assertIn('data-region="header"', markup) def test_no_placeholder_or_python_none_leaks_into_the_page(self) -> None: for target in ("/", "/hakkinda", "/?cihaz=BF-12010193", "/?durum=MOR"): with self.subTest(target=target): page = self.page(target) self.assertNotIn("$", page) self.assertNotIn("None", page) self.assertNotIn("KeyError", page) def test_page_renders_without_a_live_server_context(self) -> None: """render_fleet_page is usable on its own (tests, --check, future CLI).""" page = render.render_fleet_page(self.snapshot) self.assertIn(' None: page = self.page("/hakkinda") self.assertIn(web.PANEL_VERSION, page) self.assertIn(render.PANEL_VERSION, page) self.assertIn("Panel sürümü", page) self.assertIn("127.0.0.1:8787", page) self.assertIn("Salt-okunur", page) self.assertIn(self.read_only.reason, page) self.assertIn(self.info.python_version, page) def test_reports_the_data_source_and_its_limits(self) -> None: page = self.page("/hakkinda") self.assertIn("Veri kaynağı", page) self.assertIn("sentetik demo veri", page) self.assertIn("kullanılmadı (demo veri)", page) self.assertIn(f"{self.snapshot.ready_count} hazır", page) self.assertIn("Okuma hatası", page) self.assertIn("yok", page) def test_lists_the_vocabulary_with_tokens_and_meanings(self) -> None: page = self.page("/hakkinda") for spec in fleet_data.STATE_VOCABULARY: with self.subTest(state=spec.state): self.assertIn(spec.word, page) self.assertIn(spec.token, page) self.assertIn(spec.meaning, page) def test_lists_every_wave_and_channel(self) -> None: page = self.page("/hakkinda") for wave in fleet_data.WAVES: with self.subTest(wave=wave.code): self.assertIn(wave.code, page) for channel in fleet_data.CHANNELS: with self.subTest(channel=channel.key): self.assertIn(channel.key, page) self.assertIn(channel.label, page) def test_states_the_panel_rules(self) -> None: page = self.page("/hakkinda") self.assertGreaterEqual(len(render.PANEL_RULES), 5) for rule in render.PANEL_RULES: with self.subTest(rule=rule[:30]): self.assertTrue(rule.strip()) self.assertIn(rule[:24], page) self.assertIn("Panel kuralları", page) def test_full_privilege_level_is_distinct_and_honest(self) -> None: page = self.page("/", context=self.full_context) self.assertIn("badge--privilege-full", page) self.assertIn("Tam yetki", page) self.assertIn("yazma uç noktası uygulanmadı", page) self.assertNotIn("badge--privilege-read-only", page) def test_about_page_has_no_external_url(self) -> None: page = self.page("/hakkinda") self.assertNotIn("http://", page) self.assertNotIn("https://", page) # -------------------------------------------------------------------------- # routing and the privilege gate # -------------------------------------------------------------------------- class TestRoutingAndGate(PanelCase): def test_only_read_methods_are_served(self) -> None: for method in ("POST", "PUT", "PATCH", "DELETE", "OPTIONS", "TRACE"): with self.subTest(method=method): response = self.get("/", method) self.assertEqual(response.status, 405) markup = response.body.decode("utf-8") self.assertIn("Yöntem reddedildi", markup) self.assertIn(method, markup) self.assertIn("yalnız okuma yapar", markup) headers = dict(response.headers) self.assertEqual(headers.get("Allow"), "GET, HEAD") def test_write_methods_are_refused_even_with_full_privilege(self) -> None: response = self.get("/", "POST", self.full_context) self.assertEqual(response.status, 405) def test_head_returns_the_same_length_without_a_body(self) -> None: head = self.get("/", "HEAD") get = self.get("/", "GET") self.assertEqual(head.status, 200) self.assertEqual(head.body, b"") self.assertEqual(head.content_length, get.content_length) self.assertEqual(head.content_type, get.content_type) def test_static_assets_are_served_from_disk_byte_for_byte(self) -> None: for name in ("tokens.css", "app.css"): with self.subTest(name=name): response = self.get(f"/static/{name}") self.assertEqual(response.status, 200) self.assertEqual(response.content_type, "text/css; charset=utf-8") self.assertEqual(response.body, (STATIC_DIR / name).read_bytes()) def test_unknown_static_asset_is_a_404(self) -> None: response = self.get("/static/gizli.txt") self.assertEqual(response.status, 404) self.assertIn("Sayfa yok", response.body.decode("utf-8")) def test_path_traversal_is_refused(self) -> None: for target in ( "/static/../server.py", "/static/..%2fserver.py", "/static/%2e%2e/fleet_data.py", "/../web/server.py", "/static/.%2e/%2e%2e/etc/passwd", ): with self.subTest(target=target): response = self.get(target) self.assertEqual(response.status, 404) body = response.body.decode("utf-8") self.assertNotIn("BaseHTTPRequestHandler", body) self.assertNotIn("route(context", body) def test_unknown_path_is_a_turkish_404(self) -> None: response = self.get("/boyle-bir-sayfa-yok") self.assertEqual(response.status, 404) markup = response.body.decode("utf-8") self.assertIn("Sayfa yok", markup) self.assertIn("/boyle-bir-sayfa-yok", markup) def test_security_headers_keep_the_panel_local_and_script_free(self) -> None: headers = dict(self.get("/").headers) self.assertEqual(headers["X-Content-Type-Options"], "nosniff") self.assertEqual(headers["Referrer-Policy"], "no-referrer") csp = headers["Content-Security-Policy"] self.assertIn("default-src 'self'", csp) self.assertIn("script-src 'none'", csp) self.assertIn("form-action 'self'", csp) self.assertNotIn("http", csp) self.assertEqual(headers["Cache-Control"], "no-store") def test_route_is_pure_and_repeatable(self) -> None: targets = ("/", "/hakkinda", "/static/app.css", "/?durum=HAZIR&q=1201", "/yok", "/static/../x") for target in targets: with self.subTest(target=target): first = self.get(target) second = self.get(target) self.assertEqual(first, second) def test_bogus_query_values_do_not_crash_the_page(self) -> None: for target in ( "/?q=&durum=&dalga=&cihaz=&hazir_degil=abc", "/?durum=READY&durum=YOK", "/?q=%C4%B0stanbul%20%2F%20test", "/?cihaz=" + "x" * 500, ): with self.subTest(target=target[:40]): response = self.get(target) self.assertEqual(response.status, 200) self.assertEqual(empty_elements(response.body.decode("utf-8")), []) def test_a_full_sweep_of_every_endpoint_writes_nothing(self) -> None: """Read-only is a property of the surface, not a promise in a docstring.""" before = tree_fingerprint(WEB_DIR) requests = ( ("GET", "/"), ("GET", "/filo"), ("GET", "/fleet"), ("GET", "/hakkinda"), ("GET", "/hakkinda/"), ("GET", "/about"), ("GET", "/static/tokens.css"), ("GET", "/static/app.css"), ("GET", "/?q=1201&durum=HAZIR&dalga=P1&hazir_degil=1&cihaz=BF-12010193"), ("GET", "/yok"), ("POST", "/"), ("PUT", "/hakkinda"), ("DELETE", "/static/app.css"), ("HEAD", "/"), ) for method, target in requests: with self.subTest(method=method, target=target): response = self.get(target, method) self.assertIn(response.status, (200, 404, 405)) self.assertEqual(tree_fingerprint(WEB_DIR), before) if __name__ == "__main__": unittest.main(verbosity=2)