ui: локальный Tabler dashboard + 150 проверенных TG-источников и probe 595 каналов
This commit is contained in:
@@ -454,10 +454,10 @@ def test_http_exports_match_feed_filters_and_item_find(monkeypatch):
|
||||
server.server_close()
|
||||
thread.join(timeout=5)
|
||||
|
||||
def test_web_has_free_panel_block():
|
||||
"""Вкладка абузов обязана показывать free-панели new-api."""
|
||||
html = open(os.path.join(ROOT, "web", "index.html"), encoding="utf-8").read()
|
||||
def test_web_has_local_dashboard_and_free_panel_block():
|
||||
"""The ready-made UI stays local and retains the free-panel discovery feature."""
|
||||
html = (ROOT / "web" / "index.html").read_text(encoding="utf-8")
|
||||
assert "loadPanels" in html
|
||||
assert "/api/panels" in html
|
||||
assert "pn-grid" in html
|
||||
assert ".pn-grid{" in html
|
||||
assert "/assets/vendor/tabler/tabler.min.css" in html
|
||||
assert "/assets/vendor/tabler/tabler.min.js" in html
|
||||
|
||||
77
tests/test_static_assets.py
Normal file
77
tests/test_static_assets.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""Local UI dependencies are served without exposing project data."""
|
||||
import http.client
|
||||
import threading
|
||||
from http.server import ThreadingHTTPServer
|
||||
|
||||
import pytest
|
||||
|
||||
from omni import serve
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def static_server(tmp_path, monkeypatch):
|
||||
web = tmp_path / "web"
|
||||
vendor = web / "vendor" / "tabler"
|
||||
vendor.mkdir(parents=True)
|
||||
(vendor / "tabler.min.css").write_text("body{color:#123}", encoding="utf-8")
|
||||
(vendor / "tabler.min.js").write_text("window.tabler={};", encoding="utf-8")
|
||||
(web / "index.html").write_text("<html>panel</html>", encoding="utf-8")
|
||||
(web / "private.js").write_text("private", encoding="utf-8")
|
||||
(vendor / "secret.json").write_text('{"secret":"test-only"}', encoding="utf-8")
|
||||
(tmp_path / "outside.js").write_text("outside", encoding="utf-8")
|
||||
monkeypatch.setattr(serve, "WEB", web)
|
||||
server = ThreadingHTTPServer(("127.0.0.1", 0), serve.Handler)
|
||||
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||||
thread.start()
|
||||
|
||||
def get(path):
|
||||
connection = http.client.HTTPConnection("127.0.0.1", server.server_port, timeout=5)
|
||||
try:
|
||||
connection.request("GET", path)
|
||||
response = connection.getresponse()
|
||||
return response.status, dict(response.getheaders()), response.read()
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
try:
|
||||
yield get
|
||||
finally:
|
||||
server.shutdown()
|
||||
server.server_close()
|
||||
thread.join(timeout=5)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name,ctype,expected", [
|
||||
("tabler.min.css", "text/css; charset=utf-8", b"body{color:#123}"),
|
||||
("tabler.min.js", "text/javascript; charset=utf-8", b"window.tabler={};"),
|
||||
])
|
||||
def test_local_template_assets(static_server, name, ctype, expected):
|
||||
status, headers, body = static_server("/assets/vendor/tabler/" + name + "?v=1.7.1")
|
||||
assert status == 200 and body == expected
|
||||
assert headers["Content-Type"] == ctype
|
||||
assert headers["X-Content-Type-Options"] == "nosniff"
|
||||
assert int(headers["Content-Length"]) == len(expected)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", [
|
||||
"/assets/vendor/tabler/missing.js",
|
||||
"/assets/vendor/tabler/",
|
||||
"/assets/vendor/tabler/secret.json",
|
||||
"/assets/private.js",
|
||||
"/assets/index.html",
|
||||
"/assets/vendor/../../private.js",
|
||||
"/assets/vendor/%2e%2e/%2e%2e/outside.js",
|
||||
"/assets/%2foutside.js",
|
||||
"/assets/vendor/..%5c..%5cprivate.js",
|
||||
"/assets/vendor/%00.js",
|
||||
])
|
||||
def test_assets_reject_private_files_and_traversal(static_server, path):
|
||||
status, _, body = static_server(path)
|
||||
assert status == 404
|
||||
assert body == b"not found"
|
||||
|
||||
|
||||
def test_index_still_served(static_server):
|
||||
status, headers, body = static_server("/")
|
||||
assert status == 200 and body == b"<html>panel</html>"
|
||||
assert headers["Content-Type"].startswith("text/html")
|
||||
Reference in New Issue
Block a user