bbscanner / tests /test_clear_scope.py
Wuhp
Allow safe session-scoped clearing of imported scope assets
f833573
Raw History Blame Contribute Delete
3.11 kB
from unittest.mock import patch
from fastapi.testclient import TestClient
from app import main
def test_clear_scope_deletes_only_session_assets_preserves_findings():
original_assets, original_jobs = main.assets, main.jobs
main.assets, main.jobs = {}, {}
try:
with TestClient(main.app) as first, TestClient(main.app) as second:
sid_a = first.get("/api/assets").headers["X-ASFB-Session"]
sid_b = second.get("/api/assets").headers["X-ASFB-Session"]
assert sid_a != sid_b
main.assets["a1"] = {"id": "a1", "owner": sid_a, "name": "https://a.example"}
main.assets["a2"] = {"id": "a2", "owner": sid_a, "name": "https://b.example"}
main.assets["b1"] = {"id": "b1", "owner": sid_b, "name": "https://other.example"}
main.jobs["historical"] = {
"id": "historical", "owner": sid_a, "asset_id": "a1",
"status": "completed", "alerts": [{"source": "zap", "name": "example"}],
}
result = first.delete("/api/assets")
assert result.status_code == 200
assert result.json()["cleared"] == 2
assert first.get("/api/assets").json()["assets"] == []
assert len(second.get("/api/assets").json()["assets"]) == 1
assert main.jobs["historical"]["alerts"][0]["name"] == "example"
assert main.jobs["historical"]["status"] == "completed"
assert first.delete("/api/assets").json()["cleared"] == 0
finally:
main.assets, main.jobs = original_assets, original_jobs
def test_scope_clear_only_cancels_jobs_referencing_removed_assets():
original_assets, original_jobs = main.assets, main.jobs
main.assets, main.jobs = {}, {}
try:
with TestClient(main.app) as client:
sid = client.get("/api/assets").headers["X-ASFB-Session"]
main.assets["target"] = {"id": "target", "owner": sid, "name": "https://example.org"}
main.jobs["queued"] = {
"id": "queued", "owner": sid, "asset_id": "target", "status": "queued"
}
main.jobs["other"] = {
"id": "other", "owner": sid, "asset_id": "unrelated", "status": "queued"
}
with patch.object(main, "cancel_owned_jobs", return_value={
"cancelled_queued": 1, "cancellation_requested_running": 0
}) as cancel:
result = client.delete("/api/assets")
assert result.status_code == 200
assert result.json()["cancelled_queued"] == 1
cancel.assert_called_once_with(sid, {"queued"})
assert "target" not in main.assets
finally:
main.assets, main.jobs = original_assets, original_jobs
def test_scope_clear_dashboard_button_is_distinct_from_clear_selection():
from pathlib import Path
source = Path("app/index.html").read_text()
assert 'id="clearScope"' in source
assert "async function clearScope()" in source
assert "api('/assets',{method:'DELETE'})" in source
assert "function clearSelection()" in source