Files
glucose-dashboard/tests/test_profile_data.py
T
willemjan 79249958c2
willemjan/glucose-dashboard/pipeline/head This commit looks good
Add pump profile fetching and Insulineprofiel page
Fetch and parse the latest-used Nightscout profile (basal schedule, ISF,
carb ratio, DIA, targets) and show it as a new dashboard page: a list of
basal/ISF/carb-ratio segments plus a bar chart of basal rate by hour of
day. This is the data foundation for treatment overlays on the glucose
charts and the redesigned PDF report in follow-up PRs.
2026-09-05 21:37:17 +02:00

118 lines
4.1 KiB
Python

import pytest
import profile_data as pd_
def _raw_profile(units="mg/dl", default_name="Default"):
return {
"defaultProfile": default_name,
"store": {
"Default": {
"units": units,
"dia": "5",
"basal": [
{"time": "00:00", "value": "0.8"},
{"time": "06:00", "value": "1.2"},
{"time": "22:00", "value": "0.7"},
],
"sens": [{"time": "00:00", "value": "50"}],
"carbratio": [{"time": "00:00", "value": "10"}],
"target_low": [{"time": "00:00", "value": "90"}],
"target_high": [{"time": "00:00", "value": "120"}],
}
},
}
def test_parse_profile_returns_empty_dict_for_empty_input():
assert pd_.parse_profile({}) == {}
def test_parse_profile_converts_mgdl_to_mmol():
profile = pd_.parse_profile(_raw_profile(units="mg/dl"))
assert profile["units"] == "mmol"
# 90 mg/dl -> ~5.0 mmol/L, 120 mg/dl -> ~6.7 mmol/L, 50 mg/dl (ISF) -> ~2.8 mmol/L
assert profile["target_low"][0]["value"] == pytest.approx(5.0, abs=0.05)
assert profile["target_high"][0]["value"] == pytest.approx(6.7, abs=0.05)
assert profile["sens"][0]["value"] == pytest.approx(2.8, abs=0.05)
def test_parse_profile_leaves_mmol_profiles_unconverted():
profile = pd_.parse_profile(_raw_profile(units="mmol"))
assert profile["target_low"][0]["value"] == pytest.approx(90.0)
def test_parse_profile_does_not_convert_basal_or_carbratio():
profile = pd_.parse_profile(_raw_profile(units="mg/dl"))
assert profile["basal"][0]["value"] == pytest.approx(0.8)
assert profile["carbratio"][0]["value"] == pytest.approx(10.0)
def test_parse_profile_sorts_basal_segments_by_time():
raw = _raw_profile()
raw["store"]["Default"]["basal"] = [
{"time": "22:00", "value": "0.7"},
{"time": "00:00", "value": "0.8"},
{"time": "06:00", "value": "1.2"},
]
profile = pd_.parse_profile(raw)
assert [seg["minutes"] for seg in profile["basal"]] == [0, 360, 1320]
def test_parse_profile_falls_back_to_first_profile_when_default_name_missing():
raw = _raw_profile(default_name="DoesNotExist")
profile = pd_.parse_profile(raw)
assert profile["dia"] == pytest.approx(5.0)
def test_parse_profile_dia_and_name():
profile = pd_.parse_profile(_raw_profile())
assert profile["dia"] == pytest.approx(5.0)
assert profile["name"] == "Default"
def test_value_at_returns_active_segment():
segments = [{"minutes": 0, "value": 0.8}, {"minutes": 360, "value": 1.2}, {"minutes": 1320, "value": 0.7}]
assert pd_.value_at(segments, 100) == pytest.approx(0.8)
assert pd_.value_at(segments, 360) == pytest.approx(1.2)
assert pd_.value_at(segments, 1000) == pytest.approx(1.2)
assert pd_.value_at(segments, 1350) == pytest.approx(0.7)
def test_value_at_wraps_to_last_segment_before_first():
segments = [{"minutes": 360, "value": 1.2}, {"minutes": 1320, "value": 0.7}]
assert pd_.value_at(segments, 100) == pytest.approx(0.7)
def test_value_at_empty_segments_returns_none():
assert pd_.value_at([], 100) is None
def test_segments_table_computes_end_times_from_next_segment():
segments = [{"minutes": 0, "value": 0.8}, {"minutes": 360, "value": 1.2}]
rows = pd_.segments_table(segments)
assert rows == [
{"start": "00:00", "end": "06:00", "value": 0.8},
{"start": "06:00", "end": "24:00", "value": 1.2},
]
def test_segments_to_hourly_bars_closes_the_24h_loop():
segments = [{"minutes": 0, "value": 0.8}, {"minutes": 360, "value": 1.2}]
bars = pd_.segments_to_hourly_bars(segments)
assert bars[-1] == {"hour": 24.0, "value": 0.8}
def test_segments_to_hourly_bars_empty_input():
assert pd_.segments_to_hourly_bars([]) == []
def test_total_daily_basal_weights_by_segment_duration():
# 6h @ 0.8 + 18h @ 1.2 = 4.8 + 21.6 = 26.4
segments = [{"minutes": 0, "value": 0.8}, {"minutes": 360, "value": 1.2}]
assert pd_.total_daily_basal(segments) == pytest.approx(26.4)
def test_total_daily_basal_empty_input():
assert pd_.total_daily_basal([]) == 0.0