aboutsummaryrefslogtreecommitdiff
path: root/lib/project/tests/test_gui_assets.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-09-12 15:25:06 -0400
committerhistoria <historiavg@proton.me>2026-09-12 15:25:06 -0400
commit464edbc4fd658728f06d3a7d98340aa28ff3e3ec (patch)
treea182f62ef0365f2c2143f88436de78a03d752367 /lib/project/tests/test_gui_assets.py
parent1bbe59f78be9a8355bb0bee2bc8ab14ca42ac71c (diff)
downloadproducer-464edbc4fd658728f06d3a7d98340aa28ff3e3ec.tar.gz
feat: slop web gui
Diffstat (limited to 'lib/project/tests/test_gui_assets.py')
-rw-r--r--lib/project/tests/test_gui_assets.py46
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/project/tests/test_gui_assets.py b/lib/project/tests/test_gui_assets.py
new file mode 100644
index 0000000..b7f949a
--- /dev/null
+++ b/lib/project/tests/test_gui_assets.py
@@ -0,0 +1,46 @@
+"""Packaged, CSP-compatible frontend assets do not require a bundler or CDN."""
+from html.parser import HTMLParser
+
+import pytest
+
+pytest.importorskip("fastapi")
+from fastapi.testclient import TestClient
+
+from producer.gui import create_app
+
+
+class AssetReferences(HTMLParser):
+ def __init__(self):
+ super().__init__()
+ self.scripts = []
+ self.stylesheets = []
+ self.inline_attributes = []
+
+ def handle_starttag(self, tag, attrs):
+ attrs = dict(attrs)
+ self.inline_attributes.extend(name for name in attrs if name == "style" or name.startswith("on"))
+ if tag == "script":
+ self.scripts.append(attrs.get("src"))
+ if tag == "link" and attrs.get("rel") == "stylesheet":
+ self.stylesheets.append(attrs.get("href"))
+
+
+def test_gui_packaged_external_assets_and_guided_workflow(tmp_path):
+ with TestClient(create_app(tmp_path, 8765, "test-token"), base_url="http://127.0.0.1:8765") as client:
+ page = client.get("/")
+ assert page.status_code == 200
+ parser = AssetReferences()
+ parser.feed(page.text)
+ assert parser.scripts == ["/assets/app.js"]
+ assert parser.stylesheets == ["/assets/style.css"]
+ assert not parser.inline_attributes
+ assert "unsafe-inline" not in page.headers["Content-Security-Policy"]
+ assert "Approximate sound comparison, not an exact export preview." in page.text
+ for name in ("Choose your recording", "Try a short passage", "Compare the sound", "Export the full recording"):
+ assert name in page.text
+ for path in parser.scripts + parser.stylesheets + ["/assets/state.js"]:
+ response = client.get(path)
+ assert response.status_code == 200, path
+ assert response.headers["Cache-Control"] == "no-store"
+ assert len(response.content) > 100
+ assert client.get("/api/schema").status_code == 401