Add additional test cases for MyLocationsList

This commit is contained in:
Nebojsa Vuksic 2025-07-31 15:01:00 +02:00
parent e791d63d22
commit 45ef9a28da

View File

@ -3,6 +3,7 @@ package org.jetbrains.plugins.template
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
@ -23,24 +24,136 @@ import org.junit.Test
internal class MyLocationListTest {
@get:Rule
val composeRule = createComposeRule()
private val noLocations = emptyList<Location>()
private val myLocationsViewModelApi = FakeMyLocationsViewModel(locations = noLocations)
@Test
fun `show placeholder when no locations is added`() = runTest {
val myLocationsRobot = MyLocationListRobot(composeRule)
composeRule.setContentWrappedInTheme {
val noLocations = emptyList<Location>()
val myLocationsViewModel = FakeMyLocationsViewModel(locations = noLocations)
MyLocationsListWithEmptyListPlaceholder(
modifier = Modifier.fillMaxWidth(),
myLocationsViewModelApi = myLocationsViewModel
)
}
fun `verify placeholder is shown when no locations is added`() = composeRule.runComposeTest {
val myLocationsRobot = MyLocationListRobot(this)
myLocationsRobot
.verifyNoLocationsPlaceHolderVisible()
}
@Test
fun `verify location is selected when user adds location`() = composeRule.runComposeTest { locationsViewModelApi ->
val myLocationsRobot = MyLocationListRobot(this)
locationsViewModelApi.onAddLocation(Location("Munich", "Germany"))
myLocationsRobot
.verifyListItemWithTextIsSelected("Munich, Germany")
}
@Test
fun `verify item selection when multiple items are present`() = composeRule.runComposeTest { locationsViewModelApi ->
val myLocationsRobot = MyLocationListRobot(this)
// Add multiple locations
locationsViewModelApi.onAddLocation(Location("Munich", "Germany"))
locationsViewModelApi.onAddLocation(Location("Berlin", "Germany"))
locationsViewModelApi.onAddLocation(Location("Paris", "France"))
// Initially, the last added location (Paris) should be selected
myLocationsRobot.verifyListItemWithTextIsSelected("Paris, France")
// Select a different location
myLocationsRobot.clickOnItemWithText("Berlin, Germany")
// Verify the clicked location is now selected
myLocationsRobot.verifyListItemWithTextIsSelected("Berlin, Germany")
}
@Test
fun `verify item deletion when multiple items are present`() = composeRule.runComposeTest { locationsViewModelApi ->
val myLocationsRobot = MyLocationListRobot(this)
// Add multiple locations
val munich = Location("Munich", "Germany")
val berlin = Location("Berlin", "Germany")
val paris = Location("Paris", "France")
locationsViewModelApi.onAddLocation(munich)
locationsViewModelApi.onAddLocation(berlin)
locationsViewModelApi.onAddLocation(paris)
// Initially, the last added location (Paris) should be selected
myLocationsRobot.verifyListItemWithTextIsSelected("Paris, France")
// Delete the selected location (Paris)
locationsViewModelApi.onDeleteLocation(paris)
// Verify Paris is no longer in the list and Berlin is now selected
// (as it's the last item in the list after deletion)
myLocationsRobot.verifyItemDoesNotExist("Paris, France")
myLocationsRobot.verifyListItemWithTextIsSelected("Berlin, Germany")
}
@Test
fun `verify middle item deletion when three items are present`() = composeRule.runComposeTest { locationsViewModelApi ->
val myLocationsRobot = MyLocationListRobot(this)
// Add three locations
val munich = Location("Munich", "Germany")
val berlin = Location("Berlin", "Germany")
val paris = Location("Paris", "France")
locationsViewModelApi.onAddLocation(munich)
locationsViewModelApi.onAddLocation(berlin)
locationsViewModelApi.onAddLocation(paris)
// Initially, the last added location (Paris) should be selected
myLocationsRobot.verifyListItemWithTextIsSelected("Paris, France")
// Delete the middle location (Berlin)
locationsViewModelApi.onDeleteLocation(berlin)
// Verify Berlin is no longer in the list
myLocationsRobot.verifyItemDoesNotExist("Berlin, Germany")
// Verify Munich and Paris still exist
myLocationsRobot.verifyItemExists("Munich, Germany")
myLocationsRobot.verifyItemExists("Paris, France")
// Paris should still be selected as it was the selected item before deletion
myLocationsRobot.verifyListItemWithTextIsSelected("Paris, France")
}
@Test
fun `verify deletion of the only item in list`() = composeRule.runComposeTest { locationsViewModelApi ->
val myLocationsRobot = MyLocationListRobot(this)
// Add one location
val munich = Location("Munich", "Germany")
locationsViewModelApi.onAddLocation(munich)
// Verify the location is selected
myLocationsRobot.verifyListItemWithTextIsSelected("Munich, Germany")
// Delete the only location
locationsViewModelApi.onDeleteLocation(munich)
// Verify the location is no longer in the list
myLocationsRobot.verifyItemDoesNotExist("Munich, Germany")
// Verify the empty list placeholder is shown
myLocationsRobot.verifyNoLocationsPlaceHolderVisible()
}
private fun ComposeContentTestRule.runComposeTest(
myLocationsViewModelApi: MyLocationsViewModelApi = this@MyLocationListTest.myLocationsViewModelApi,
block: suspend ComposeContentTestRule.(MyLocationsViewModelApi) -> Unit
) = runTest {
this@runComposeTest.setContentWrappedInTheme {
MyLocationsListWithEmptyListPlaceholder(
modifier = Modifier.fillMaxWidth(),
myLocationsViewModelApi = myLocationsViewModelApi
)
}
this@runComposeTest.block(myLocationsViewModelApi)
}
private class FakeMyLocationsViewModel(
locations: List<Location> = emptyList()
) : MyLocationsViewModelApi {
@ -60,13 +173,17 @@ internal class MyLocationListTest {
override fun onAddLocation(locationToAdd: Location) {
val currentLocations = locationsFlow.value
currentLocations.add(locationToAdd)
locationsFlow.value = currentLocations
selectedItemIndex.value = currentLocations.lastIndex
}
override fun onDeleteLocation(locationToDelete: Location) {
val currentLocations = locationsFlow.value
currentLocations.remove(locationToDelete)
locationsFlow.value = currentLocations
selectedItemIndex.value = currentLocations.lastIndex
}
override fun onLocationSelected(selectedLocationIndex: Int) {
@ -84,6 +201,7 @@ internal class MyLocationListTest {
}
private class MyLocationListRobot(private val composableRule: ComposeContentTestRule) {
fun clickOnItemWithText(text: String) {
composableRule
.onNodeWithText(text)
@ -94,8 +212,28 @@ private class MyLocationListRobot(private val composableRule: ComposeContentTest
composableRule
.onNodeWithText("No locations added yet. Go and add the first location.")
.assertExists()
composableRule
.onNodeWithContentDescription("Empty list icon.")
.assertExists()
}
fun verifyListItemWithTextIsSelected(text: String) {
composableRule
.onNodeWithText(text)
.assertExists()
.assertIsSelected()
}
fun verifyItemDoesNotExist(text: String) {
composableRule
.onNodeWithText(text)
.assertDoesNotExist()
}
fun verifyItemExists(text: String) {
composableRule
.onNodeWithText(text)
.assertExists()
}
}