V10.516 補 Webcrumbs host data 授權回歸測試
All checks were successful
CD Pipeline / deploy (push) Successful in 1m6s
All checks were successful
CD Pipeline / deploy (push) Successful in 1m6s
This commit is contained in:
151
tests/test_webcrumbs_host_data_runtime_auth.py
Normal file
151
tests/test_webcrumbs_host_data_runtime_auth.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from flask import Flask
|
||||
|
||||
import auth
|
||||
from routes import system_public_routes as routes
|
||||
|
||||
|
||||
def _make_app(monkeypatch):
|
||||
app = Flask(__name__)
|
||||
app.secret_key = "test-secret"
|
||||
app.register_blueprint(routes.system_public_bp)
|
||||
monkeypatch.setattr(auth, "DISABLE_LOGIN", True)
|
||||
return app
|
||||
|
||||
|
||||
def test_webcrumbs_host_data_api_blocks_when_login_disabled_without_internal_key(monkeypatch):
|
||||
app = _make_app(monkeypatch)
|
||||
monkeypatch.setenv("INTERNAL_API_KEY", "test-internal-key")
|
||||
|
||||
called = {"value": False}
|
||||
|
||||
def fail_if_called(limit=5):
|
||||
called["value"] = True
|
||||
return {}
|
||||
|
||||
monkeypatch.setattr(routes, "build_webcrumbs_seed_data", fail_if_called)
|
||||
|
||||
response = app.test_client().get("/api/webcrumbs/marketplace-host-data")
|
||||
|
||||
assert response.status_code == 401
|
||||
payload = response.get_json()
|
||||
assert payload["success"] is False
|
||||
assert payload["error"] == "auth_required"
|
||||
assert payload["boundary"]["auth_required"] is True
|
||||
assert payload["boundary"]["writes_database"] is False
|
||||
assert payload["boundary"]["calls_llm"] is False
|
||||
assert payload["boundary"]["fetches_external"] is False
|
||||
assert called["value"] is False
|
||||
|
||||
|
||||
def test_webcrumbs_host_data_api_allows_internal_key_when_login_disabled(monkeypatch):
|
||||
app = _make_app(monkeypatch)
|
||||
monkeypatch.setenv("INTERNAL_API_KEY", "test-internal-key")
|
||||
|
||||
seed_payload = {
|
||||
"marketSnapshot": [
|
||||
{
|
||||
"name": "SKU-1 exact price alert",
|
||||
"price": 250,
|
||||
"change_pct": 12.5,
|
||||
"freshness_status": "price_alert_exact",
|
||||
}
|
||||
],
|
||||
"aiCandidate": {
|
||||
"ticker": "SKU-1",
|
||||
"name": "exact alert",
|
||||
"thesis": "MOMO NT$300 vs PChome NT$250",
|
||||
},
|
||||
"metadata": {
|
||||
"source": "competitor_intel_repository",
|
||||
"writes_database": False,
|
||||
"calls_llm": False,
|
||||
"fetches_external": False,
|
||||
},
|
||||
}
|
||||
captured = {}
|
||||
|
||||
def fake_build_webcrumbs_seed_data(limit=5):
|
||||
captured["limit"] = limit
|
||||
return seed_payload
|
||||
|
||||
monkeypatch.setattr(routes, "build_webcrumbs_seed_data", fake_build_webcrumbs_seed_data)
|
||||
|
||||
response = app.test_client().get(
|
||||
"/api/webcrumbs/marketplace-host-data?limit=99",
|
||||
headers={"X-Internal-Key": "test-internal-key"},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
payload = response.get_json()
|
||||
assert captured["limit"] == 8
|
||||
assert payload["success"] is True
|
||||
assert payload["data"] == seed_payload
|
||||
assert payload["metadata"]["source"] == "competitor_intel_repository"
|
||||
assert payload["boundary"]["auth_required"] is True
|
||||
assert payload["boundary"]["writes_database"] is False
|
||||
assert payload["boundary"]["calls_llm"] is False
|
||||
assert payload["boundary"]["fetches_external"] is False
|
||||
|
||||
|
||||
def test_webcrumbs_page_uses_auth_required_seed_when_login_disabled_without_sensitive_access(monkeypatch):
|
||||
app = _make_app(monkeypatch)
|
||||
monkeypatch.setenv("INTERNAL_API_KEY", "test-internal-key")
|
||||
|
||||
captured = {}
|
||||
|
||||
def fake_build_external_tool_payload(kind, include_host_data=True):
|
||||
captured["kind"] = kind
|
||||
captured["include_host_data"] = include_host_data
|
||||
return {
|
||||
"key": kind,
|
||||
"plugin_seed_data": {
|
||||
"marketSnapshot": [
|
||||
{
|
||||
"name": "MOMO/PChome host data requires authentication",
|
||||
"freshness_status": "auth_required",
|
||||
}
|
||||
],
|
||||
"aiCandidate": {
|
||||
"name": "MOMO/PChome host data locked",
|
||||
"release_status": "blocked",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def fake_render_template(template_name, **context):
|
||||
return str(context["tool"]["plugin_seed_data"])
|
||||
|
||||
monkeypatch.setattr(routes, "build_external_tool_payload", fake_build_external_tool_payload)
|
||||
monkeypatch.setattr(routes, "render_template", fake_render_template)
|
||||
|
||||
response = app.test_client().get("/webcrumbs")
|
||||
|
||||
body = response.get_data(as_text=True)
|
||||
assert response.status_code == 200
|
||||
assert captured == {"kind": "webcrumbs", "include_host_data": False}
|
||||
assert "auth_required" in body
|
||||
assert "MOMO NT$" not in body
|
||||
assert "PChome NT$" not in body
|
||||
|
||||
|
||||
def test_webcrumbs_page_allows_sensitive_seed_for_logged_in_session(monkeypatch):
|
||||
app = _make_app(monkeypatch)
|
||||
|
||||
captured = {}
|
||||
|
||||
def fake_build_external_tool_payload(kind, include_host_data=True):
|
||||
captured["kind"] = kind
|
||||
captured["include_host_data"] = include_host_data
|
||||
return {"key": kind, "plugin_seed_data": {"release_status": "review_required"}}
|
||||
|
||||
monkeypatch.setattr(routes, "build_external_tool_payload", fake_build_external_tool_payload)
|
||||
monkeypatch.setattr(routes, "render_template", lambda template_name, **context: "ok")
|
||||
|
||||
client = app.test_client()
|
||||
with client.session_transaction() as session:
|
||||
session["logged_in"] = True
|
||||
|
||||
response = client.get("/webcrumbs")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert captured == {"kind": "webcrumbs", "include_host_data": True}
|
||||
Reference in New Issue
Block a user