python / test_storage.py
import json
from pathlib import Path
import httpx
import pytest
import server
def mock_scan(monkeypatch, tmp_path):
monkeypatch.setenv("WEB_SECURITY_MCP_REPORT_DIR", str(tmp_path / "reports"))
response = httpx.Response(200, headers={"content-type": "text/html", "set-cookie": "PHPSESSID=PRIVATE_SENTINEL"},
text='<script src="https://cdn.example/a.js"></script>',
request=httpx.Request("GET", "https://example.com/"))
monkeypatch.setattr(server, "_fetch", lambda url: (response, [url]))
@pytest.mark.parametrize("include_markdown", [False, True])
def test_scan_saves_exact_complete_result(monkeypatch, tmp_path, include_markdown):
mock_scan(monkeypatch, tmp_path)
result = server.scan_url("https://example.com/", include_review_markdown=include_markdown)
assert next(iter(result)) == "saved_report"
artifact = result["saved_report"]
path = Path(artifact["path"])
assert artifact["status"] == "saved" and path.is_absolute()
assert path.parent == tmp_path / "reports"
raw = path.read_text(encoding="utf-8")
assert json.loads(raw) == result
assert "PRIVATE_SENTINEL" not in raw
assert ("review_markdown" in result) is include_markdown
assert not list(path.parent.glob("*.tmp"))
def test_saved_json_exceeds_copy_limit_and_repeated_scans_do_not_overwrite(monkeypatch, tmp_path):
mock_scan(monkeypatch, tmp_path)
analyze = server.analyze_response
def large_result(*args, **kwargs):
report = analyze(*args, **kwargs)
report["offline_test_payload"] = "日本語" * 20000
return report
monkeypatch.setattr(server, "analyze_response", large_result)
first = server.scan_url("https://example.com/")
second = server.scan_url("https://example.com/")
assert first["saved_report"]["path"] != second["saved_report"]["path"]
for result in [first, second]:
raw = Path(result["saved_report"]["path"]).read_text(encoding="utf-8")
assert len(raw) > 50000
assert json.loads(raw) == result
def test_storage_failure_preserves_findings_and_cleans_temporary_file(monkeypatch, tmp_path):
mock_scan(monkeypatch, tmp_path)
def fail(*args):
raise OSError("synthetic disk failure")
monkeypatch.setattr(server.os, "replace", fail)
result = server.scan_url("https://example.com/")
assert result["saved_report"] == {"status": "failed", "error": "synthetic disk failure"}
assert result["findings"]
assert not list((tmp_path / "reports").iterdir())
def test_default_directory_is_server_relative_not_process_cwd(monkeypatch, tmp_path):
monkeypatch.delenv("WEB_SECURITY_MCP_REPORT_DIR", raising=False)
monkeypatch.chdir(tmp_path)
assert server._report_directory() == Path(server.__file__).resolve().parent / "reports"
python / test_storage.py
import json
from pathlib import Path
import httpx
import pytest
import server
def mock_scan(monkeypatch, tmp_path):
monkeypatch.setenv("WEB_SECURITY_MCP_REPORT_DIR", str(tmp_path / "reports"))
response = httpx.Response(200, headers={"content-type": "text/html", "set-cookie": "PHPSESSID=PRIVATE_SENTINEL"},
text='<script src="https://cdn.example/a.js"></script>',
request=httpx.Request("GET", "https://example.com/"))
monkeypatch.setattr(server, "_fetch", lambda url: (response, [url]))
@pytest.mark.parametrize("include_markdown", [False, True])
def test_scan_saves_exact_complete_result(monkeypatch, tmp_path, include_markdown):
mock_scan(monkeypatch, tmp_path)
result = server.scan_url("https://example.com/", include_review_markdown=include_markdown)
assert next(iter(result)) == "saved_report"
artifact = result["saved_report"]
path = Path(artifact["path"])
assert artifact["status"] == "saved" and path.is_absolute()
assert path.parent == tmp_path / "reports"
raw = path.read_text(encoding="utf-8")
assert json.loads(raw) == result
assert "PRIVATE_SENTINEL" not in raw
assert ("review_markdown" in result) is include_markdown
assert not list(path.parent.glob("*.tmp"))
def test_saved_json_exceeds_copy_limit_and_repeated_scans_do_not_overwrite(monkeypatch, tmp_path):
mock_scan(monkeypatch, tmp_path)
analyze = server.analyze_response
def large_result(*args, **kwargs):
report = analyze(*args, **kwargs)
report["offline_test_payload"] = "日本語" * 20000
return report
monkeypatch.setattr(server, "analyze_response", large_result)
first = server.scan_url("https://example.com/")
second = server.scan_url("https://example.com/")
assert first["saved_report"]["path"] != second["saved_report"]["path"]
for result in [first, second]:
raw = Path(result["saved_report"]["path"]).read_text(encoding="utf-8")
assert len(raw) > 50000
assert json.loads(raw) == result
def test_storage_failure_preserves_findings_and_cleans_temporary_file(monkeypatch, tmp_path):
mock_scan(monkeypatch, tmp_path)
def fail(*args):
raise OSError("synthetic disk failure")
monkeypatch.setattr(server.os, "replace", fail)
result = server.scan_url("https://example.com/")
assert result["saved_report"] == {"status": "failed", "error": "synthetic disk failure"}
assert result["findings"]
assert not list((tmp_path / "reports").iterdir())
def test_default_directory_is_server_relative_not_process_cwd(monkeypatch, tmp_path):
monkeypatch.delenv("WEB_SECURITY_MCP_REPORT_DIR", raising=False)
monkeypatch.chdir(tmp_path)
assert server._report_directory() == Path(server.__file__).resolve().parent / "reports"