Reorganize algorithm packages by business responsibility, move orchestration into services, and keep database access behind pooled repositories. Harden analysis API validation, remove unsafe legacy simulation endpoints, and add regression and architecture boundary coverage. BREAKING CHANGE: legacy algorithm module paths and obsolete simulation endpoints are removed.
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
import importlib.util
|
|
from datetime import date, datetime, timedelta, timezone
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
def _load_time_module():
|
|
module_path = Path(__file__).resolve().parents[2] / "app" / "domain" / "time.py"
|
|
spec = importlib.util.spec_from_file_location("tests_domain_time", module_path)
|
|
module = importlib.util.module_from_spec(spec)
|
|
assert spec and spec.loader
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_parse_utc_time_rejects_naive_datetimes():
|
|
module = _load_time_module()
|
|
|
|
with pytest.raises(ValueError, match="timezone information"):
|
|
module.parse_utc_time("2025-01-01T08:00:00")
|
|
|
|
|
|
def test_parse_utc_time_normalizes_offset_datetime_to_utc():
|
|
module = _load_time_module()
|
|
result = module.parse_utc_time("2025-01-01T08:00:00+08:00")
|
|
|
|
assert result == datetime(2025, 1, 1, 0, 0, tzinfo=timezone.utc)
|
|
|
|
|
|
def test_extract_date_keeps_original_offset_calendar_day():
|
|
module = _load_time_module()
|
|
result = module.extract_date("2025-01-01T00:30:00+08:00")
|
|
|
|
assert result == date(2025, 1, 1)
|
|
|
|
|
|
def test_utc_now_returns_timezone_aware_utc_datetime():
|
|
module = _load_time_module()
|
|
result = module.utc_now()
|
|
|
|
assert result.tzinfo == timezone.utc
|
|
assert result.utcoffset() == timedelta(0)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("clock", "expected_seconds"),
|
|
[
|
|
("1:00", 3600),
|
|
("01:00", 3600),
|
|
("0:05", 300),
|
|
("0:05:00", 300),
|
|
("24:00", 86400),
|
|
],
|
|
)
|
|
def test_parse_clock_duration_seconds_accepts_epanet_clock_formats(
|
|
clock, expected_seconds
|
|
):
|
|
module = _load_time_module()
|
|
|
|
assert module.parse_clock_duration_seconds(clock) == expected_seconds
|
|
|
|
|
|
@pytest.mark.parametrize("clock", ["bad", "1:60", "1:00:60", "-1:00"])
|
|
def test_parse_clock_duration_seconds_rejects_invalid_clock_formats(clock):
|
|
module = _load_time_module()
|
|
|
|
with pytest.raises(ValueError):
|
|
module.parse_clock_duration_seconds(clock)
|