pull/330/head
Don Turner 3 years ago
parent d42881e5d4
commit 56c0645816

@ -75,6 +75,8 @@ class NavigationTest {
private lateinit var appName: String private lateinit var appName: String
private lateinit var saved: String private lateinit var saved: String
private lateinit var settings: String private lateinit var settings: String
private lateinit var brand: String
private lateinit var ok: String
@Before @Before
fun setup() { fun setup() {
@ -88,6 +90,8 @@ class NavigationTest {
appName = getString(R.string.app_name) appName = getString(R.string.app_name)
saved = getString(BookmarksR.string.saved) saved = getString(BookmarksR.string.saved)
settings = getString(SettingsR.string.top_app_bar_action_icon_description) settings = getString(SettingsR.string.top_app_bar_action_icon_description)
brand = getString(SettingsR.string.brand_android)
ok = getString(SettingsR.string.dismiss_dialog_button_text)
} }
} }
@ -189,6 +193,31 @@ class NavigationTest {
} }
} }
@Test
fun whenSettingsIconIsClicked_settingsDialogIsShown() {
composeTestRule.apply {
onNodeWithContentDescription(settings).performClick()
// Check that one of the settings is actually displayed.
onNodeWithText(brand).assertExists()
}
}
@Test
fun whenSettingsDialogDismissed_previousScreenIsDisplayed(){
composeTestRule.apply {
// Navigate to the saved screen, open the settings dialog, then close it.
onNodeWithText(saved).performClick()
onNodeWithContentDescription(settings).performClick()
onNodeWithText(ok).performClick()
// Check that the saved screen is still visible and selected.
onNodeWithText(saved).assertIsSelected()
}
}
/* /*
* There should always be at most one instance of a top-level destination at the same time. * There should always be at most one instance of a top-level destination at the same time.
*/ */

@ -0,0 +1,83 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.feature.settings
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithText
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success
import org.junit.Rule
import org.junit.Test
class SettingsDialogTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
private fun getString(id: Int) = composeTestRule.activity.resources.getString(id)
@Test
fun whenLoading_showsLoadingText() {
composeTestRule.setContent {
SettingsDialog(
settingsUiState = Loading,
onDismiss = { },
onChangeThemeBrand = {},
onChangeDarkThemeConfig = {}
)
}
composeTestRule
.onNodeWithText(getString(R.string.loading))
.assertExists()
}
@Test
fun whenStateIsSuccess_allSettingsAreDisplayed(){
composeTestRule.setContent {
SettingsDialog(
settingsUiState = Success(
UserEditableSettings(
brand = ANDROID,
darkThemeConfig = DARK
)
),
onDismiss = { },
onChangeThemeBrand = {},
onChangeDarkThemeConfig = {}
)
}
// Check that all the possible settings are displayed.
composeTestRule.onNodeWithText(getString(R.string.brand_default)).assertExists()
composeTestRule.onNodeWithText(getString(R.string.brand_android)).assertExists()
composeTestRule.onNodeWithText(
getString(R.string.dark_mode_config_system_default)
).assertExists()
composeTestRule.onNodeWithText(getString(R.string.dark_mode_config_light)).assertExists()
composeTestRule.onNodeWithText(getString(R.string.dark_mode_config_dark)).assertExists()
// Check that the correct settings are selected.
composeTestRule.onNodeWithText(getString(R.string.brand_android)).assertIsSelected()
composeTestRule.onNodeWithText(getString(R.string.dark_mode_config_dark)).assertIsSelected()
}
}

@ -25,8 +25,10 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -53,6 +55,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.LIGH
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT
import com.google.samples.apps.nowinandroid.feature.settings.R.string
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success
@ -73,8 +76,8 @@ internal fun SettingsDialog(
@Composable @Composable
fun SettingsDialog( fun SettingsDialog(
onDismiss: () -> Unit,
settingsUiState: SettingsUiState, settingsUiState: SettingsUiState,
onDismiss: () -> Unit,
onChangeThemeBrand: (themeBrand: ThemeBrand) -> Unit, onChangeThemeBrand: (themeBrand: ThemeBrand) -> Unit,
onChangeDarkThemeConfig: (darkThemeConfig: DarkThemeConfig) -> Unit onChangeDarkThemeConfig: (darkThemeConfig: DarkThemeConfig) -> Unit
) { ) {
@ -88,8 +91,8 @@ fun SettingsDialog(
) )
}, },
text = { text = {
Column { Divider()
Divider() Column (Modifier.verticalScroll(rememberScrollState())) {
when (settingsUiState) { when (settingsUiState) {
Loading -> { Loading -> {
Text( Text(
@ -111,7 +114,7 @@ fun SettingsDialog(
}, },
confirmButton = { confirmButton = {
Text( Text(
text = "OK", text = stringResource(string.dismiss_dialog_button_text),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
modifier = Modifier modifier = Modifier
@ -182,7 +185,7 @@ fun SettingsDialogThemeChooserRow(
.selectable( .selectable(
selected = selected, selected = selected,
role = Role.RadioButton, role = Role.RadioButton,
onClick = onClick onClick = onClick,
) )
.padding(8.dp), .padding(8.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically

@ -73,5 +73,5 @@ data class UserEditableSettings(val brand: ThemeBrand, val darkThemeConfig: Dark
sealed interface SettingsUiState { sealed interface SettingsUiState {
object Loading : SettingsUiState object Loading : SettingsUiState
class Success(val settings: UserEditableSettings) : SettingsUiState data class Success(val settings: UserEditableSettings) : SettingsUiState
} }

@ -26,4 +26,5 @@
<string name="dark_mode_config_system_default">System default</string> <string name="dark_mode_config_system_default">System default</string>
<string name="dark_mode_config_light">Light</string> <string name="dark_mode_config_light">Light</string>
<string name="dark_mode_config_dark">Dark</string> <string name="dark_mode_config_dark">Dark</string>
<string name="dismiss_dialog_button_text">OK</string>
</resources> </resources>

@ -0,0 +1,73 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.feature.settings
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success
import junit.framework.Assert.assertEquals
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
class SettingsViewModelTest {
@get:Rule
val mainDispatcherRule = MainDispatcherRule()
private val userDataRepository = TestUserDataRepository()
private lateinit var viewModel: SettingsViewModel
@Before
fun setup() {
viewModel = SettingsViewModel(userDataRepository)
}
@Test
fun stateIsInitiallyLoading() = runTest {
assertEquals(Loading, viewModel.settingsUiState.value)
}
@Test
fun stateIsSuccessAfterUserDataLoaded() = runTest {
val collectJob =
launch(UnconfinedTestDispatcher()) { viewModel.settingsUiState.collect() }
userDataRepository.setThemeBrand(ANDROID)
userDataRepository.setDarkThemeConfig(DARK)
assertEquals(
Success(
UserEditableSettings(
brand = ANDROID,
darkThemeConfig = DARK
)
),
viewModel.settingsUiState.value)
collectJob.cancel()
}
}
Loading…
Cancel
Save