Files
breakpilot-compliance/backend-compliance/tests/test_security_templates.py
Benjamin Admin 49ce417428
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 32s
CI/CD / test-python-backend-compliance (push) Successful in 34s
CI/CD / test-python-document-crawler (push) Successful in 23s
CI/CD / test-python-dsms-gateway (push) Successful in 21s
CI/CD / validate-canonical-controls (push) Successful in 11s
CI/CD / Deploy (push) Successful in 2s
feat: add compliance modules 2-5 (dashboard, security templates, process manager, evidence collector)
Module 2: Extended Compliance Dashboard with roadmap, module-status, next-actions, snapshots, score-history
Module 3: 7 German security document templates (IT-Sicherheitskonzept, Datenschutz, Backup, Logging, Incident-Response, Zugriff, Risikomanagement)
Module 4: Compliance Process Manager with CRUD, complete/skip/seed, ~50 seed tasks, 3-tab UI
Module 5: Evidence Collector Extended with automated checks, control-mapping, coverage report, 4-tab UI

Also includes: canonical control library enhancements (verification method, categories, dedup), control generator improvements, RAG client extensions

52 tests pass, frontend builds clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 21:03:04 +01:00

176 lines
5.9 KiB
Python

"""Tests for security document templates (Module 3)."""
import pytest
from unittest.mock import MagicMock, patch
from fastapi.testclient import TestClient
from fastapi import FastAPI
from datetime import datetime
from compliance.api.legal_template_routes import router
from classroom_engine.database import get_db
from compliance.api.tenant_utils import get_tenant_id
DEFAULT_TENANT_ID = "9282a473-5c95-4b3a-bf78-0ecc0ec71d3e"
# =============================================================================
# Test App Setup
# =============================================================================
app = FastAPI()
app.include_router(router)
mock_db = MagicMock()
def override_get_db():
yield mock_db
def override_tenant():
return DEFAULT_TENANT_ID
app.dependency_overrides[get_db] = override_get_db
app.dependency_overrides[get_tenant_id] = override_tenant
client = TestClient(app)
SECURITY_TEMPLATE_TYPES = [
"it_security_concept",
"data_protection_concept",
"backup_recovery_concept",
"logging_concept",
"incident_response_plan",
"access_control_concept",
"risk_management_concept",
]
# =============================================================================
# Helpers
# =============================================================================
def make_template_row(doc_type, title="Test Template", content="# Test"):
row = MagicMock()
row._mapping = {
"id": "tmpl-001",
"tenant_id": DEFAULT_TENANT_ID,
"document_type": doc_type,
"title": title,
"description": f"Test {doc_type}",
"content": content,
"placeholders": ["COMPANY_NAME", "ISB_NAME"],
"language": "de",
"jurisdiction": "DE",
"status": "published",
"license_id": None,
"license_name": None,
"source_name": None,
"inspiration_sources": [],
"created_at": datetime(2026, 3, 14),
"updated_at": datetime(2026, 3, 14),
}
return row
# =============================================================================
# Tests
# =============================================================================
class TestSecurityTemplateTypes:
"""Verify the 7 security template types are accepted by the API."""
def test_all_security_types_in_valid_set(self):
"""All 7 security template types are in VALID_DOCUMENT_TYPES."""
from compliance.api.legal_template_routes import VALID_DOCUMENT_TYPES
for doc_type in SECURITY_TEMPLATE_TYPES:
assert doc_type in VALID_DOCUMENT_TYPES, (
f"{doc_type} not in VALID_DOCUMENT_TYPES"
)
def test_security_template_count(self):
"""There are exactly 7 security template types."""
assert len(SECURITY_TEMPLATE_TYPES) == 7
def test_create_security_template_accepted(self):
"""Creating a template with a security type is accepted (not 400)."""
insert_row = MagicMock()
insert_row._mapping = {
"id": "new-tmpl",
"tenant_id": DEFAULT_TENANT_ID,
"document_type": "it_security_concept",
"title": "IT-Sicherheitskonzept",
"description": "Test",
"content": "# IT-Sicherheitskonzept",
"placeholders": [],
"language": "de",
"jurisdiction": "DE",
"status": "draft",
"license_id": None,
"license_name": None,
"source_name": None,
"inspiration_sources": [],
"created_at": datetime(2026, 3, 14),
"updated_at": datetime(2026, 3, 14),
}
mock_db.execute.return_value.fetchone.return_value = insert_row
mock_db.commit = MagicMock()
resp = client.post("/legal-templates", json={
"document_type": "it_security_concept",
"title": "IT-Sicherheitskonzept",
"content": "# IT-Sicherheitskonzept\n\n## 1. Managementzusammenfassung",
"language": "de",
"jurisdiction": "DE",
})
# Should NOT be 400 (invalid type)
assert resp.status_code != 400 or "Invalid document_type" not in resp.text
def test_invalid_type_rejected(self):
"""A non-existent template type is rejected with 400."""
resp = client.post("/legal-templates", json={
"document_type": "nonexistent_type",
"title": "Test",
"content": "# Test",
})
assert resp.status_code == 400
assert "Invalid document_type" in resp.json()["detail"]
class TestSecurityTemplateFilter:
"""Verify filtering templates by security document types."""
def test_filter_by_security_type(self):
"""GET /legal-templates?document_type=it_security_concept returns matching templates."""
row = make_template_row("it_security_concept", "IT-Sicherheitskonzept")
mock_db.execute.return_value.fetchall.return_value = [row]
resp = client.get("/legal-templates?document_type=it_security_concept")
assert resp.status_code == 200
data = resp.json()
assert "templates" in data or isinstance(data, list)
class TestSecurityTemplatePlaceholders:
"""Verify placeholder structure for security templates."""
def test_common_placeholders_present(self):
"""Security templates should use standard placeholders."""
common_placeholders = [
"COMPANY_NAME", "GF_NAME", "ISB_NAME",
"DOCUMENT_VERSION", "VERSION_DATE", "NEXT_REVIEW_DATE",
]
row = make_template_row(
"it_security_concept",
content="# IT-Sicherheitskonzept\n{{COMPANY_NAME}} {{ISB_NAME}}"
)
row._mapping["placeholders"] = common_placeholders
mock_db.execute.return_value.fetchone.return_value = row
# Verify the mock has all expected placeholders
assert all(
p in row._mapping["placeholders"]
for p in ["COMPANY_NAME", "GF_NAME", "ISB_NAME"]
)