Jetpack Compose App - Error Screen UI Test

Objective:

Add android UI tests for the Error Screen. The Error Screen is designed to provide an internationalized error message prefix in the in-app chosen language. So, for example, if an in-chosen language is French, the error message should start with "Erreur: " prefix. It should also support the RTL flow for the Arabic language. These UI tests will use DeviceConfigurationOverride API to specify locales and assert the display of the appropriate wording. Spoiler alert: a few tests will fail - we will fix the problems in a later post.

Components built

We will add the following components:

  • ErrorScreenTest.kt: Class for testing the Error Screen

Code

ErrorScreenTest.kt

Add ErrorScreenTest.kt to the com.coroutines.thisdayinhistory.screens.main package in the androidTest source set:


package com.coroutines.thisdayinhistory.screens.main

import androidx.compose.foundation.background
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.Locales
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.text.intl.LocaleList
import com.coroutines.thisdayinhistory.R
import com.coroutines.thisdayinhistory.ui.screens.main.HistoryScreenError
import com.coroutines.thisdayinhistory.ui.theme.ThisDayInHistoryTheme
import com.coroutines.thisdayinhistory.ui.theme.ThisDayInHistoryThemeEnum
import com.coroutines.thisdayinhistory.ui.viewmodels.SettingsViewModelMock
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test


class ErrorScreenTest {

    @get:Rule
    val composeTestRule = createComposeRule()
    private val errorMessage = "test"
    private var expectedDisplayedErrorMessage = ""


    @Test
    fun screenErrorDutchLocaleNotInAppLanguageTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("nl"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Light)
                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        //expect to fall back on English
                        expectedDisplayedErrorMessage = "There was an error: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorArabicLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("ar"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Light)
                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "errorMessage :" + "خطأ"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorSpanishLocaleTest() = runTest {
        composeTestRule.setContent {
            val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Light)
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("es"))
            ) {
                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "Error: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorGermanLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("de"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Light)
                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage =
                            stringResource(id = R.string.error_message_prefix)
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorSwedishLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("se"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)

                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {

                        expectedDisplayedErrorMessage =
                            stringResource(id = R.string.error_message_prefix)
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorRussianLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("ru"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)

                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "Ошибка: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorPortugueseLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("pt"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)

                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "Erro: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorItalianLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("it"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)

                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "Errore: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage, true)
            .assertIsDisplayed()
    }

    @Test
    fun screenErrorSwissItalianLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("it-CH"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)

                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {


                        expectedDisplayedErrorMessage = "Errore: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }
        }

        composeTestRule
            .onNodeWithText(expectedDisplayedErrorMessage)
            .assertIsDisplayed()
    }


    @Test
    fun screenErrorFrenchLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("fr"))
            ) {
                val settingsViewModel =
                    SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)

                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "Erreur: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
                }
            }

            composeTestRule
                .onNodeWithText(expectedDisplayedErrorMessage)
                .assertIsDisplayed()
        }

    @Test
    fun screenErrorFrenchMonacoLocaleTest() {
        composeTestRule.setContent {
            DeviceConfigurationOverride(
                DeviceConfigurationOverride.Locales(LocaleList("fr-MC"))
            ) {
                val settingsViewModel = SettingsViewModelMock(ThisDayInHistoryThemeEnum.Dark)
                
                ThisDayInHistoryTheme(viewModel = settingsViewModel) {
                    val appThemeColor = MaterialTheme.colorScheme.background
                    Surface(
                        modifier = Modifier.background(appThemeColor)
                    ) {
                        expectedDisplayedErrorMessage = "Erreur: $errorMessage"
                        HistoryScreenError(errorMessage = errorMessage)
                    }
                }
            }

            composeTestRule
                .onNodeWithText(expectedDisplayedErrorMessage)
                .assertIsDisplayed()
        }
    }

}