feat: Vorbereitung-Module auf 100% — Persistenz, Backend-Services, UCCA Frontend
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 37s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 18s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 37s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 18s
Phase A: PostgreSQL State Store (sdk_states Tabelle, InMemory-Fallback) Phase B: Modules dynamisch vom Backend, Scope DB-Persistenz, Source Policy State Phase C: UCCA Frontend (3 Seiten, Wizard, RiskScoreGauge), Obligations Live-Daten Phase D: Document Import (PDF/LLM/Gap-Analyse), System Screening (SBOM/OSV.dev) Phase E: Company Profile CRUD mit Audit-Logging Phase F: Tests (Python + TypeScript), flow-data.ts DB-Tabellen aktualisiert Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
134
backend-compliance/tests/test_company_profile_routes.py
Normal file
134
backend-compliance/tests/test_company_profile_routes.py
Normal file
@@ -0,0 +1,134 @@
|
||||
"""Tests for Company Profile routes (company_profile_routes.py)."""
|
||||
|
||||
import json
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from compliance.api.company_profile_routes import (
|
||||
CompanyProfileRequest,
|
||||
row_to_response,
|
||||
log_audit,
|
||||
)
|
||||
|
||||
|
||||
class TestCompanyProfileRequest:
|
||||
"""Tests for request model defaults."""
|
||||
|
||||
def test_default_values(self):
|
||||
req = CompanyProfileRequest()
|
||||
assert req.company_name == ""
|
||||
assert req.legal_form == "GmbH"
|
||||
assert req.business_model == "B2B"
|
||||
assert req.company_size == "small"
|
||||
assert req.headquarters_country == "DE"
|
||||
assert req.is_data_controller is True
|
||||
assert req.is_data_processor is False
|
||||
assert req.uses_ai is False
|
||||
assert req.is_complete is False
|
||||
|
||||
def test_custom_values(self):
|
||||
req = CompanyProfileRequest(
|
||||
company_name="Test GmbH",
|
||||
industry="Software",
|
||||
uses_ai=True,
|
||||
ai_use_cases=["Chatbot", "Analytics"],
|
||||
offerings=["app_web", "software_saas"],
|
||||
)
|
||||
assert req.company_name == "Test GmbH"
|
||||
assert req.uses_ai is True
|
||||
assert len(req.ai_use_cases) == 2
|
||||
assert len(req.offerings) == 2
|
||||
|
||||
def test_serialization(self):
|
||||
req = CompanyProfileRequest(company_name="Test")
|
||||
data = req.model_dump()
|
||||
assert data["company_name"] == "Test"
|
||||
assert isinstance(data["target_markets"], list)
|
||||
|
||||
|
||||
class TestRowToResponse:
|
||||
"""Tests for DB row to response conversion."""
|
||||
|
||||
def _make_row(self, **overrides):
|
||||
"""Create a mock DB row with 30 fields."""
|
||||
defaults = [
|
||||
"uuid-123", # 0: id
|
||||
"default", # 1: tenant_id
|
||||
"Test GmbH", # 2: company_name
|
||||
"GmbH", # 3: legal_form
|
||||
"IT", # 4: industry
|
||||
2020, # 5: founded_year
|
||||
"B2B", # 6: business_model
|
||||
["app_web"], # 7: offerings
|
||||
"small", # 8: company_size
|
||||
"10-49", # 9: employee_count
|
||||
"2-10 Mio", # 10: annual_revenue
|
||||
"DE", # 11: headquarters_country
|
||||
"Berlin", # 12: headquarters_city
|
||||
False, # 13: has_international_locations
|
||||
[], # 14: international_countries
|
||||
["DE", "AT"], # 15: target_markets
|
||||
"DE", # 16: primary_jurisdiction
|
||||
True, # 17: is_data_controller
|
||||
False, # 18: is_data_processor
|
||||
False, # 19: uses_ai
|
||||
[], # 20: ai_use_cases
|
||||
"Max Muster", # 21: dpo_name
|
||||
"dpo@test.de", # 22: dpo_email
|
||||
None, # 23: legal_contact_name
|
||||
None, # 24: legal_contact_email
|
||||
None, # 25: machine_builder
|
||||
True, # 26: is_complete
|
||||
"2026-01-01", # 27: completed_at
|
||||
"2026-01-01", # 28: created_at
|
||||
"2026-01-01", # 29: updated_at
|
||||
]
|
||||
return tuple(defaults)
|
||||
|
||||
def test_basic_conversion(self):
|
||||
row = self._make_row()
|
||||
response = row_to_response(row)
|
||||
assert response.id == "uuid-123"
|
||||
assert response.tenant_id == "default"
|
||||
assert response.company_name == "Test GmbH"
|
||||
assert response.is_complete is True
|
||||
|
||||
def test_none_values_handled(self):
|
||||
row = list(self._make_row())
|
||||
row[5] = None # founded_year
|
||||
row[21] = None # dpo_name
|
||||
row[25] = None # machine_builder
|
||||
row[27] = None # completed_at
|
||||
response = row_to_response(tuple(row))
|
||||
assert response.founded_year is None
|
||||
assert response.dpo_name is None
|
||||
assert response.machine_builder is None
|
||||
assert response.completed_at is None
|
||||
|
||||
def test_non_list_jsonb_handled(self):
|
||||
row = list(self._make_row())
|
||||
row[7] = None # offerings (JSONB could be None)
|
||||
row[14] = None # international_countries
|
||||
response = row_to_response(tuple(row))
|
||||
assert response.offerings == []
|
||||
assert response.international_countries == []
|
||||
|
||||
|
||||
class TestLogAudit:
|
||||
"""Tests for audit logging helper."""
|
||||
|
||||
def test_log_audit_success(self):
|
||||
db = MagicMock()
|
||||
log_audit(db, "tenant-1", "create", {"company_name": "Test"}, "admin")
|
||||
db.execute.assert_called_once()
|
||||
|
||||
def test_log_audit_with_none_fields(self):
|
||||
db = MagicMock()
|
||||
log_audit(db, "tenant-1", "update", None, None)
|
||||
db.execute.assert_called_once()
|
||||
|
||||
def test_log_audit_db_error_handled(self):
|
||||
db = MagicMock()
|
||||
db.execute.side_effect = Exception("DB error")
|
||||
# Should not raise
|
||||
log_audit(db, "tenant-1", "create", {}, "admin")
|
||||
Reference in New Issue
Block a user