118 lines
3.3 KiB
Python
118 lines
3.3 KiB
Python
import pytest
|
|
|
|
import dpg_gauges as dpgg
|
|
from dpg_gauges.exceptions import GaugeConfigError, GaugeNotFoundError, GaugeValueError
|
|
from dpg_gauges.gauges import AnalogGaugeConfig, DigitalGaugeConfig
|
|
from dpg_gauges.scales import (
|
|
clamp_value,
|
|
clamped_threshold,
|
|
fill_fraction,
|
|
format_gauge_value,
|
|
generate_ticks,
|
|
normalize_value,
|
|
value_to_angle,
|
|
)
|
|
|
|
|
|
def test_public_api_exports_required_names() -> None:
|
|
required = {
|
|
"configure",
|
|
"GaugeTheme",
|
|
"GaugeStyle",
|
|
"AnimationConfig",
|
|
"SmoothingConfig",
|
|
"ThresholdBand",
|
|
"GaugeMarker",
|
|
"StatusState",
|
|
"GaugeValue",
|
|
"GaugeStats",
|
|
"analog_gauge",
|
|
"digital_gauge",
|
|
"bar_gauge",
|
|
"level_gauge",
|
|
"status_light",
|
|
"segmented_gauge",
|
|
"compass_gauge",
|
|
"thermometer_gauge",
|
|
"battery_gauge",
|
|
"multi_value_gauge",
|
|
"gauge_panel",
|
|
"gauge_grid",
|
|
"set_value",
|
|
"get_value",
|
|
"update_gauge",
|
|
"configure_gauge",
|
|
"set_thresholds",
|
|
"set_markers",
|
|
"set_show",
|
|
"delete_gauge",
|
|
"get_gauge_debug_state",
|
|
}
|
|
|
|
assert required.issubset(set(dpgg.__all__))
|
|
for name in required:
|
|
assert hasattr(dpgg, name)
|
|
|
|
|
|
def test_dataclass_construction_and_context_stub() -> None:
|
|
threshold = dpgg.ThresholdBand(10, 20, (255, 0, 0, 255), "hot")
|
|
marker = dpgg.GaugeMarker(50, (0, 255, 0), thickness=1.5)
|
|
config = AnalogGaugeConfig(
|
|
label="RPM",
|
|
min_value=0,
|
|
max_value=8000,
|
|
thresholds=[threshold],
|
|
markers=[marker],
|
|
animation=True,
|
|
smoothing=False,
|
|
)
|
|
|
|
assert config.thresholds == (threshold,)
|
|
assert config.markers == (marker,)
|
|
assert config.animation == dpgg.AnimationConfig(enabled=True)
|
|
assert config.smoothing == dpgg.SmoothingConfig(enabled=False)
|
|
|
|
with dpgg.digital_gauge(label="Speed", value=12.3) as digital:
|
|
assert isinstance(digital, DigitalGaugeConfig)
|
|
assert digital.label == "Speed"
|
|
|
|
|
|
def test_clamp_normalize_angle_and_fill_math() -> None:
|
|
assert clamp_value(150, 0, 100) == 100
|
|
assert normalize_value(25, 0, 100) == 0.25
|
|
assert fill_fraction(-10, 0, 100) == 0
|
|
assert value_to_angle(50, 0, 100, 225, -45) == 90
|
|
|
|
with pytest.raises(GaugeValueError):
|
|
clamp_value(float("nan"), 0, 100)
|
|
|
|
|
|
def test_tick_generation_and_formatting() -> None:
|
|
assert generate_ticks(0, 100, 5) == [0, 25, 50, 75, 100]
|
|
assert format_gauge_value(12.345, precision=1, unit="V") == "12.3 V"
|
|
assert format_gauge_value(float("inf"), precision=1) == "--"
|
|
|
|
with pytest.raises(GaugeConfigError):
|
|
generate_ticks(0, 100, 1)
|
|
|
|
|
|
def test_threshold_validation_and_clamping() -> None:
|
|
threshold = dpgg.ThresholdBand(-10, 120, (255, 128, 0, 255))
|
|
assert clamped_threshold(threshold, 0, 100) == (0, 100)
|
|
|
|
with pytest.raises(GaugeConfigError):
|
|
dpgg.ThresholdBand(20, 10, (255, 0, 0))
|
|
|
|
with pytest.raises(GaugeConfigError):
|
|
AnalogGaugeConfig(min_value=100, max_value=0)
|
|
|
|
|
|
def test_runtime_stubs_import_without_dpg_context() -> None:
|
|
dpgg.configure(debug=True)
|
|
|
|
with pytest.raises(GaugeNotFoundError):
|
|
dpgg.set_value("missing", 1)
|
|
|
|
with pytest.raises(GaugeNotFoundError):
|
|
dpgg.get_gauge_debug_state("missing")
|