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

@ -75,6 +75,8 @@ class NavigationTest {
private lateinit var appName: String
private lateinit var saved: String
private lateinit var settings: String
private lateinit var brand: String
private lateinit var ok: String
@Before
fun setup() {
@ -88,6 +90,8 @@ class NavigationTest {
appName = getString(R.string.app_name)
saved = getString(BookmarksR.string.saved)
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.
*/

@ -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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Divider
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.ANDROID
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.Success
@ -73,8 +76,8 @@ internal fun SettingsDialog(
@Composable
fun SettingsDialog(
onDismiss: () -> Unit,
settingsUiState: SettingsUiState,
onDismiss: () -> Unit,
onChangeThemeBrand: (themeBrand: ThemeBrand) -> Unit,
onChangeDarkThemeConfig: (darkThemeConfig: DarkThemeConfig) -> Unit
) {
@ -88,8 +91,8 @@ fun SettingsDialog(
)
},
text = {
Column {
Divider()
Divider()
Column (Modifier.verticalScroll(rememberScrollState())) {
when (settingsUiState) {
Loading -> {
Text(
@ -111,7 +114,7 @@ fun SettingsDialog(
},
confirmButton = {
Text(
text = "OK",
text = stringResource(string.dismiss_dialog_button_text),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier
@ -182,7 +185,7 @@ fun SettingsDialogThemeChooserRow(
.selectable(
selected = selected,
role = Role.RadioButton,
onClick = onClick
onClick = onClick,
)
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically

@ -73,5 +73,5 @@ data class UserEditableSettings(val brand: ThemeBrand, val darkThemeConfig: Dark
sealed interface 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_light">Light</string>
<string name="dark_mode_config_dark">Dark</string>
<string name="dismiss_dialog_button_text">OK</string>
</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