From 500836d806883c3c60d89c987e6fb94a25dae8d1 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 27 Jun 2024 15:35:29 -0700 Subject: [PATCH] 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 --- .../InterestsListDetailScreenTest.kt | 76 ++++++++++++------- .../InterestsListDetailScreen.kt | 7 ++ 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreenTest.kt b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreenTest.kt index c0ac2e6a7..2c3c8b83c 100644 --- a/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreenTest.kt +++ b/app/src/androidTest/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreenTest.kt @@ -17,6 +17,8 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane 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.ForcedSize 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.dp 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.designsystem.theme.NiaTheme 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 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 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 fun setup() { hiltRule.inject() @@ -82,9 +93,11 @@ class InterestsListDetailScreenTest { fun expandedWidth_initialState_showsTwoPanesWithPlaceholder() { composeTestRule.apply { setContent { - DeviceConfigurationOverride(override = expandedWidth) { - NiaTheme { - InterestsListDetailScreen() + with(TestDeviceConfig.Expanded) { + DeviceConfigurationOverride(override = sizeOverride) { + NiaTheme { + InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo) + } } } } @@ -98,9 +111,11 @@ class InterestsListDetailScreenTest { fun notExpandedWidth_initialState_showsListPane() { composeTestRule.apply { setContent { - DeviceConfigurationOverride(override = compactWidth) { - NiaTheme { - InterestsListDetailScreen() + with(TestDeviceConfig.Compact) { + DeviceConfigurationOverride(override = sizeOverride) { + NiaTheme { + InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo) + } } } } @@ -114,9 +129,11 @@ class InterestsListDetailScreenTest { fun expandedWidth_topicSelected_updatesDetailPane() { composeTestRule.apply { setContent { - DeviceConfigurationOverride(override = expandedWidth) { - NiaTheme { - InterestsListDetailScreen() + with(TestDeviceConfig.Expanded) { + DeviceConfigurationOverride(override = sizeOverride) { + NiaTheme { + InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo) + } } } } @@ -136,9 +153,11 @@ class InterestsListDetailScreenTest { fun notExpandedWidth_topicSelected_showsTopicDetailPane() { composeTestRule.apply { setContent { - DeviceConfigurationOverride(override = compactWidth) { - NiaTheme { - InterestsListDetailScreen() + with(TestDeviceConfig.Compact) { + DeviceConfigurationOverride(override = sizeOverride) { + NiaTheme { + InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo) + } } } } @@ -159,14 +178,16 @@ class InterestsListDetailScreenTest { var unhandledBackPress = false composeTestRule.apply { setContent { - DeviceConfigurationOverride(override = expandedWidth) { - NiaTheme { - // Back press should not be handled by the two pane layout, and thus - // "fall through" to this BackHandler. - BackHandler { - unhandledBackPress = true + with(TestDeviceConfig.Expanded) { + DeviceConfigurationOverride(override = sizeOverride) { + NiaTheme { + // Back press should not be handled by the two pane layout, and thus + // "fall through" to this BackHandler. + BackHandler { + unhandledBackPress = true + } + InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo) } - InterestsListDetailScreen() } } } @@ -186,9 +207,11 @@ class InterestsListDetailScreenTest { fun notExpandedWidth_backPressFromTopicDetail_showsListPane() { composeTestRule.apply { setContent { - DeviceConfigurationOverride(override = compactWidth) { - NiaTheme { - InterestsListDetailScreen() + with(TestDeviceConfig.Compact) { + DeviceConfigurationOverride(override = sizeOverride) { + NiaTheme { + InterestsListDetailScreen(windowAdaptiveInfo = adaptiveInfo) + } } } } @@ -197,7 +220,6 @@ class InterestsListDetailScreenTest { topicsRepository.getTopics().first().first() } onNodeWithText(firstTopic.name).performClick() - composeTestRule.waitForIdle() Espresso.pressBack() diff --git a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt index ada4e49d1..919cb44f2 100644 --- a/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt +++ b/app/src/main/kotlin/com/google/samples/apps/nowinandroid/ui/interests2pane/InterestsListDetailScreen.kt @@ -18,11 +18,14 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane import androidx.activity.compose.BackHandler 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.ListDetailPaneScaffold import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.layout.PaneAdaptedValue 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.rememberListDetailPaneScaffoldNavigator import androidx.compose.runtime.Composable @@ -71,11 +74,13 @@ fun NavGraphBuilder.interestsListDetailScreen() { @Composable internal fun InterestsListDetailScreen( viewModel: Interests2PaneViewModel = hiltViewModel(), + windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), ) { val selectedTopicId by viewModel.selectedTopicId.collectAsStateWithLifecycle() InterestsListDetailScreen( selectedTopicId = selectedTopicId, onTopicClick = viewModel::onTopicClick, + windowAdaptiveInfo = windowAdaptiveInfo, ) } @@ -84,8 +89,10 @@ internal fun InterestsListDetailScreen( internal fun InterestsListDetailScreen( selectedTopicId: String?, onTopicClick: (String) -> Unit, + windowAdaptiveInfo: WindowAdaptiveInfo, ) { val listDetailNavigator = rememberListDetailPaneScaffoldNavigator( + scaffoldDirective = calculatePaneScaffoldDirective(windowAdaptiveInfo), initialDestinationHistory = listOfNotNull( ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.List), ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.Detail).takeIf {