import os from pathlib import Path from unittest.mock import patch import pytest @pytest.fixture def client(): with patch("lib.logging.setup_logging"): from webui.server import app app.config["TESTING"] = True return app.test_client() class TestSPARoutes: def test_root_serves_index(self, client): resp = client.get("/") assert resp.status_code == 200 assert b'id="app"' in resp.data def test_spa_unknown_path_404(self, client): resp = client.get("/dashboard") assert resp.status_code == 404 def test_spa_unknown_path_404_other(self, client): resp = client.get("/zones") assert resp.status_code == 404 def test_api_routes_still_work(self, client): resp = client.get("/api/firewall/zones") assert resp.status_code in (401, 500) data = resp.get_json() assert data is not None assert data.get("ok") is False assert data.get("error") == "unauthorized" class TestWsUrlGeneration: def test_ws_url_ipv4_host(self, client): resp = client.get("/", headers={"Host": "192.168.1.1:9090"}) assert b"ws://192.168.1.1:9090/ws" in resp.data def test_ws_url_ipv6_host(self, client): resp = client.get("/", headers={"Host": "[::1]:9090"}) assert b"ws://[::1]:9090/ws" in resp.data class TestBlueprintsRegistered: def test_all_blueprints_registered(self, client): from webui.server import BLUEPRINTS assert len(BLUEPRINTS) == 9 names = [name for name, _ in BLUEPRINTS] assert "auth" in names assert "firewall" in names assert "network" in names assert "dhcp" in names assert "proxy" in names assert "certs" in names assert "wireguard" in names assert "logs" in names class TestGroupWriteHandler: def test_creates_file_with_group_write(self, tmp_path: Path) -> None: """GroupWriteHandler creates new log files with group-write (0o664).""" import contextlib from logging.handlers import RotatingFileHandler log_file = tmp_path / "test.log" old = os.umask(0o022) try: class GroupWriteHandler(RotatingFileHandler): def _open(self): with contextlib.suppress(OSError): os.chmod(self.baseFilename, 0o664) saved = os.umask(0o002) try: fd = os.open( self.baseFilename, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o664, ) finally: os.umask(saved) return os.fdopen(fd, "a", errors="backslashreplace") fh = GroupWriteHandler(str(log_file)) fh.close() finally: os.umask(old) mode = os.stat(log_file).st_mode & 0o777 assert mode == 0o664, f"Expected 0o664, got {oct(mode)}"