8c13ad55ce
- update-vendor.sh now creates webui/vendor symlinks (htm.js) - install.sh calls update-vendor.sh after package install - Add vendor/.empty and webui/vendor/.empty as directory placeholders in git
112 lines
3.5 KiB
Python
112 lines
3.5 KiB
Python
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 (200, 500)
|
|
|
|
|
|
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 TestApiStatusAll:
|
|
@patch("webui.server.get")
|
|
def test_success(self, mock_get, client):
|
|
mock_get.return_value = {"firewall": {"zones": {}}, "dnsmasq": {}}
|
|
resp = client.get("/api/status/all")
|
|
assert resp.status_code == 200
|
|
data = resp.get_json()
|
|
assert data["ok"] is True
|
|
assert "firewall" in data["data"]
|
|
|
|
@patch("webui.server.get")
|
|
def test_error(self, mock_get, client):
|
|
mock_get.side_effect = RuntimeError("connection refused")
|
|
resp = client.get("/api/status/all")
|
|
assert resp.status_code == 500
|
|
data = resp.get_json()
|
|
assert data["ok"] is False
|
|
|
|
|
|
class TestBlueprintsRegistered:
|
|
def test_all_blueprints_registered(self, client):
|
|
from webui.server import BLUEPRINTS
|
|
|
|
assert len(BLUEPRINTS) == 8
|
|
names = [name for name, _ in BLUEPRINTS]
|
|
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)}"
|