88 lines
3.5 KiB
Python
88 lines
3.5 KiB
Python
import unittest
|
|
|
|
from app import create_app
|
|
|
|
|
|
class ApiTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.snapshot = {
|
|
"as_of": "2026-08-21",
|
|
"source": {
|
|
"source_id": "fixture.tourism",
|
|
"source_url": "https://example.invalid/tourism",
|
|
"published_at": "2026-08-21T08:00:00Z",
|
|
"retrieved_at": "2026-08-21T08:05:00Z",
|
|
"vintage_id": "fixture-1",
|
|
},
|
|
"observations": [
|
|
{"metric_key": "arrivals_yoy", "value": 12, "expected": 8, "scale": 2, "unit": "percent"},
|
|
],
|
|
"exposures": [
|
|
{"symbol": "AOT", "coefficient": 1.0, "confidence": 0.95, "evidence": "airport"},
|
|
{"symbol": "PTT", "coefficient": -0.2, "confidence": 0.60, "evidence": "control"},
|
|
],
|
|
}
|
|
self.app = create_app({"TESTING": True, "SNAPSHOT": self.snapshot, "PAPER_WRITE_TOKEN": "test-token"})
|
|
self.client = self.app.test_client()
|
|
|
|
def _login_paper(self):
|
|
response = self.client.post("/api/v1/auth/paper", json={"token": "test-token"})
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_health_reports_research_mode(self):
|
|
response = self.client.get("/api/v1/health")
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(response.get_json()["mode"], "research")
|
|
|
|
def test_summary_contains_lineage_and_signal_counts(self):
|
|
response = self.client.get("/api/v1/dashboard/summary")
|
|
body = response.get_json()
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(body["data_health"]["vintage_id"], "fixture-1")
|
|
self.assertEqual(body["data_health"]["status"], "fixture")
|
|
self.assertEqual(body["signal_summary"]["total"], 2)
|
|
self.assertEqual(body["signal_summary"]["long"], 1)
|
|
self.assertEqual(body["signal_summary"]["short"], 1)
|
|
|
|
def test_paper_ledger_requires_token(self):
|
|
response = self.client.post(
|
|
"/api/v1/paper/ledger",
|
|
json={"symbol": "AOT", "target_weight": 0.1, "assumed_price": 10},
|
|
)
|
|
self.assertEqual(response.status_code, 401)
|
|
|
|
def test_paper_ledger_rejects_invalid_paper_token(self):
|
|
response = self.client.post("/api/v1/auth/paper", json={"token": "wrong-token"})
|
|
self.assertEqual(response.status_code, 401)
|
|
|
|
def test_paper_ledger_rejects_non_finite_price(self):
|
|
self._login_paper()
|
|
response = self.client.post(
|
|
"/api/v1/paper/ledger",
|
|
json={"symbol": "AOT", "target_weight": 0.1, "assumed_price": "NaN"},
|
|
)
|
|
self.assertEqual(response.status_code, 400)
|
|
|
|
def test_paper_ledger_rejects_unknown_symbol(self):
|
|
self._login_paper()
|
|
response = self.client.post(
|
|
"/api/v1/paper/ledger",
|
|
json={"symbol": "UNKNOWN", "target_weight": 0.1, "assumed_price": 10},
|
|
)
|
|
self.assertEqual(response.status_code, 400)
|
|
|
|
def test_paper_ledger_records_valid_entry(self):
|
|
self._login_paper()
|
|
response = self.client.post(
|
|
"/api/v1/paper/ledger",
|
|
json={"symbol": "AOT", "target_weight": 0.1, "assumed_price": 60},
|
|
)
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertEqual(response.get_json()["entry"]["symbol"], "AOT")
|
|
ledger = self.client.get("/api/v1/paper/ledger").get_json()["entries"]
|
|
self.assertEqual(len(ledger), 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|