test: Add comprehensive tests for WiFi signal strength (RSSI) feature

- Add AndroidDeviceInfoProviderTest.kt with 14 unit tests
  * Tests for getWifiSignalStrength() method covering:
    - Valid RSSI values (strong, medium, weak signals)
    - Null handling (WiFi manager unavailable, connection info null, RSSI -127)
    - Exception handling
  * Tests for getBatteryLevel() method covering:
    - Valid battery percentages (0%, 85%, 100%)
    - Null handling (battery manager unavailable)
    - Exception handling

- Add 8 integration tests to TrmnlDisplayRepositoryTest.kt
  * Verify RSSI is sent only for BYOD devices
  * Verify RSSI is NOT sent for TRMNL and BYOS devices
  * Test RSSI with various signal strengths (-30, -65, -90 dBm)
  * Test null RSSI handling when WiFi unavailable
  * Verify getWifiSignalStrength() is called only for BYOD

Total: 22 new tests added (199 tests total, up from 178)
All tests passing with no failures.
This commit is contained in:
Hossain Khan
2026-01-31 21:38:30 -05:00
parent 49a38d6182
commit 662641fa39
2 changed files with 453 additions and 0 deletions
@@ -701,4 +701,225 @@ class TrmnlDisplayRepositoryTest {
coVerify(exactly = 1) { androidDeviceInfoProvider.getBatteryLevel() }
coVerify(exactly = 0) { userApiService.updateDevice(any(), any(), any()) }
}
// WiFi Signal Strength (RSSI) Tests
@Test
fun `getNextDisplayData should send RSSI for BYOD device when WiFi available`() =
runTest {
// Arrange
val byodConfig =
byodDeviceConfig.copy(
deviceId = null,
userApiToken = "test_token",
apiAccessToken = "test_api_key",
)
val expectedRssi = -65
every { androidDeviceInfoProvider.getWifiSignalStrength() } returns expectedRssi
coEvery {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = expectedRssi,
)
} returns ApiResult.success(mockk(relaxed = true))
// Act
repository.getNextDisplayData(byodConfig)
// Assert - Verify RSSI was fetched and sent
coVerify(exactly = 1) { androidDeviceInfoProvider.getWifiSignalStrength() }
coVerify {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = expectedRssi,
)
}
}
@Test
fun `getNextDisplayData should send null RSSI for BYOD when WiFi unavailable`() =
runTest {
// Arrange
val byodConfig =
byodDeviceConfig.copy(
deviceId = null,
userApiToken = "test_token",
apiAccessToken = "test_api_key",
)
every { androidDeviceInfoProvider.getWifiSignalStrength() } returns null
coEvery { apiService.getNextDisplayData(any(), any(), any(), any()) } returns
ApiResult.success(mockk(relaxed = true))
// Act
repository.getNextDisplayData(byodConfig)
// Assert - Verify RSSI was fetched but null was sent
coVerify(exactly = 1) { androidDeviceInfoProvider.getWifiSignalStrength() }
coVerify {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = null,
)
}
}
@Test
fun `getNextDisplayData should NOT send RSSI for TRMNL device`() =
runTest {
// Arrange - TRMNL device (not BYOD)
val trmnlConfig =
testDeviceConfig.copy(
apiAccessToken = "trmnl_api_key",
)
coEvery { apiService.getNextDisplayData(any(), any(), any(), any()) } returns
ApiResult.success(mockk(relaxed = true))
// Act
repository.getNextDisplayData(trmnlConfig)
// Assert - Verify WiFi signal was NOT fetched and null RSSI was sent
coVerify(exactly = 0) { androidDeviceInfoProvider.getWifiSignalStrength() }
coVerify {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = null,
)
}
}
@Test
fun `getNextDisplayData should NOT send RSSI for BYOS device`() =
runTest {
// Arrange - BYOS device uses next display data endpoint (not current_screen)
val byosConfig =
byosDeviceConfig.copy(
apiAccessToken = "byos_api_key",
)
coEvery { apiService.getNextDisplayData(any(), any(), any(), any(), any()) } returns
ApiResult.success(mockk(relaxed = true))
// Act
repository.getNextDisplayData(byosConfig)
// Assert - Verify WiFi signal was NOT fetched for BYOS device
coVerify(exactly = 0) { androidDeviceInfoProvider.getWifiSignalStrength() }
// Verify null RSSI was sent
coVerify {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = null,
)
}
}
@Test
fun `getNextDisplayData should call getWifiSignalStrength only for BYOD devices`() =
runTest {
// Arrange - Multiple device types
val byodConfig = byodDeviceConfig.copy(apiAccessToken = "byod_key")
val trmnlConfig = testDeviceConfig.copy(apiAccessToken = "trmnl_key")
val byosConfig = byosDeviceConfig.copy(apiAccessToken = "byos_key")
every { androidDeviceInfoProvider.getWifiSignalStrength() } returns -70
coEvery { apiService.getNextDisplayData(any(), any(), any(), any(), any()) } returns
ApiResult.success(mockk(relaxed = true))
// Act - Fetch for all device types
repository.getNextDisplayData(byodConfig)
repository.getNextDisplayData(trmnlConfig)
repository.getNextDisplayData(byosConfig)
// Assert - Verify WiFi signal was called only once (for BYOD)
coVerify(exactly = 1) { androidDeviceInfoProvider.getWifiSignalStrength() }
}
@Test
fun `getNextDisplayData should include RSSI in header for BYOD with strong signal`() =
runTest {
// Arrange
val byodConfig = byodDeviceConfig.copy(apiAccessToken = "test_key")
val strongSignal = -30 // Excellent signal
every { androidDeviceInfoProvider.getWifiSignalStrength() } returns strongSignal
coEvery {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = strongSignal,
)
} returns ApiResult.success(mockk(relaxed = true))
// Act
repository.getNextDisplayData(byodConfig)
// Assert
coVerify {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = strongSignal,
)
}
}
@Test
fun `getNextDisplayData should include RSSI in header for BYOD with weak signal`() =
runTest {
// Arrange
val byodConfig = byodDeviceConfig.copy(apiAccessToken = "test_key")
val weakSignal = -90 // Very weak signal
every { androidDeviceInfoProvider.getWifiSignalStrength() } returns weakSignal
coEvery {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = weakSignal,
)
} returns ApiResult.success(mockk(relaxed = true))
// Act
repository.getNextDisplayData(byodConfig)
// Assert
coVerify {
apiService.getNextDisplayData(
fullApiUrl = any(),
accessToken = any(),
deviceMacId = any(),
useBase64 = any(),
rssi = weakSignal,
)
}
}
}
@@ -0,0 +1,232 @@
package ink.trmnl.android.util
import android.content.Context
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.os.BatteryManager
import com.google.common.truth.Truth.assertThat
import io.mockk.every
import io.mockk.mockk
import io.mockk.unmockkAll
import org.junit.After
import org.junit.Before
import org.junit.Test
/**
* Unit tests for [AndroidDeviceInfoProvider].
*/
class AndroidDeviceInfoProviderTest {
private lateinit var context: Context
private lateinit var provider: AndroidDeviceInfoProvider
private lateinit var batteryManager: BatteryManager
private lateinit var wifiManager: WifiManager
private lateinit var wifiInfo: WifiInfo
@Before
fun setup() {
context = mockk(relaxed = true)
batteryManager = mockk()
wifiManager = mockk()
wifiInfo = mockk()
provider = AndroidDeviceInfoProvider(context)
}
@After
fun tearDown() {
unmockkAll()
}
// Battery Level Tests
@Test
fun `getBatteryLevel returns valid percentage when battery manager available`() {
// Arrange
val expectedBatteryLevel = 85
every { context.getSystemService(Context.BATTERY_SERVICE) } returns batteryManager
every { batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) } returns expectedBatteryLevel
// Act
val result = provider.getBatteryLevel()
// Assert
assertThat(result).isEqualTo(expectedBatteryLevel)
}
@Test
fun `getBatteryLevel returns null when battery manager unavailable`() {
// Arrange
every { context.getSystemService(Context.BATTERY_SERVICE) } returns null
// Act
val result = provider.getBatteryLevel()
// Assert
assertThat(result).isNull()
}
@Test
fun `getBatteryLevel returns null when exception occurs`() {
// Arrange
every { context.getSystemService(Context.BATTERY_SERVICE) } throws RuntimeException("Test exception")
// Act
val result = provider.getBatteryLevel()
// Assert
assertThat(result).isNull()
}
@Test
fun `getBatteryLevel returns 0 when battery level is 0`() {
// Arrange
every { context.getSystemService(Context.BATTERY_SERVICE) } returns batteryManager
every { batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) } returns 0
// Act
val result = provider.getBatteryLevel()
// Assert
assertThat(result).isEqualTo(0)
}
@Test
fun `getBatteryLevel returns 100 when battery is full`() {
// Arrange
every { context.getSystemService(Context.BATTERY_SERVICE) } returns batteryManager
every { batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) } returns 100
// Act
val result = provider.getBatteryLevel()
// Assert
assertThat(result).isEqualTo(100)
}
// WiFi Signal Strength Tests
@Test
fun `getWifiSignalStrength returns valid RSSI when WiFi connected`() {
// Arrange
val expectedRssi = -65 // Good signal strength
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns wifiInfo
every { wifiInfo.rssi } returns expectedRssi
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isEqualTo(expectedRssi)
}
@Test
fun `getWifiSignalStrength returns null when WiFi manager unavailable`() {
// Arrange
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns null
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isNull()
}
@Test
fun `getWifiSignalStrength returns null when WiFi info unavailable`() {
// Arrange
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns null
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isNull()
}
@Test
fun `getWifiSignalStrength returns null when RSSI is -127 (no signal)`() {
// Arrange
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns wifiInfo
every { wifiInfo.rssi } returns -127 // Special value indicating no signal
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isNull()
}
@Test
fun `getWifiSignalStrength handles getIntProperty exception`() {
// Arrange
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns wifiInfo
every { wifiInfo.rssi } throws RuntimeException("Access denied")
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isNull()
}
@Test
fun `getWifiSignalStrength returns null when exception occurs`() {
// Arrange
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } throws RuntimeException("Test exception")
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isNull()
}
@Test
fun `getWifiSignalStrength returns strong signal value`() {
// Arrange
val strongSignal = -30 // Excellent signal
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns wifiInfo
every { wifiInfo.rssi } returns strongSignal
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isEqualTo(strongSignal)
}
@Test
fun `getWifiSignalStrength returns weak signal value`() {
// Arrange
val weakSignal = -90 // Very weak signal
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns wifiInfo
every { wifiInfo.rssi } returns weakSignal
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isEqualTo(weakSignal)
}
@Test
fun `getWifiSignalStrength returns medium signal value`() {
// Arrange
val mediumSignal = -70 // Good signal
every { context.applicationContext.getSystemService(Context.WIFI_SERVICE) } returns wifiManager
every { wifiManager.connectionInfo } returns wifiInfo
every { wifiInfo.rssi } returns mediumSignal
// Act
val result = provider.getWifiSignalStrength()
// Assert
assertThat(result).isEqualTo(mediumSignal)
}
}