package dev.dtrentin.chart.model import dev.dtrentin.chart.lod.MinMaxLttbLodStrategy import dev.dtrentin.chart.render.DecimalAxisFormatter import dev.dtrentin.chart.render.LineSignalRenderer import dev.dtrentin.chart.render.TimeAxisFormatter import androidx.compose.ui.graphics.Color import kotlin.test.* class ChartConfigTest { @Test fun ChartConfig_defaultsConstruct() { // Default no-arg construction must succeed with all sub-config defaults. val cfg = ChartConfig() assertEquals(10f, cfg.data.xWindowSeconds) assertTrue(cfg.data.yRange is YRange.Auto) assertEquals(T0.FirstSample, cfg.data.t0) assertEquals(AxisLabelMode.INSIDE, cfg.axis.xLabelMode) assertEquals(AxisLabelMode.INSIDE, cfg.axis.yLabelMode) assertEquals(2, cfg.axis.yLabelDecimals) assertTrue(cfg.axis.showGrid) assertEquals(ChartTheme(), cfg.render.theme) assertEquals(FrameRate.Display, cfg.render.frameRate) } @Test fun ChartConfig_subConfigsOverride() { // Override only DataConfig.xWindowSeconds; other fields remain default. val cfg = ChartConfig(data = DataConfig(xWindowSeconds = 30f)) assertEquals(30f, cfg.data.xWindowSeconds) // Other DataConfig defaults preserved. assertTrue(cfg.data.yRange is YRange.Auto) assertEquals(T0.FirstSample, cfg.data.t0) // AxisConfig and RenderConfig untouched → equal to defaults. assertEquals(AxisConfig(), cfg.axis) // RenderConfig has lodStrategy with fresh allocation each call; compare type only. assertEquals(FrameRate.Display, cfg.render.frameRate) assertEquals(ChartTheme(), cfg.render.theme) } @Test fun ChartConfig_topLevelAccessors() { // Convenience accessors delegate to nested configs. val theme = ChartTheme(backgroundColor = Color.Magenta) val cfg = ChartConfig( data = DataConfig(xWindowSeconds = 42f), render = RenderConfig(theme = theme), ) assertEquals(42f, cfg.xWindowSeconds) assertEquals(theme, cfg.theme) } @Test fun ChartConfig_equality_isStructural() { // Two ChartConfig() with default DataConfig + AxisConfig should be structurally equal. // RenderConfig default contains a fresh MinMaxLttbLodStrategy() — strategies do not // override equals, so identity differs → render sub-configs are NOT equal. // Pass an explicit shared RenderConfig to assert structural equality on the rest. val sharedRender = RenderConfig() val a = ChartConfig(render = sharedRender) val b = ChartConfig(render = sharedRender) assertEquals(a, b) assertEquals(a.hashCode(), b.hashCode()) } @Test fun FrameRate_FixedValidation_rejectsZero() { assertFailsWith { FrameRate.Fixed(0) } } @Test fun RenderConfig_lodStrategyDefault_isMinMaxLttb() { val rc = RenderConfig() assertTrue( rc.lodStrategy is MinMaxLttbLodStrategy, "default lodStrategy must be MinMaxLttbLodStrategy, got ${rc.lodStrategy::class}" ) } @Test fun AxisConfig_formatterDefaults() { val ac = AxisConfig() assertSame(TimeAxisFormatter, ac.xFormatter) assertEquals(DecimalAxisFormatter(decimals = 2), ac.yFormatter) } @Test fun SignalConfig_defaultRenderer_isLineSignalRenderer() { val sc = SignalConfig(color = Color.Red) assertSame(LineSignalRenderer, sc.renderer, "default renderer must be LineSignalRenderer singleton") } }