Files
gh-christianlouis-dmarq/backend/app/tests/test_workspace_onboarding.py
T
2026-05-23 19:56:19 +02:00

168 lines
6.1 KiB
Python

from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from app.models.domain import Domain
from app.models.mail_source import MailSource
from app.models.setting import Setting
from app.models.workspace import Workspace
from app.models.workspace_access import WorkspaceAuditLog
def _standard_payload(**overrides):
payload = {
"template_id": "standard_monitoring",
"workspace": {
"slug": "Client One",
"name": "Client One",
"description": "Managed client workspace",
},
"variables": {
"domain": "Example.COM",
"report_mailbox": "dmarc@example.com",
"imap_server": "imap.example.com",
"imap_password": "super-secret-password",
},
}
payload.update(overrides)
return payload
def test_onboarding_templates_are_available(authed_client: TestClient):
"""Operators can discover the versioned onboarding template bundle."""
response = authed_client.get("/api/v1/onboarding/templates")
assert response.status_code == 200
templates = response.json()["templates"]
assert {template["id"] for template in templates} >= {
"standard_monitoring",
"dns_only_assessment",
}
standard = next(template for template in templates if template["id"] == "standard_monitoring")
assert standard["domains"]
assert standard["mail_sources"]
assert standard["notification_defaults"]
assert standard["checklist"]
def test_onboarding_preview_renders_without_persisting(
authed_client: TestClient,
db_session: Session,
):
"""Preview renders a safe plan and leaves the database unchanged."""
response = authed_client.post("/api/v1/onboarding/preview", json=_standard_payload())
assert response.status_code == 200
plan = response.json()["plan"]
assert plan["workspace"]["slug"] == "client-one"
assert plan["domains"][0]["name"] == "example.com"
assert plan["mail_sources"][0]["password"] == "[redacted]"
assert "super-secret-password" not in str(plan)
assert db_session.query(Workspace).count() == 0
assert db_session.query(Domain).count() == 0
def test_onboarding_rejects_invalid_domain(authed_client: TestClient):
"""Invalid rendered domains fail before any apply attempt."""
payload = _standard_payload(variables={"domain": "bad domain"})
response = authed_client.post("/api/v1/onboarding/preview", json=payload)
assert response.status_code == 422
assert "invalid domain" in str(response.json()["detail"])
def test_apply_onboarding_creates_workspace_assets_and_audit(
authed_client: TestClient,
db_session: Session,
):
"""Applying a template creates the workspace, assets, defaults, and audit event."""
response = authed_client.post(
"/api/v1/onboarding/apply",
json=_standard_payload(),
headers={"x-real-ip": "198.51.100.25"},
)
assert response.status_code == 200
result = response.json()["result"]
assert result["applied"] is True
assert result["workspace"]["slug"] == "client-one"
assert result["results"]["domains"][0]["status"] == "created"
assert result["results"]["mail_sources"][0]["status"] == "created"
assert "super-secret-password" not in str(result)
workspace = db_session.query(Workspace).filter(Workspace.slug == "client-one").one()
domain = db_session.query(Domain).filter(Domain.name == "example.com").one()
source = db_session.query(MailSource).filter(MailSource.name == "Client One DMARC inbox").one()
setting = (
db_session.query(Setting)
.filter(Setting.key == "notifications.alert_missing_reports_enabled")
.one()
)
audit = (
db_session.query(WorkspaceAuditLog)
.filter(WorkspaceAuditLog.action == "workspace.onboarding_applied")
.one()
)
assert domain.workspace_id == workspace.id
assert domain.dkim_selectors == "google,selector1"
assert source.workspace_id == workspace.id
assert source.server == "imap.example.com"
assert source.enabled is False
assert source.password == "super-secret-password"
assert setting.value == "true"
assert audit.workspace_id == workspace.id
assert audit.ip_address == "198.51.100.25"
assert "super-secret-password" not in (audit.details or "")
def test_apply_onboarding_is_idempotent_for_existing_assets(
authed_client: TestClient,
db_session: Session,
):
"""Applying the same template again reports existing assets instead of duplicating them."""
first = authed_client.post("/api/v1/onboarding/apply", json=_standard_payload())
second = authed_client.post("/api/v1/onboarding/apply", json=_standard_payload())
assert first.status_code == 200
assert second.status_code == 200
result = second.json()["result"]
assert result["workspace"]["status"] == "existing"
assert result["results"]["domains"][0]["status"] == "existing"
assert result["results"]["mail_sources"][0]["status"] == "existing"
assert db_session.query(Workspace).count() == 1
assert db_session.query(Domain).count() == 1
assert db_session.query(MailSource).count() == 1
def test_onboarding_notification_overwrite_is_explicit(
authed_client: TestClient,
db_session: Session,
):
"""Existing notification settings are preserved unless overwrite_existing is true."""
db_session.add(
Setting(
key="notifications.summary_weekly_enabled",
value="false",
description="Existing setting",
value_type="boolean",
category="notifications",
)
)
db_session.commit()
response = authed_client.post("/api/v1/onboarding/apply", json=_standard_payload())
assert response.status_code == 200
row = (
db_session.query(Setting)
.filter(Setting.key == "notifications.summary_weekly_enabled")
.one()
)
assert row.value == "false"
overwrite_payload = _standard_payload(overwrite_existing=True)
response = authed_client.post("/api/v1/onboarding/apply", json=overwrite_payload)
assert response.status_code == 200
db_session.refresh(row)
assert row.value == "true"