package androidavatar.learning.artlearnersapp.presentation.ui
import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.createComposeRule
import org.junit.Rule
import org.junit.Test
class ImageSearchScreenTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun initialScreen_displaysSearchFieldAndButton() {
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = {},
onBack = {},
state = SearchImageUiState()
)
}
composeTestRule.onNodeWithText("Search Image").assertIsDisplayed()
composeTestRule.onNodeWithContentDescription("Search").assertIsDisplayed()
}
@Test
fun whenLoading_showsCircularProgressIndicator() {
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = {},
onBack = {},
state = SearchImageUiState(isLoading = true)
)
}
composeTestRule.onNodeWithTag("Progress").assertExists()
}
@Test
fun whenErrorMessagePresent_displaysErrorAndButton() {
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = {},
onBack = {},
state = SearchImageUiState(errorMessage = "Network Error")
)
}
composeTestRule.onNodeWithText("Network Error").assertIsDisplayed()
composeTestRule.onNodeWithText("Go Back").assertIsDisplayed()
}
@Test
fun enteringValidQuery_triggersOnSearchCallback() {
var queryTriggered = false
var receivedQuery: String? = null
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {
queryTriggered = true
receivedQuery = it
},
onImageClick = {},
onBack = {},
state = SearchImageUiState()
)
}
composeTestRule.onNodeWithText("Search Image").performTextInput("mountain")
composeTestRule.onNodeWithContentDescription("Search").performClick()
assert(queryTriggered)
assert(receivedQuery == "mountain")
}
@Test
fun enteringShortQuery_doesNotTriggerSearch() {
var searchTriggered = false
composeTestRule.setContent {
ImageSearchScreen(
onSearch = { searchTriggered = true },
onImageClick = {},
onBack = {},
state = SearchImageUiState()
)
}
composeTestRule.onNodeWithText("Search Image").performTextInput("ab")
composeTestRule.onNodeWithContentDescription("Search").performClick()
assert(!searchTriggered)
}
@Test
fun clickingImage_triggersImageClickCallback() {
val fakeUrls = listOf("url1", "url2")
var clickedUrl: String? = null
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = { clickedUrl = it },
onBack = {},
state = SearchImageUiState(searchResults = fakeUrls)
)
}
composeTestRule.onAllNodes(hasContentDescription("Search result image"))
.onFirst()
.performClick()
assert(clickedUrl == "url1")
}
@Test
fun loadingState_hidesImagesAndErrorMessage() {
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = {},
onBack = {},
state = SearchImageUiState(isLoading = true)
)
}
composeTestRule.onNodeWithTag("Progress").assertExists()
composeTestRule.onNodeWithText("Go Back").assertDoesNotExist()
composeTestRule.onAllNodes(hasContentDescription("Search result image"))
.assertCountEquals(0)
}
@Test
fun whenResultsAvailable_displaysGridOfImages() {
val fakeUrls = listOf("url1", "url2", "url3")
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = {},
onBack = {},
state = SearchImageUiState(searchResults = fakeUrls)
)
}
composeTestRule.onAllNodes(hasContentDescription("Search result image"))
.assertCountEquals(3)
}
@Test
fun whenError_displaysOnlyErrorUI() {
composeTestRule.setContent {
ImageSearchScreen(
onSearch = {},
onImageClick = {},
onBack = {},
state = SearchImageUiState(errorMessage = "Something went wrong")
)
}
composeTestRule.onNodeWithText("Something went wrong").assertIsDisplayed()
composeTestRule.onNodeWithTag("Progress").assertDoesNotExist()
composeTestRule.onAllNodes(hasContentDescription("Search result image"))
.assertCountEquals(0)
}
}