Files
tconnectsync/tests/sync/tandemsource/test_choose_device.py
T
James Woglom ddca912eea Remove PumpMetadata transform; callers use raw BffPump, normalize at call sites
Delete the PumpMetadata TypedDict, _bff_pump_to_metadata and pump_metadata
transform layer. Callers now consume the raw BffPump dicts from get_pumper()
directly. The pump-local -> UTC date conversion is kept as a shared
naive_local_to_utc() helper, applied only at the call sites that compare a
pump date against real UTC (choose_device staleness/selection, autoupdate
timing).

Also expand pump_events JSON parse coverage: drive bolus (20), basal (279),
CGM (399) and alarm (5) events through pump_events(), asserting decoded
fields and enum members (previously only eventCode 16 was covered).
2026-07-01 04:22:57 +00:00

126 lines
4.8 KiB
Python

#!/usr/bin/env python3
import unittest
import arrow
from tconnectsync.sync.tandemsource.choose_device import (
ChooseDevice,
InvalidSerialNumber,
NoDevicesFound,
)
from ...api.fake import TConnectApi
from ...secrets import build_secrets
LOGGER = "tconnectsync.sync.tandemsource.choose_device"
class FakeTandemSourceApi:
"""Fake TandemSource API returning a configurable get_pumper() pumps list of
raw BffPump dicts."""
def __init__(self, pumps=None):
self._pumps = pumps if pumps is not None else []
def get_pumper(self):
return {'pumps': self._pumps}
def needs_relogin(self):
return False
def pump(serial, assignmentId=None, maxDate=None):
return {
'serialNumber': serial,
'assignmentId': assignmentId if assignmentId is not None else ('dev-' + serial),
'maxDateOfEvents': maxDate,
}
class TestChooseDevice(unittest.TestCase):
maxDiff = None
def _choose(self, pumps, **secret_kwargs):
tconnect = TConnectApi()
tconnect._tandemsource = FakeTandemSourceApi(pumps=pumps)
secret = build_secrets(**secret_kwargs)
return ChooseDevice(secret, tconnect)
# --- auto-select branch (sentinel 11111111 or falsy) ---
def test_empty_list_raises_no_devices_found(self):
cd = self._choose([], PUMP_SERIAL_NUMBER=11111111)
with self.assertRaises(NoDevicesFound):
cd.choose()
def test_auto_selects_most_recent_regardless_of_order(self):
older = pump('111', maxDate=arrow.utcnow().shift(days=-10).isoformat())
newer = pump('222', maxDate=arrow.utcnow().shift(days=-1).isoformat())
cd = self._choose([newer, older], PUMP_SERIAL_NUMBER=11111111)
self.assertIs(cd.choose(), newer)
def test_auto_select_skips_never_uploaded_pumps(self):
never = pump('111', maxDate=None) # first in the list
dated = pump('222', maxDate=arrow.utcnow().shift(days=-2).isoformat())
cd = self._choose([never, dated], PUMP_SERIAL_NUMBER=11111111)
self.assertIs(cd.choose(), dated)
def test_auto_select_falls_back_to_first_when_all_never_uploaded(self):
first = pump('111', maxDate=None)
second = pump('222', maxDate=None)
cd = self._choose([first, second], PUMP_SERIAL_NUMBER=11111111)
self.assertIs(cd.choose(), first)
def test_sentinel_int_triggers_auto_select(self):
p = pump('90556643', maxDate=arrow.utcnow().shift(days=-1).isoformat())
cd = self._choose([p], PUMP_SERIAL_NUMBER=11111111)
# Must not raise InvalidSerialNumber even though no serial == 11111111
self.assertIs(cd.choose(), p)
def test_falsy_serial_triggers_auto_select(self):
p = pump('90556643', maxDate=arrow.utcnow().shift(days=-1).isoformat())
cd = self._choose([p], PUMP_SERIAL_NUMBER=None)
self.assertIs(cd.choose(), p)
# --- explicit-serial branch ---
def test_explicit_serial_overrides_recency(self):
chosen = pump('90556643', maxDate=arrow.utcnow().shift(days=-10).isoformat())
newer = pump('99999999', maxDate=arrow.utcnow().shift(days=-1).isoformat())
cd = self._choose([newer, chosen], PUMP_SERIAL_NUMBER=90556643)
self.assertIs(cd.choose(), chosen)
def test_unknown_serial_raises_invalid_serial_number(self):
p = pump('90556643', maxDate=arrow.utcnow().shift(days=-1).isoformat())
cd = self._choose([p], PUMP_SERIAL_NUMBER=12345678)
with self.assertRaisesRegex(InvalidSerialNumber, "is not present on your account"):
cd.choose()
# --- stale-pump warning ---
def test_stale_selected_pump_warns(self):
p = pump('90556643', maxDate=arrow.utcnow().shift(days=-5).isoformat())
cd = self._choose([p], PUMP_SERIAL_NUMBER=90556643)
with self.assertLogs(LOGGER, level="WARNING") as cm:
cd.choose()
self.assertTrue(any("no events in the last" in m for m in cm.output))
def test_fresh_selected_pump_does_not_warn(self):
p = pump('90556643', maxDate=arrow.utcnow().shift(days=-1).isoformat())
cd = self._choose([p], PUMP_SERIAL_NUMBER=90556643)
# assertNoLogs is 3.10+; CI runs 3.8, so assert INFO logs contain no warning text.
with self.assertLogs(LOGGER, level="INFO") as cm:
cd.choose()
self.assertFalse(any("no events in the last" in m for m in cm.output))
def test_unparseable_date_on_selected_pump_is_swallowed(self):
p = pump('90556643', maxDate="not-a-date")
cd = self._choose([p], PUMP_SERIAL_NUMBER=90556643)
with self.assertLogs(LOGGER, level="INFO") as cm:
device = cd.choose()
self.assertIs(device, p)
self.assertFalse(any("no events in the last" in m for m in cm.output))
if __name__ == "__main__":
unittest.main()