File size: 3,114 Bytes
f833573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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