From e141e1ef46ebb2a61f452122201a77527a5a1c9e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 09:02:46 +0000 Subject: fix+feat: CI build fixes and hardware source feature flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI fixes: - ParticleWindView: bounds.lonEast → bounds.northEast.longitude (MapLibre 13.x API; lonEast not available as property) - VesselRegistryFragment: Vessel(id="") and CrewMember(id="") → include required name="" so copy() compiles Hardware source feature flags: - HardwareSource enum: AIS_RECEIVER, NMEA_INSTRUMENTS - FeatureFlags: SharedPreferences-backed; all sources default OFF (app works phone-only out of the box) - NavApplication: exposes featureFlags singleton - SafetyFragment: "HARDWARE DATA SOURCES" card with two MaterialSwitch toggles; reads initial state from FeatureFlags; calls SafetyListener.onHardwareSourceChanged on change - AIS_RECEIVER flag: - MainViewModel.processAisSentence() / refreshAisFromInternet() skip when disabled; onHardwareSourceChanged() clears targets + cpaAlerts - NMEA_INSTRUMENTS flag: - LocationService skips nmeaStreamManager.start() on service launch when disabled - New ACTION_START_NMEA / ACTION_STOP_NMEA intents allow live toggle - MainActivity.onHardwareSourceChanged() sends the appropriate intent Tests: 102 total, all GREEN (+7 FeatureFlagsTest) https://claude.ai/code/session_011h2dXbgXg3PesQMmQUNTCW --- .../org/terst/nav/settings/HardwareSource.kt | 23 ++++++++ .../org/terst/nav/settings/FeatureFlagsTest.kt | 61 ++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 test-runner/src/main/kotlin/org/terst/nav/settings/HardwareSource.kt create mode 100644 test-runner/src/test/kotlin/org/terst/nav/settings/FeatureFlagsTest.kt (limited to 'test-runner/src') diff --git a/test-runner/src/main/kotlin/org/terst/nav/settings/HardwareSource.kt b/test-runner/src/main/kotlin/org/terst/nav/settings/HardwareSource.kt new file mode 100644 index 0000000..b44cb66 --- /dev/null +++ b/test-runner/src/main/kotlin/org/terst/nav/settings/HardwareSource.kt @@ -0,0 +1,23 @@ +package org.terst.nav.settings + +enum class HardwareSource(val prefKey: String, val label: String) { + AIS_RECEIVER("hw_ais_receiver", "AIS Receiver"), + NMEA_INSTRUMENTS("hw_nmea_instruments", "NMEA Instruments") +} + +/** Minimal in-memory implementation for JVM tests. */ +class InMemoryFeatureFlags { + private val state = mutableMapOf() + + fun isEnabled(source: HardwareSource): Boolean = state[source] ?: false + + fun setEnabled(source: HardwareSource, enabled: Boolean) { + state[source] = enabled + } + + fun toggle(source: HardwareSource): Boolean { + val next = !isEnabled(source) + setEnabled(source, next) + return next + } +} diff --git a/test-runner/src/test/kotlin/org/terst/nav/settings/FeatureFlagsTest.kt b/test-runner/src/test/kotlin/org/terst/nav/settings/FeatureFlagsTest.kt new file mode 100644 index 0000000..a8e8271 --- /dev/null +++ b/test-runner/src/test/kotlin/org/terst/nav/settings/FeatureFlagsTest.kt @@ -0,0 +1,61 @@ +package org.terst.nav.settings + +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test + +class FeatureFlagsTest { + + private lateinit var flags: InMemoryFeatureFlags + + @Before + fun setup() { + flags = InMemoryFeatureFlags() + } + + @Test + fun `all sources default to disabled`() { + for (source in HardwareSource.values()) { + assertFalse("Expected $source to be disabled by default", flags.isEnabled(source)) + } + } + + @Test + fun `setEnabled true enables source`() { + flags.setEnabled(HardwareSource.AIS_RECEIVER, true) + assertTrue(flags.isEnabled(HardwareSource.AIS_RECEIVER)) + } + + @Test + fun `setEnabled false disables source`() { + flags.setEnabled(HardwareSource.AIS_RECEIVER, true) + flags.setEnabled(HardwareSource.AIS_RECEIVER, false) + assertFalse(flags.isEnabled(HardwareSource.AIS_RECEIVER)) + } + + @Test + fun `toggle flips from false to true`() { + val result = flags.toggle(HardwareSource.NMEA_INSTRUMENTS) + assertTrue(result) + assertTrue(flags.isEnabled(HardwareSource.NMEA_INSTRUMENTS)) + } + + @Test + fun `toggle flips from true to false`() { + flags.setEnabled(HardwareSource.NMEA_INSTRUMENTS, true) + val result = flags.toggle(HardwareSource.NMEA_INSTRUMENTS) + assertFalse(result) + assertFalse(flags.isEnabled(HardwareSource.NMEA_INSTRUMENTS)) + } + + @Test + fun `sources are independent`() { + flags.setEnabled(HardwareSource.AIS_RECEIVER, true) + assertFalse(flags.isEnabled(HardwareSource.NMEA_INSTRUMENTS)) + } + + @Test + fun `toggle returns new state`() { + assertFalse(flags.toggle(HardwareSource.AIS_RECEIVER).also { assertTrue(it) } == false) + } +} -- cgit v1.2.3