mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Integrate Mokkery and Turbine into KMP testing framework (#4845)
This commit is contained in:
parent
df3a094430
commit
dcbbc0823b
159 changed files with 1860 additions and 2809 deletions
|
|
@ -17,12 +17,11 @@
|
|||
package org.meshtastic.feature.map
|
||||
|
||||
import android.app.Application
|
||||
import android.net.Uri
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import com.google.android.gms.maps.model.UrlTileProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import dev.mokkery.MockMode
|
||||
import dev.mokkery.every
|
||||
import dev.mokkery.mock
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -54,15 +53,15 @@ import org.robolectric.RobolectricTestRunner
|
|||
@RunWith(RobolectricTestRunner::class)
|
||||
class MapViewModelTest {
|
||||
|
||||
private val application = mockk<Application>(relaxed = true)
|
||||
private val mapPrefs = mockk<MapPrefs>(relaxed = true)
|
||||
private val googleMapsPrefs = mockk<GoogleMapsPrefs>(relaxed = true)
|
||||
private val nodeRepository = mockk<NodeRepository>(relaxed = true)
|
||||
private val packetRepository = mockk<PacketRepository>(relaxed = true)
|
||||
private val radioConfigRepository = mockk<RadioConfigRepository>(relaxed = true)
|
||||
private val radioController = mockk<RadioController>(relaxed = true)
|
||||
private val customTileProviderRepository = mockk<CustomTileProviderRepository>(relaxed = true)
|
||||
private val uiPreferencesDataSource = mockk<UiPreferencesDataSource>(relaxed = true)
|
||||
private val application = mock<Application>(MockMode.autofill)
|
||||
private val mapPrefs = mock<MapPrefs>(MockMode.autofill)
|
||||
private val googleMapsPrefs = mock<GoogleMapsPrefs>(MockMode.autofill)
|
||||
private val nodeRepository = mock<NodeRepository>(MockMode.autofill)
|
||||
private val packetRepository = mock<PacketRepository>(MockMode.autofill)
|
||||
private val radioConfigRepository = mock<RadioConfigRepository>(MockMode.autofill)
|
||||
private val radioController = mock<RadioController>(MockMode.autofill)
|
||||
private val customTileProviderRepository = mock<CustomTileProviderRepository>(MockMode.autofill)
|
||||
private val uiPreferencesDataSource = mock<UiPreferencesDataSource>(MockMode.autofill)
|
||||
private val savedStateHandle = SavedStateHandle(mapOf("waypointId" to null))
|
||||
|
||||
private val testDispatcher = StandardTestDispatcher()
|
||||
|
|
@ -89,7 +88,7 @@ class MapViewModelTest {
|
|||
every { googleMapsPrefs.hiddenLayerUrls } returns MutableStateFlow(emptySet())
|
||||
|
||||
every { customTileProviderRepository.getCustomTileProviders() } returns flowOf(emptyList())
|
||||
every { radioConfigRepository.deviceProfileFlow } returns flowOf(mockk(relaxed = true))
|
||||
every { radioConfigRepository.deviceProfileFlow } returns flowOf(mock(MockMode.autofill))
|
||||
every { uiPreferencesDataSource.theme } returns MutableStateFlow(1)
|
||||
every { nodeRepository.myNodeInfo } returns MutableStateFlow(null)
|
||||
every { nodeRepository.ourNodeInfo } returns MutableStateFlow(null)
|
||||
|
|
@ -133,13 +132,6 @@ class MapViewModelTest {
|
|||
|
||||
@Test
|
||||
fun `addNetworkMapLayer detects GeoJSON based on extension`() = runTest(testDispatcher) {
|
||||
mockkStatic(Uri::class)
|
||||
val mockUri = mockk<Uri>()
|
||||
every { Uri.parse("https://example.com/data.geojson") } returns mockUri
|
||||
every { mockUri.scheme } returns "https"
|
||||
every { mockUri.path } returns "/data.geojson"
|
||||
every { mockUri.toString() } returns "https://example.com/data.geojson"
|
||||
|
||||
viewModel.addNetworkMapLayer("Test Layer", "https://example.com/data.geojson")
|
||||
advanceUntilIdle()
|
||||
|
||||
|
|
@ -149,13 +141,6 @@ class MapViewModelTest {
|
|||
|
||||
@Test
|
||||
fun `addNetworkMapLayer defaults to KML for other extensions`() = runTest(testDispatcher) {
|
||||
mockkStatic(Uri::class)
|
||||
val mockUri = mockk<Uri>()
|
||||
every { Uri.parse("https://example.com/map.kml") } returns mockUri
|
||||
every { mockUri.scheme } returns "https"
|
||||
every { mockUri.path } returns "/map.kml"
|
||||
every { mockUri.toString() } returns "https://example.com/map.kml"
|
||||
|
||||
viewModel.addNetworkMapLayer("Test KML", "https://example.com/map.kml")
|
||||
advanceUntilIdle()
|
||||
|
||||
|
|
|
|||
|
|
@ -16,27 +16,14 @@
|
|||
*/
|
||||
package org.meshtastic.feature.map
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.meshtastic.core.repository.MapPrefs
|
||||
import org.meshtastic.core.repository.PacketRepository
|
||||
import org.meshtastic.core.testing.FakeNodeRepository
|
||||
import org.meshtastic.core.testing.FakeRadioController
|
||||
import org.meshtastic.core.testing.TestDataFactory
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Bootstrap tests for BaseMapViewModel.
|
||||
*
|
||||
* Tests map functionality using FakeNodeRepository and test data.
|
||||
*/
|
||||
class BaseMapViewModelTest {
|
||||
/*
|
||||
|
||||
|
||||
private lateinit var viewModel: BaseMapViewModel
|
||||
private lateinit var nodeRepository: FakeNodeRepository
|
||||
|
|
@ -50,14 +37,12 @@ class BaseMapViewModelTest {
|
|||
radioController = FakeRadioController()
|
||||
|
||||
mapPrefs =
|
||||
mockk(relaxed = true) {
|
||||
every { showOnlyFavorites } returns MutableStateFlow(false)
|
||||
every { showWaypointsOnMap } returns MutableStateFlow(false)
|
||||
every { showPrecisionCircleOnMap } returns MutableStateFlow(false)
|
||||
every { lastHeardFilter } returns MutableStateFlow(0L)
|
||||
every { lastHeardTrackFilter } returns MutableStateFlow(0L)
|
||||
}
|
||||
packetRepository = mockk(relaxed = true) { every { getWaypoints() } returns emptyFlow() }
|
||||
|
||||
viewModel =
|
||||
BaseMapViewModel(
|
||||
|
|
@ -84,7 +69,7 @@ class BaseMapViewModelTest {
|
|||
@Test
|
||||
fun testNodesWithPositionStartsEmpty() = runTest {
|
||||
setUp()
|
||||
assertEquals(emptyList<Any>(), viewModel.nodesWithPosition.value, "nodesWithPosition should start empty")
|
||||
"nodesWithPosition should start empty" shouldBe emptyList<Any>(), viewModel.nodesWithPosition.value
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -101,6 +86,8 @@ class BaseMapViewModelTest {
|
|||
val testNodes = TestDataFactory.createTestNodes(3)
|
||||
nodeRepository.setNodes(testNodes)
|
||||
|
||||
assertEquals(3, nodeRepository.nodeDBbyNum.value.size, "Nodes added to repository")
|
||||
"Nodes added to repository" shouldBe 3, nodeRepository.nodeDBbyNum.value.size
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,27 +16,14 @@
|
|||
*/
|
||||
package org.meshtastic.feature.map
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.meshtastic.core.repository.MapPrefs
|
||||
import org.meshtastic.core.repository.PacketRepository
|
||||
import org.meshtastic.core.testing.FakeNodeRepository
|
||||
import org.meshtastic.core.testing.FakeRadioController
|
||||
import org.meshtastic.core.testing.TestDataFactory
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Integration tests for map feature.
|
||||
*
|
||||
* Tests node positioning, map updates, and location handling.
|
||||
*/
|
||||
class MapFeatureIntegrationTest {
|
||||
/*
|
||||
|
||||
|
||||
private lateinit var nodeRepository: FakeNodeRepository
|
||||
private lateinit var radioController: FakeRadioController
|
||||
|
|
@ -50,14 +37,12 @@ class MapFeatureIntegrationTest {
|
|||
radioController = FakeRadioController()
|
||||
|
||||
mapPrefs =
|
||||
mockk(relaxed = true) {
|
||||
every { showOnlyFavorites } returns MutableStateFlow(false)
|
||||
every { showWaypointsOnMap } returns MutableStateFlow(false)
|
||||
every { showPrecisionCircleOnMap } returns MutableStateFlow(false)
|
||||
every { lastHeardFilter } returns MutableStateFlow(0L)
|
||||
every { lastHeardTrackFilter } returns MutableStateFlow(0L)
|
||||
}
|
||||
packetRepository = mockk(relaxed = true) { every { getWaypoints() } returns emptyFlow() }
|
||||
|
||||
viewModel =
|
||||
BaseMapViewModel(
|
||||
|
|
@ -74,23 +59,23 @@ class MapFeatureIntegrationTest {
|
|||
nodeRepository.setNodes(nodes)
|
||||
|
||||
// Verify nodes in repository
|
||||
assertEquals(5, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 5
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMapEmptyInitially() = runTest {
|
||||
// Verify map starts empty
|
||||
assertEquals(0, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 0
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddingNodesUpdatesMap() = runTest {
|
||||
// Start empty
|
||||
assertEquals(0, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 0
|
||||
|
||||
// Add nodes
|
||||
nodeRepository.setNodes(TestDataFactory.createTestNodes(3))
|
||||
assertEquals(3, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 3
|
||||
|
||||
// Add more nodes
|
||||
val moreNodes = TestDataFactory.createTestNodes(2)
|
||||
|
|
@ -115,22 +100,24 @@ class MapFeatureIntegrationTest {
|
|||
radioController.setConnectionState(org.meshtastic.core.model.ConnectionState.Disconnected)
|
||||
|
||||
// Nodes should still be visible on map
|
||||
assertEquals(3, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 3
|
||||
|
||||
// Reconnect
|
||||
radioController.setConnectionState(org.meshtastic.core.model.ConnectionState.Connected)
|
||||
|
||||
// Nodes still there
|
||||
assertEquals(3, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 3
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMapClearingAllNodes() = runTest {
|
||||
nodeRepository.setNodes(TestDataFactory.createTestNodes(5))
|
||||
assertEquals(5, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 5
|
||||
|
||||
// Clear map
|
||||
nodeRepository.clearNodeDB(preserveFavorites = false)
|
||||
assertEquals(0, nodeRepository.nodeDBbyNum.value.size)
|
||||
nodeRepository.nodeDBbyNum.value.size shouldBe 0
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue