mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
34 lines
1.2 KiB
Python
34 lines
1.2 KiB
Python
"""Regression: SQL avg/extract "hours" aggregates must serialize as JSON numbers.
|
|||
|
|
|
||
|
|
``EXTRACT(epoch ...)`` returns ``numeric`` on PostgreSQL 14+, which asyncpg
|
||
|
|
surfaces as a ``Decimal``. A ``Decimal`` serializes to a JSON *string*, so the
|
||
|
|
panel's ``avg_cycle_hours.toFixed(1)`` (and the other hours fields) threw
|
||
|
|
``toFixed is not a function`` against the live deploy. ``_as_hours`` coerces to a
|
||
|
|
real ``float`` so the field is always a JSON number.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from decimal import Decimal
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from roboco.services.metrics import _as_hours
|
||
|
|
|
||
|
|
|
||
|
|
def test_as_hours_coerces_decimal_to_float() -> None:
|
||
|
|
result = _as_hours(Decimal("1.21"))
|
||
|
|
assert result == pytest.approx(1.21)
|
||
|
|
assert isinstance(result, float) # not Decimal -> serializes as a JSON number
|
||
|
|
|
||
|
|
|
||
|
|
def test_as_hours_rounds_to_two_places() -> None:
|
||
|
|
assert _as_hours(Decimal("1.236")) == pytest.approx(1.24)
|
||
|
|
assert _as_hours(3.14159) == pytest.approx(3.14)
|
||
|
|
assert isinstance(_as_hours(3.14159), float)
|
||
|
|
|
||
|
|
|
||
|
|
def test_as_hours_none_and_zero_yield_none() -> None:
|
||
|
|
assert _as_hours(None) is None
|
||
|
|
assert _as_hours(0) is None
|
||
|
|
assert _as_hours(Decimal("0")) is None
|