feat(scada): add project monitoring replay
Generic Container CI/CD / test-build-publish (push) Successful in 3m39s
Server CI/CD v2 / build-test-publish-and-deploy (push) Successful in 3m39s

This commit is contained in:
2026-11-04 14:27:21 +08:00
parent f25423dec4
commit 26fa5d1909
53 changed files with 5153 additions and 20 deletions
@@ -7,6 +7,7 @@ from sqlalchemy.dialects import postgresql
from app.infra.db.metadb.repositories import metadata_repository
from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository
from app.domain.schemas.project_settings import ProjectSettings
@pytest.fixture
@@ -99,3 +100,60 @@ async def test_update_map_config_preserves_legacy_settings_and_other_projects():
repository.get_project_by_id.assert_awaited_once_with(project_id)
assert project.map_config == {'legend': 'original', 'coordinate_reference': {'source_srid': 990001}, 'place_search': search}
session.commit.assert_awaited_once()
@pytest.mark.anyio
async def test_update_project_settings_preserves_unmentioned_parameters():
original = {"scada_monitoring_interval_seconds": 300, "future_option": {"enabled": True}}
project = SimpleNamespace(settings=original)
session = SimpleNamespace(commit=AsyncMock(), refresh=AsyncMock())
repository = MetadataRepository(session)
repository.get_project_by_id = AsyncMock(return_value=project)
project_id = uuid4()
await repository.update_project(
project_id,
updates={"settings": {"scada_monitoring_interval_seconds": 900}},
)
assert project.settings == {"scada_monitoring_interval_seconds": 900, "future_option": {"enabled": True}}
assert original["scada_monitoring_interval_seconds"] == 300
session.commit.assert_awaited_once()
@pytest.mark.anyio
async def test_empty_settings_update_preserves_values_and_explicit_null_clears_interval():
project = SimpleNamespace(settings={"scada_monitoring_interval_seconds": 900, "other": True})
session = SimpleNamespace(commit=AsyncMock(), refresh=AsyncMock())
repository = MetadataRepository(session)
repository.get_project_by_id = AsyncMock(return_value=project)
project_id = uuid4()
await repository.update_project(project_id, updates={"settings": {}})
assert project.settings == {"scada_monitoring_interval_seconds": 900, "other": True}
await repository.update_project(
project_id, updates={"settings": {"scada_monitoring_interval_seconds": None}}
)
assert project.settings == {"scada_monitoring_interval_seconds": None, "other": True}
def test_scada_monitoring_roles_are_typed_inside_extensible_project_settings():
settings = ProjectSettings.model_validate({
"scada_monitoring_interval_seconds": 900,
"scada_monitoring": {
"rule_version": "burst-monitor-v1",
"pressure_device_ids": ["P1", "P2"],
"outlet_flow_device_ids": ["F1"],
},
"future_option": True,
})
assert settings.scada_monitoring.pressure_device_ids == ["P1", "P2"]
assert settings.model_dump()["future_option"] is True
with pytest.raises(ValueError):
ProjectSettings.model_validate({
"scada_monitoring": {
"pressure_device_ids": ["D1"],
"outlet_flow_device_ids": ["D1"],
}
})