Files
ai-exchange/tests/unit/test_api_static_server.py
T
2026-04-30 01:15:28 +08:00

103 lines
4.5 KiB
Python

import os
import shutil
import subprocess
import unittest
os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://user:pass@localhost:5432/ai_ict_test")
from src.api.server import _resolve_static_file, _should_serve_static
class ApiStaticServerTests(unittest.TestCase):
def test_root_is_treated_as_static(self) -> None:
self.assertTrue(_should_serve_static("/"))
self.assertTrue(str(_resolve_static_file("/")).endswith("src/web/index.html"))
def test_static_asset_path_is_resolved(self) -> None:
self.assertTrue(_should_serve_static("/static/app.js"))
self.assertTrue(str(_resolve_static_file("/static/app.js")).endswith("src/web/app.js"))
def test_training_lab_is_treated_as_static(self) -> None:
self.assertTrue(_should_serve_static("/training"))
self.assertTrue(str(_resolve_static_file("/training")).endswith("src/web/training/index.html"))
self.assertTrue(_should_serve_static("/training/static/training.js"))
self.assertTrue(str(_resolve_static_file("/training/static/training.js")).endswith("src/web/training/training.js"))
def test_static_path_rejects_escape(self) -> None:
self.assertIsNone(_resolve_static_file("/static/../../README.md"))
self.assertIsNone(_resolve_static_file("/training/static/../../README.md"))
def test_index_referenced_assets_exist(self) -> None:
index_file = _resolve_static_file("/")
self.assertIsNotNone(index_file)
index_html = index_file.read_text(encoding="utf-8")
for asset in ("/static/styles.css", "/static/app.js"):
with self.subTest(asset=asset):
self.assertIn(asset, index_html)
asset_file = _resolve_static_file(asset)
self.assertIsNotNone(asset_file)
self.assertTrue(asset_file.exists())
def test_training_index_referenced_assets_exist(self) -> None:
index_file = _resolve_static_file("/training")
self.assertIsNotNone(index_file)
index_html = index_file.read_text(encoding="utf-8")
for asset in ("/training/static/training.css", "/training/static/training.js"):
with self.subTest(asset=asset):
self.assertIn(asset, index_html)
asset_file = _resolve_static_file(asset)
self.assertIsNotNone(asset_file)
self.assertTrue(asset_file.exists())
def test_training_lab_draws_mss_answer_overlay(self) -> None:
app_file = _resolve_static_file("/training/static/training.js")
self.assertIsNotNone(app_file)
app_js = app_file.read_text(encoding="utf-8")
self.assertIn("broken_level", app_js)
self.assertIn("MSS", app_js)
self.assertIn("drawPriceLabel", app_js)
def test_training_lab_surfaces_attempt_history(self) -> None:
app_file = _resolve_static_file("/training/static/training.js")
self.assertIsNotNone(app_file)
app_js = app_file.read_text(encoding="utf-8")
self.assertIn("/training/attempts/history", app_js)
self.assertIn("/training/attempts/${attemptId}", app_js)
self.assertIn("Recent attempts", app_js)
self.assertIn("attempt-history-item", app_js)
@unittest.skipIf(shutil.which("node") is None, "node is required for JS syntax checks")
def test_dashboard_javascript_syntax_is_valid(self) -> None:
app_file = _resolve_static_file("/static/app.js")
self.assertIsNotNone(app_file)
result = subprocess.run(["node", "--check", str(app_file)], capture_output=True, text=True, check=False)
self.assertEqual(result.returncode, 0, result.stderr + result.stdout)
@unittest.skipIf(shutil.which("node") is None, "node is required for JS syntax checks")
def test_training_lab_javascript_syntax_is_valid(self) -> None:
app_file = _resolve_static_file("/training/static/training.js")
self.assertIsNotNone(app_file)
result = subprocess.run(["node", "--check", str(app_file)], capture_output=True, text=True, check=False)
self.assertEqual(result.returncode, 0, result.stderr + result.stdout)
def test_dashboard_surfaces_executed_backtest_sample_size(self) -> None:
app_file = _resolve_static_file("/static/app.js")
self.assertIsNotNone(app_file)
app_js = app_file.read_text(encoding="utf-8")
self.assertIn("executed_signals", app_js)
self.assertIn("executed_expectancy_r", app_js)
self.assertIn("Latest Executed", app_js)
if __name__ == "__main__":
unittest.main()