Workaround to make adaptive info use size override

currentWindowAdaptiveInfo() is not affected by using the ForcedSize
override, so the list detail scaffold directve will be calculated with
non-overridden values. This work around hoists the WindowAdaptiveInfo
so that we can pass in an appropriate value in tests.

Change-Id: Ieef99f6d710ddb70243ac5105aa7805dd638ccf8
pull/1518/head
Jonathan Koren 5 months ago
parent 353623e7ff
commit 500836d806

@ -17,6 +17,8 @@
package com.google.samples.apps.nowinandroid.ui.interests2pane package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.material3.adaptive.Posture
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.ForcedSize import androidx.compose.ui.test.ForcedSize
import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertIsDisplayed
@ -28,6 +30,7 @@ import androidx.compose.ui.test.performClick
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso
import androidx.window.core.layout.WindowSizeClass
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
@ -65,13 +68,21 @@ class InterestsListDetailScreenTest {
private val placeholderText by composeTestRule.stringResource(FeatureTopicR.string.feature_topic_select_an_interest) private val placeholderText by composeTestRule.stringResource(FeatureTopicR.string.feature_topic_select_an_interest)
private val listPaneTag = "interests:topics" private val listPaneTag = "interests:topics"
// Overrides for device sizes.
private val expandedWidth = DeviceConfigurationOverride.ForcedSize(DpSize(1200.dp, 840.dp))
private val compactWidth = DeviceConfigurationOverride.ForcedSize(DpSize(412.dp, 915.dp))
private val Topic.testTag private val Topic.testTag
get() = "topic:${this.id}" get() = "topic:${this.id}"
// Overrides for device sizes.
private enum class TestDeviceConfig(widthDp: Float, heightDp: Float) {
Compact(412f, 915f),
Expanded(1200f, 840f);
val sizeOverride = DeviceConfigurationOverride.ForcedSize(DpSize(widthDp.dp, heightDp.dp))
val adaptiveInfo = WindowAdaptiveInfo(
windowSizeClass = WindowSizeClass.compute(widthDp, heightDp),
windowPosture = Posture()
)
}
@Before @Before
fun setup() { fun setup() {
hiltRule.inject() hiltRule.inject()
@ -82,9 +93,11 @@ class InterestsListDetailScreenTest {
fun expandedWidth_initialState_showsTwoPanesWithPlaceholder() { fun expandedWidth_initialState_showsTwoPanesWithPlaceholder() {
composeTestRule.apply { composeTestRule.apply {
setContent { setContent {
DeviceConfigurationOverride(override = expandedWidth) { with(TestDeviceConfig.Expanded) {
DeviceConfigurationOverride(override = sizeOverride) {
NiaTheme { NiaTheme {
InterestsListDetailScreen() InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo)
}
} }
} }
} }
@ -98,9 +111,11 @@ class InterestsListDetailScreenTest {
fun notExpandedWidth_initialState_showsListPane() { fun notExpandedWidth_initialState_showsListPane() {
composeTestRule.apply { composeTestRule.apply {
setContent { setContent {
DeviceConfigurationOverride(override = compactWidth) { with(TestDeviceConfig.Compact) {
DeviceConfigurationOverride(override = sizeOverride) {
NiaTheme { NiaTheme {
InterestsListDetailScreen() InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo)
}
} }
} }
} }
@ -114,9 +129,11 @@ class InterestsListDetailScreenTest {
fun expandedWidth_topicSelected_updatesDetailPane() { fun expandedWidth_topicSelected_updatesDetailPane() {
composeTestRule.apply { composeTestRule.apply {
setContent { setContent {
DeviceConfigurationOverride(override = expandedWidth) { with(TestDeviceConfig.Expanded) {
DeviceConfigurationOverride(override = sizeOverride) {
NiaTheme { NiaTheme {
InterestsListDetailScreen() InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo)
}
} }
} }
} }
@ -136,9 +153,11 @@ class InterestsListDetailScreenTest {
fun notExpandedWidth_topicSelected_showsTopicDetailPane() { fun notExpandedWidth_topicSelected_showsTopicDetailPane() {
composeTestRule.apply { composeTestRule.apply {
setContent { setContent {
DeviceConfigurationOverride(override = compactWidth) { with(TestDeviceConfig.Compact) {
DeviceConfigurationOverride(override = sizeOverride) {
NiaTheme { NiaTheme {
InterestsListDetailScreen() InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo)
}
} }
} }
} }
@ -159,14 +178,16 @@ class InterestsListDetailScreenTest {
var unhandledBackPress = false var unhandledBackPress = false
composeTestRule.apply { composeTestRule.apply {
setContent { setContent {
DeviceConfigurationOverride(override = expandedWidth) { with(TestDeviceConfig.Expanded) {
DeviceConfigurationOverride(override = sizeOverride) {
NiaTheme { NiaTheme {
// Back press should not be handled by the two pane layout, and thus // Back press should not be handled by the two pane layout, and thus
// "fall through" to this BackHandler. // "fall through" to this BackHandler.
BackHandler { BackHandler {
unhandledBackPress = true unhandledBackPress = true
} }
InterestsListDetailScreen() InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo)
}
} }
} }
} }
@ -186,9 +207,11 @@ class InterestsListDetailScreenTest {
fun notExpandedWidth_backPressFromTopicDetail_showsListPane() { fun notExpandedWidth_backPressFromTopicDetail_showsListPane() {
composeTestRule.apply { composeTestRule.apply {
setContent { setContent {
DeviceConfigurationOverride(override = compactWidth) { with(TestDeviceConfig.Compact) {
DeviceConfigurationOverride(override = sizeOverride) {
NiaTheme { NiaTheme {
InterestsListDetailScreen() InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo)
}
} }
} }
} }
@ -197,7 +220,6 @@ class InterestsListDetailScreenTest {
topicsRepository.getTopics().first().first() topicsRepository.getTopics().first().first()
} }
onNodeWithText(firstTopic.name).performClick() onNodeWithText(firstTopic.name).performClick()
composeTestRule.waitForIdle()
Espresso.pressBack() Espresso.pressBack()

@ -18,11 +18,14 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.adaptive.layout.AnimatedPane import androidx.compose.material3.adaptive.layout.AnimatedPane
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -71,11 +74,13 @@ fun NavGraphBuilder.interestsListDetailScreen() {
@Composable @Composable
internal fun InterestsListDetailScreen( internal fun InterestsListDetailScreen(
viewModel: Interests2PaneViewModel = hiltViewModel(), viewModel: Interests2PaneViewModel = hiltViewModel(),
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(),
) { ) {
val selectedTopicId by viewModel.selectedTopicId.collectAsStateWithLifecycle() val selectedTopicId by viewModel.selectedTopicId.collectAsStateWithLifecycle()
InterestsListDetailScreen( InterestsListDetailScreen(
selectedTopicId = selectedTopicId, selectedTopicId = selectedTopicId,
onTopicClick = viewModel::onTopicClick, onTopicClick = viewModel::onTopicClick,
windowAdaptiveInfo = windowAdaptiveInfo,
) )
} }
@ -84,8 +89,10 @@ internal fun InterestsListDetailScreen(
internal fun InterestsListDetailScreen( internal fun InterestsListDetailScreen(
selectedTopicId: String?, selectedTopicId: String?,
onTopicClick: (String) -> Unit, onTopicClick: (String) -> Unit,
windowAdaptiveInfo: WindowAdaptiveInfo,
) { ) {
val listDetailNavigator = rememberListDetailPaneScaffoldNavigator( val listDetailNavigator = rememberListDetailPaneScaffoldNavigator(
scaffoldDirective = calculatePaneScaffoldDirective(windowAdaptiveInfo),
initialDestinationHistory = listOfNotNull( initialDestinationHistory = listOfNotNull(
ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.List), ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.List),
ThreePaneScaffoldDestinationItem<Nothing>(ListDetailPaneScaffoldRole.Detail).takeIf { ThreePaneScaffoldDestinationItem<Nothing>(ListDetailPaneScaffoldRole.Detail).takeIf {

Loading…
Cancel
Save