168 lines
4.8 KiB
Python
168 lines
4.8 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import UTC, datetime, timedelta
|
|
import unittest
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import Session
|
|
|
|
from govoplan_core.core.institutional import (
|
|
FormDefinition,
|
|
FormFieldDefinition,
|
|
InstitutionalReference,
|
|
TemporalRevision,
|
|
)
|
|
from govoplan_forms.backend.db.models import FormDefinitionRevision
|
|
from govoplan_forms.backend.service import (
|
|
FormDefinitionStoreError,
|
|
SqlFormDefinitionProvider,
|
|
form_definition_history,
|
|
record_form_definition,
|
|
)
|
|
|
|
|
|
NOW = datetime(2026, 8, 1, 10, 0, tzinfo=UTC)
|
|
|
|
|
|
@dataclass
|
|
class Principal:
|
|
tenant_id: str = "tenant-1"
|
|
account_id: str = "account-1"
|
|
|
|
|
|
def definition(
|
|
*,
|
|
revision: str = "1",
|
|
state: str = "published",
|
|
tenant_id: str = "tenant-1",
|
|
) -> FormDefinition:
|
|
recorded_at = NOW + timedelta(minutes=int(revision) - 1)
|
|
return FormDefinition(
|
|
reference=InstitutionalReference(
|
|
kind="form",
|
|
owner_module="forms",
|
|
object_id="permit-application",
|
|
tenant_id=tenant_id,
|
|
version=revision,
|
|
),
|
|
key="permit-application",
|
|
temporal=TemporalRevision(
|
|
revision=revision,
|
|
recorded_at=recorded_at,
|
|
change_reason="Initial schema." if revision == "1" else "Revise schema.",
|
|
),
|
|
title="Permit application",
|
|
fields=(
|
|
FormFieldDefinition(
|
|
key="name",
|
|
label="Name",
|
|
required=True,
|
|
constraints={"min_length": 2, "max_length": 200},
|
|
),
|
|
FormFieldDefinition(
|
|
key="delivery",
|
|
label="Delivery",
|
|
value_type="choice",
|
|
options=("portal", "mail"),
|
|
),
|
|
),
|
|
publication_state=state, # type: ignore[arg-type]
|
|
allow_drafts=True,
|
|
max_attachments=2,
|
|
handoff_kinds=("case",),
|
|
)
|
|
|
|
|
|
class FormsTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.engine = create_engine("sqlite+pysqlite:///:memory:")
|
|
FormDefinitionRevision.__table__.create(self.engine)
|
|
self.session = Session(self.engine)
|
|
self.principal = Principal()
|
|
|
|
def tearDown(self) -> None:
|
|
self.session.close()
|
|
self.engine.dispose()
|
|
|
|
def test_provider_returns_exact_published_revision_and_history(self) -> None:
|
|
first = record_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
definition=definition(),
|
|
)
|
|
provider = SqlFormDefinitionProvider()
|
|
|
|
self.assertEqual(
|
|
(first,),
|
|
tuple(
|
|
provider.list_form_definitions(
|
|
self.session,
|
|
self.principal,
|
|
tenant_id="tenant-1",
|
|
)
|
|
),
|
|
)
|
|
exact = provider.get_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
reference=first.reference,
|
|
effective_at=NOW,
|
|
)
|
|
self.assertEqual("1", exact.temporal.revision if exact else None)
|
|
|
|
record_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
definition=definition(revision="2"),
|
|
expected_revision="1",
|
|
)
|
|
self.assertEqual(
|
|
["2", "1"],
|
|
[
|
|
item.temporal.revision
|
|
for item in form_definition_history(
|
|
self.session,
|
|
self.principal,
|
|
form_id="permit-application",
|
|
)
|
|
],
|
|
)
|
|
|
|
def test_replay_occ_and_tenant_boundaries_fail_closed(self) -> None:
|
|
first = record_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
definition=definition(),
|
|
)
|
|
replay = record_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
definition=definition(),
|
|
)
|
|
self.assertEqual(first, replay)
|
|
|
|
with self.assertRaisesRegex(FormDefinitionStoreError, "stale"):
|
|
record_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
definition=definition(revision="2"),
|
|
expected_revision="0",
|
|
)
|
|
with self.assertRaisesRegex(FormDefinitionStoreError, "cross tenants"):
|
|
record_form_definition(
|
|
self.session,
|
|
self.principal,
|
|
definition=definition(tenant_id="tenant-2"),
|
|
)
|
|
with self.assertRaisesRegex(Exception, "cross tenants"):
|
|
SqlFormDefinitionProvider().list_form_definitions(
|
|
self.session,
|
|
Principal("tenant-2"),
|
|
tenant_id="tenant-1",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|