From 69d3a24295435a10968a1d5143aa726aec23d68f Mon Sep 17 00:00:00 2001 From: Alexander Maryanovsky Date: Wed, 31 Jan 2024 14:43:20 +0200 Subject: [PATCH] Add common test samples to widgets-gallery (#4202) --- examples/widgets-gallery/gradle.properties | 3 +- .../widgets-gallery/shared/build.gradle.kts | 49 +++-- .../drawable}/ic_instagram.xml | 0 .../drawable}/ic_send.xml | 0 .../drawable}/ic_twitter.xml | 0 .../drawable}/p1.jpeg | Bin .../drawable}/p2.jpeg | Bin .../drawable}/p3.jpeg | Bin .../drawable}/p6.jpeg | Bin .../values/strings.xml | 0 .../compose/demo/widgets/platform/Res.kt | 9 - .../compose/demo/widgets/ui/MainView.kt | 6 + .../compose/demo/widgets/ui/WidgetView.kt | 3 +- .../compose/demo/widgets/ui/WidgetsType.kt | 5 +- .../demo/widgets/ui/screens/AppBars.kt | 37 ++-- .../demo/widgets/ui/screens/Buttons.kt | 4 +- .../compose/demo/widgets/ui/screens/Chips.kt | 78 ++++---- .../demo/widgets/ui/screens/Loaders.kt | 33 ++-- .../demo/widgets/ui/screens/SnackBars.kt | 48 ++--- .../demo/widgets/ui/screens/TextInputs.kt | 123 ++++++------- .../compose/demo/widgets/ui/screens/Texts.kt | 5 +- .../demo/widgets/ui/screens/Toggles.kt | 4 +- .../demo/widgets/ui/screens/UICards.kt | 167 ++++++++++-------- .../demo/widgets/ui/utils/ResizablePanel.kt | 9 +- .../src/commonTest/kotlin/ExampleTest.kt | 34 ++++ .../src/commonTest/kotlin/WidgetsPanelTest.kt | 28 +++ 26 files changed, 386 insertions(+), 259 deletions(-) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/ic_instagram.xml (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/ic_send.xml (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/ic_twitter.xml (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/p1.jpeg (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/p2.jpeg (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/p3.jpeg (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes/images => composeResources/drawable}/p6.jpeg (100%) rename examples/widgets-gallery/shared/src/commonMain/{resources/composeRes => composeResources}/values/strings.xml (100%) delete mode 100644 examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Res.kt create mode 100644 examples/widgets-gallery/shared/src/commonTest/kotlin/ExampleTest.kt create mode 100644 examples/widgets-gallery/shared/src/commonTest/kotlin/WidgetsPanelTest.kt diff --git a/examples/widgets-gallery/gradle.properties b/examples/widgets-gallery/gradle.properties index 39193936c1..f8f6769bad 100644 --- a/examples/widgets-gallery/gradle.properties +++ b/examples/widgets-gallery/gradle.properties @@ -10,4 +10,5 @@ kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.native.binary.memoryModel=experimental kotlin.version=1.9.21 agp.version=8.0.2 -compose.version=1.5.11 +# Replace this with release version when it comes out +compose.version=1.6.0-dev1397 diff --git a/examples/widgets-gallery/shared/build.gradle.kts b/examples/widgets-gallery/shared/build.gradle.kts index 26fd7599d3..fadb5ec3a7 100644 --- a/examples/widgets-gallery/shared/build.gradle.kts +++ b/examples/widgets-gallery/shared/build.gradle.kts @@ -1,4 +1,5 @@ -@file:Suppress("OPT_IN_IS_NOT_ENABLED") +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree plugins { kotlin("multiplatform") @@ -9,7 +10,19 @@ plugins { version = "1.0-SNAPSHOT" kotlin { - androidTarget() + androidTarget { + @OptIn(ExperimentalKotlinGradlePluginApi::class) + instrumentedTestVariant { + sourceSetTree.set(KotlinSourceSetTree.test) + + dependencies { + // Remove the dependency on ui-test-junit4-android when 1.7.0 is released, + // as the needed classes in will have moved to ui-test + implementation("androidx.compose.ui:ui-test-junit4-android:1.6.0") + debugImplementation("androidx.compose.ui:ui-test-manifest") + } + } + } jvm("desktop") @@ -32,33 +45,34 @@ kotlin { implementation(compose.material) implementation(compose.materialIconsExtended) @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) - implementation("org.jetbrains.compose.components:components-resources:1.6.0-dev1306") + implementation("org.jetbrains.compose.components:components-resources:${project.property("compose.version")}") } } val androidMain by getting { dependencies { - api("androidx.activity:activity-compose:1.7.2") + api("androidx.activity:activity-compose:1.8.2") api("androidx.appcompat:appcompat:1.6.1") - api("androidx.core:core-ktx:1.10.1") + api("androidx.core:core-ktx:1.12.0") } } - val iosMain by creating { - dependsOn(commonMain) - } - val iosX64Main by getting { - dependsOn(iosMain) - } - val iosArm64Main by getting { - dependsOn(iosMain) - } - val iosSimulatorArm64Main by getting { - dependsOn(iosMain) - } val desktopMain by getting { dependencies { implementation(compose.desktop.common) } } + val desktopTest by getting { + dependencies { + implementation(compose.desktop.currentOs) + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + + @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + implementation(compose.uiTest) + } + } } } @@ -71,6 +85,7 @@ android { defaultConfig { minSdk = 26 + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/ic_instagram.xml b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/ic_instagram.xml similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/ic_instagram.xml rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/ic_instagram.xml diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/ic_send.xml b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/ic_send.xml similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/ic_send.xml rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/ic_send.xml diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/ic_twitter.xml b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/ic_twitter.xml similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/ic_twitter.xml rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/ic_twitter.xml diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p1.jpeg b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p1.jpeg similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p1.jpeg rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p1.jpeg diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p2.jpeg b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p2.jpeg similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p2.jpeg rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p2.jpeg diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p3.jpeg b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p3.jpeg similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p3.jpeg rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p3.jpeg diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p6.jpeg b/examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p6.jpeg similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/images/p6.jpeg rename to examples/widgets-gallery/shared/src/commonMain/composeResources/drawable/p6.jpeg diff --git a/examples/widgets-gallery/shared/src/commonMain/resources/composeRes/values/strings.xml b/examples/widgets-gallery/shared/src/commonMain/composeResources/values/strings.xml similarity index 100% rename from examples/widgets-gallery/shared/src/commonMain/resources/composeRes/values/strings.xml rename to examples/widgets-gallery/shared/src/commonMain/composeResources/values/strings.xml diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Res.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Res.kt deleted file mode 100644 index cfa63a8965..0000000000 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/platform/Res.kt +++ /dev/null @@ -1,9 +0,0 @@ -package org.jetbrains.compose.demo.widgets.platform - -object Res { - object strings { - val spotify_nav_home = "Home" - val spotify_nav_search = "Search" - val spotify_nav_library = "Your Library" - } -} \ No newline at end of file diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/MainView.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/MainView.kt index a398a61b4c..e008688db9 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/MainView.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/MainView.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.testTag import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.SemanticsProperties import androidx.compose.ui.semantics.semantics @@ -115,6 +116,10 @@ private fun WidgetsListView(widgetsTypeState: MutableState) { } +val WidgetsType.listItemTestTag: String + get() = "${testTag}_list_item" + + @Composable private fun WidgetsListItemViewImpl( widgetsType: WidgetsType, @@ -133,6 +138,7 @@ private fun WidgetsListItemViewImpl( } .height(height) .padding(start = 16.dp) + .testTag(widgetsType.listItemTestTag) ) { val inFocusInteractionSource = remember { MutableInteractionSource() } val inFocus by inFocusInteractionSource.collectIsHoveredAsState() diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetView.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetView.kt index 07468259f5..757552d48b 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetView.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetView.kt @@ -2,7 +2,6 @@ package org.jetbrains.compose.demo.widgets.ui import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -19,7 +18,7 @@ fun WidgetsView( modifier: Modifier ) { ClearFocusBox { - Column(modifier = modifier.verticalScroll(state = rememberScrollState())) { + Box(modifier = modifier.verticalScroll(state = rememberScrollState())) { @Suppress("UNUSED_VARIABLE") val exhaustive = when (widgetsTypeState.value) { WidgetsType.APP_BARS -> AppBars() diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetsType.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetsType.kt index 80b03c7655..59d1d1e60d 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetsType.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/WidgetsType.kt @@ -24,9 +24,12 @@ enum class WidgetsType(private val customTitle: String? = null) { val title: String get() = customTitle ?: readableName + val testTag: String + get() = name.lowercase() + companion object { val sortedValues: List by lazy { - values().sortedBy { it.name } + entries.sortedBy { it.name } } } } \ No newline at end of file diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/AppBars.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/AppBars.kt index 4990285078..350b0cb345 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/AppBars.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/AppBars.kt @@ -5,7 +5,8 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.* import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.outlined.ReadMore import androidx.compose.material.icons.filled.MoreHoriz import androidx.compose.material.icons.filled.StarBorder import androidx.compose.material.icons.outlined.* @@ -14,20 +15,24 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp -import org.jetbrains.compose.demo.widgets.platform.Res import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.demo.widgets.theme.twitterColor +import org.jetbrains.compose.demo.widgets.ui.WidgetsType import org.jetbrains.compose.demo.widgets.ui.utils.SubtitleText import org.jetbrains.compose.demo.widgets.ui.utils.TitleText import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.ImageResource +import org.jetbrains.compose.resources.stringResource +import widgets_gallery.shared.generated.resources.Res @Composable fun AppBars() { - TopAppBarsDemo() - BottomAppBarDemo() - NavigationBarDemo() + Column(Modifier.testTag(WidgetsType.APP_BARS.testTag)) { + TopAppBarsDemo() + BottomAppBarDemo() + NavigationBarDemo() + } } @OptIn(ExperimentalResourceApi::class) @@ -40,7 +45,7 @@ private fun TopAppBarsDemo() { elevation = 8.dp, navigationIcon = { IconButton(onClick = {}) { - Icon(Icons.Default.ArrowBack, contentDescription = "ArrowBack") + Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "ArrowBack") } } ) @@ -54,12 +59,12 @@ private fun TopAppBarsDemo() { elevation = 8.dp, navigationIcon = { IconButton(onClick = {}) { - Icon(painterResource(ImageResource("composeRes/images/ic_instagram.xml")), contentDescription = "Instagram") + Icon(painterResource(Res.drawable.ic_instagram), contentDescription = "Instagram") } }, actions = { IconButton(onClick = {}) { - Icon(painterResource(ImageResource("composeRes/images/ic_send.xml")), contentDescription = "Send") + Icon(painterResource(Res.drawable.ic_send), contentDescription = "Send") } } ) @@ -69,7 +74,7 @@ private fun TopAppBarsDemo() { TopAppBar( title = { Icon( - painterResource(ImageResource("composeRes/images/ic_twitter.xml")), + painterResource(Res.drawable.ic_twitter), contentDescription = "Twitter", tint = twitterColor, modifier = Modifier.fillMaxWidth() @@ -80,7 +85,7 @@ private fun TopAppBarsDemo() { elevation = 8.dp, navigationIcon = { Image( - painterResource(ImageResource("composeRes/images/p6.jpeg")), + painterResource(Res.drawable.p6), contentDescription = "", modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp) .requiredSize(32.dp).clip(CircleShape) @@ -100,7 +105,7 @@ private fun TopAppBarsDemo() { @Composable private fun BottomAppBarDemo() { Spacer(modifier = Modifier.height(16.dp)) - SubtitleText("Bottom app bars: Note bottom app bar support FAB cutouts when used with scafolds see demoUI crypto app") + SubtitleText("Bottom app bars: Note bottom app bar support FAB cutouts when used with scaffolds see demoUI crypto app") BottomAppBar( cutoutShape = CircleShape @@ -123,19 +128,19 @@ private fun NavigationBarDemo() { icon = { Icon(Icons.Outlined.Home, contentDescription = "Home") }, selected = navItemState.value == NavType.HOME, onClick = { navItemState.value = NavType.HOME }, - label = { Text(text = Res.strings.spotify_nav_home) }, + label = { Text(text = stringResource(Res.string.spotify_nav_home)) }, ) BottomNavigationItem( icon = { Icon(Icons.Outlined.Search, contentDescription = "Search") }, selected = navItemState.value == NavType.SEARCH, onClick = { navItemState.value = NavType.SEARCH }, - label = { Text(text = Res.strings.spotify_nav_search) } + label = { Text(text = stringResource(Res.string.spotify_nav_search)) } ) BottomNavigationItem( icon = { Icon(Icons.Outlined.LibraryMusic, contentDescription = "LibraryMusic") }, selected = navItemState.value == NavType.LIBRARY, onClick = { navItemState.value = NavType.LIBRARY }, - label = { Text(text = Res.strings.spotify_nav_library) } + label = { Text(text = stringResource(Res.string.spotify_nav_library)) } ) } @@ -143,7 +148,7 @@ private fun NavigationBarDemo() { BottomNavigation { BottomNavigationItem( - icon = { Icon(Icons.Outlined.ReadMore, contentDescription = "ReadMore") }, + icon = { Icon(Icons.AutoMirrored.Outlined.ReadMore, contentDescription = "ReadMore") }, selected = navItemState.value == NavType.HOME, onClick = { navItemState.value = NavType.HOME }, ) diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Buttons.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Buttons.kt index a7e5e295b5..7b650d0eee 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Buttons.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Buttons.kt @@ -14,14 +14,16 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp import org.jetbrains.compose.demo.widgets.theme.purple import org.jetbrains.compose.demo.widgets.theme.purple200 import org.jetbrains.compose.demo.widgets.theme.typography +import org.jetbrains.compose.demo.widgets.ui.WidgetsType @Composable fun Buttons() { - Column { + Column(Modifier.testTag(WidgetsType.BUTTONS.testTag)) { Button(onClick = {}, modifier = Modifier.padding(8.dp)) { Text(text = "Main Button") } diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Chips.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Chips.kt index fa42888f9a..ce37098f20 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Chips.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Chips.kt @@ -13,44 +13,62 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import org.jetbrains.compose.demo.widgets.ui.WidgetsType import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.demo.widgets.ui.utils.SubtitleText +import org.jetbrains.compose.resources.DrawableResource import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.ImageResource +import widgets_gallery.shared.generated.resources.Res +@OptIn(ExperimentalResourceApi::class) @Composable fun Chips() { - // There is no in-built chips but you can make yours like below - SubtitleText(subtitle = "Custom chips with surface") - Column(modifier = Modifier.padding(8.dp)) { - YoutubeChip(selected = true, text = "Chip", modifier = Modifier.padding(horizontal = 8.dp)) - Spacer(modifier = Modifier.padding(8.dp)) - YoutubeChip( - selected = false, - text = "Inactive", - modifier = Modifier.padding(horizontal = 8.dp) - ) - Spacer(modifier = Modifier.padding(8.dp)) - CustomImageChip(text = "custom", imageId = ImageResource("composeRes/images/p2.jpeg"), selected = true) - Spacer(modifier = Modifier.padding(8.dp)) - CustomImageChip(text = "custom2", imageId = ImageResource("composeRes/images/p6.jpeg"), selected = false) - } - SubtitleText(subtitle = "Buttons with circle clipping.") - Column(modifier = Modifier.padding(8.dp)) { - Button( - onClick = {}, - modifier = Modifier.padding(8.dp).clip(CircleShape) - ) { - Text(text = "Chip button") + Column(Modifier.testTag(WidgetsType.CHIPS.testTag)) { + // There is no in-built chips but you can make yours like below + SubtitleText(subtitle = "Custom chips with surface") + Column(modifier = Modifier.padding(8.dp)) { + YoutubeChip( + selected = true, + text = "Chip", + modifier = Modifier.padding(horizontal = 8.dp) + ) + Spacer(modifier = Modifier.padding(8.dp)) + YoutubeChip( + selected = false, + text = "Inactive", + modifier = Modifier.padding(horizontal = 8.dp) + ) + Spacer(modifier = Modifier.padding(8.dp)) + CustomImageChip( + text = "custom", + imageId = Res.drawable.p2, + selected = true + ) + Spacer(modifier = Modifier.padding(8.dp)) + CustomImageChip( + text = "custom2", + imageId = Res.drawable.p6, + selected = false + ) } - Button( - onClick = {}, - enabled = false, - modifier = Modifier.padding(8.dp).clip(CircleShape) - ) { - Text(text = "Disabled chip") + SubtitleText(subtitle = "Buttons with circle clipping.") + Column(modifier = Modifier.padding(8.dp)) { + Button( + onClick = {}, + modifier = Modifier.padding(8.dp).clip(CircleShape) + ) { + Text(text = "Chip button") + } + Button( + onClick = {}, + enabled = false, + modifier = Modifier.padding(8.dp).clip(CircleShape) + ) { + Text(text = "Disabled chip") + } } } } @@ -62,7 +80,7 @@ fun Chips() { @Composable private fun CustomImageChip( text: String, - imageId: ImageResource, + imageId: DrawableResource, selected: Boolean, modifier: Modifier = Modifier ) { diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Loaders.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Loaders.kt index df19865d62..97a6ce4357 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Loaders.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Loaders.kt @@ -1,41 +1,34 @@ package org.jetbrains.compose.demo.widgets.ui.screens +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp +import org.jetbrains.compose.demo.widgets.ui.WidgetsType @Composable fun Loaders() { - AlignedColumn { + Column( + modifier = Modifier + .padding(16.dp) + .testTag(WidgetsType.LOADERS.testTag), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { CircularProgressIndicator() - } - AlignedColumn { CircularProgressIndicator(strokeWidth = 8.dp) - } - AlignedColumn { LinearProgressIndicator() - } - AlignedColumn { - LinearProgressIndicator() - Text(text = "Loading with text...", modifier = Modifier.padding(8.dp)) + Column { + LinearProgressIndicator() + Text(text = "Loading with text...", modifier = Modifier.padding(8.dp)) + } } } -@Composable -private fun AlignedColumn(content: @Composable () -> Unit) { - Column( - modifier = Modifier.fillMaxWidth().padding(16.dp) - ) { - content() - } -} \ No newline at end of file diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/SnackBars.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/SnackBars.kt index 78946984a7..ad3af37ea3 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/SnackBars.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/SnackBars.kt @@ -1,38 +1,46 @@ package org.jetbrains.compose.demo.widgets.ui.screens +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material.Snackbar import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp -import org.jetbrains.compose.demo.widgets.theme.typography +import org.jetbrains.compose.demo.widgets.ui.WidgetsType @Composable fun SnackBars() { - Snackbar(modifier = Modifier.padding(4.dp)) { - Text(text = "This is a basic snackbar") - } - Snackbar( - modifier = Modifier.padding(4.dp), - action = { - TextButton(onClick = {}) { - Text(text = "Remove") + Column( + modifier = Modifier + .padding(4.dp) + .testTag(WidgetsType.SNACK_BARS.testTag), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Snackbar { + Text(text = "This is a basic snackbar") + } + Snackbar( + action = { + TextButton(onClick = {}) { + Text(text = "Remove") + } } + ) { + Text(text = "This is a basic snackbar with action item") } - ) { - Text(text = "This is a basic Snackbar with action item") - } - Snackbar( - modifier = Modifier.padding(4.dp), - actionOnNewLine = true, - action = { - TextButton(onClick = {}) { - Text(text = "Remove") + Snackbar( + actionOnNewLine = true, + action = { + TextButton(onClick = {}) { + Text(text = "Remove") + } } + ) { + Text(text = "Snackbar with action item below text") } - ) { - Text(text = "Snackbar with action item below text") } } diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/TextInputs.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/TextInputs.kt index b4cc78bd8b..1df77caf0f 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/TextInputs.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/TextInputs.kt @@ -1,6 +1,7 @@ package org.jetbrains.compose.demo.widgets.ui.screens +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardOptions @@ -13,80 +14,84 @@ import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Email import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import org.jetbrains.compose.demo.widgets.ui.WidgetsType @Composable fun TextInputs() { - var text by remember { mutableStateOf(TextFieldValue("")) } + Column(Modifier.testTag(WidgetsType.TEXT_INPUTS.testTag)) { + var text by remember { mutableStateOf(TextFieldValue("")) } - // TODO Explore CoreTextField + // TODO Explore CoreTextField // CoreTextField( // value = text, // onValueChange = { newValue -> text = newValue }, // modifier = Modifier.padding(8.dp).preferredSize(0.dp), // cursorColor = Color.Magenta // ) - TextField( - value = text, - onValueChange = { newValue -> text = newValue }, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - singleLine = true, - label = { Text("label") }, - placeholder = { Text("placeholder") }, - ) + TextField( + value = text, + onValueChange = { newValue -> text = newValue }, + modifier = Modifier.padding(8.dp).fillMaxWidth(), + singleLine = true, + label = { Text("label") }, + placeholder = { Text("placeholder") }, + ) - OutlinedTextField( - value = text, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - singleLine = true, - label = { Text(text = "Password") }, - placeholder = { Text(text = "12334444") }, - visualTransformation = PasswordVisualTransformation(), - onValueChange = { - text = it - }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password) - ) + OutlinedTextField( + value = text, + modifier = Modifier.padding(8.dp).fillMaxWidth(), + singleLine = true, + label = { Text(text = "Password") }, + placeholder = { Text(text = "12334444") }, + visualTransformation = PasswordVisualTransformation(), + onValueChange = { + text = it + }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password) + ) - OutlinedTextField( - value = text, - leadingIcon = { Icon(Icons.Default.Email, contentDescription = "Email") }, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - singleLine = true, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), - label = { Text(text = "Email address") }, - placeholder = { Text(text = "Your email") }, - onValueChange = { - text = it - } - ) - OutlinedTextField( - value = text, - leadingIcon = { Icon(Icons.Default.Email, contentDescription = "Email") }, - trailingIcon = { Icon(Icons.Default.Edit, contentDescription = "Edit") }, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - singleLine = true, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), - label = { Text(text = "Email address") }, - placeholder = { Text(text = "Your email") }, - onValueChange = { - text = it - } - ) + OutlinedTextField( + value = text, + leadingIcon = { Icon(Icons.Default.Email, contentDescription = "Email") }, + modifier = Modifier.padding(8.dp).fillMaxWidth(), + singleLine = true, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), + label = { Text(text = "Email address") }, + placeholder = { Text(text = "Your email") }, + onValueChange = { + text = it + } + ) + OutlinedTextField( + value = text, + leadingIcon = { Icon(Icons.Default.Email, contentDescription = "Email") }, + trailingIcon = { Icon(Icons.Default.Edit, contentDescription = "Edit") }, + modifier = Modifier.padding(8.dp).fillMaxWidth(), + singleLine = true, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), + label = { Text(text = "Email address") }, + placeholder = { Text(text = "Your email") }, + onValueChange = { + text = it + } + ) - var numberText by remember { mutableStateOf(TextFieldValue("")) } - OutlinedTextField( - value = numberText, - modifier = Modifier.padding(8.dp).fillMaxWidth(), - singleLine = true, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), - label = { Text(text = "Phone number") }, - placeholder = { Text(text = "88888888") }, - onValueChange = { - numberText = it - } - ) + var numberText by remember { mutableStateOf(TextFieldValue("")) } + OutlinedTextField( + value = numberText, + modifier = Modifier.padding(8.dp).fillMaxWidth(), + singleLine = true, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + label = { Text(text = "Phone number") }, + placeholder = { Text(text = "88888888") }, + onValueChange = { + numberText = it + } + ) + } } diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Texts.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Texts.kt index c14f8f9545..d22aca0ba8 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Texts.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Texts.kt @@ -1,21 +1,22 @@ package org.jetbrains.compose.demo.widgets.ui.screens import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import org.jetbrains.compose.demo.widgets.theme.typography +import org.jetbrains.compose.demo.widgets.ui.WidgetsType import org.jetbrains.compose.demo.widgets.ui.utils.SubtitleText @Composable fun TextViews() { - Column { + Column(Modifier.testTag(WidgetsType.TEXT_VIEWS.testTag)) { val textModifier = Modifier.padding(horizontal = 8.dp) SubtitleText(subtitle = "Font weights") diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Toggles.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Toggles.kt index ce3ac76ee2..8ed12c8497 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Toggles.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/Toggles.kt @@ -9,11 +9,13 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp +import org.jetbrains.compose.demo.widgets.ui.WidgetsType @Composable fun Toggles() { - Column { + Column(Modifier.testTag(WidgetsType.TOGGLES.testTag)) { var checked by remember { mutableStateOf(true) } Checkbox( checked = checked, diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/UICards.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/UICards.kt index 08223f5e6e..b89579ae13 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/UICards.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/screens/UICards.kt @@ -9,96 +9,109 @@ import androidx.compose.material.icons.filled.ShoppingCart import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp import org.jetbrains.compose.demo.widgets.data.DemoDataProvider import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.demo.widgets.theme.typography +import org.jetbrains.compose.demo.widgets.ui.WidgetsType import org.jetbrains.compose.resources.ExperimentalResourceApi -import org.jetbrains.compose.resources.ImageResource +import widgets_gallery.shared.generated.resources.Res @OptIn(ExperimentalMaterialApi::class, ExperimentalResourceApi::class) @Composable fun UICards() { - val item = remember { DemoDataProvider.item } + Column(Modifier.testTag(WidgetsType.UI_CARDS.testTag)) { + val item = remember { DemoDataProvider.item } - Text( - text = "Inbuilt box as container for any Clipping/Alignment controls", - style = typography.subtitle1, - modifier = Modifier.padding(8.dp) - ) - Card( - modifier = Modifier.padding(8.dp).fillMaxWidth(), - backgroundColor = MaterialTheme.colors.primary, - shape = RoundedCornerShape(topStart = 16.dp, bottomEnd = 16.dp) - ) { - Column { - Text( - text = item.title, - modifier = Modifier.padding(8.dp), - color = MaterialTheme.colors.onPrimary - ) - Text( - text = item.subtitle, - modifier = Modifier.padding(8.dp), - color = MaterialTheme.colors.onPrimary - ) + Text( + text = "Inbuilt box as container for any Clipping/Alignment controls", + style = typography.subtitle1, + modifier = Modifier.padding(8.dp) + ) + Card( + modifier = Modifier.padding(8.dp).fillMaxWidth(), + backgroundColor = MaterialTheme.colors.primary, + shape = RoundedCornerShape(topStart = 16.dp, bottomEnd = 16.dp) + ) { + Column { + Text( + text = item.title, + modifier = Modifier.padding(8.dp), + color = MaterialTheme.colors.onPrimary + ) + Text( + text = item.subtitle, + modifier = Modifier.padding(8.dp), + color = MaterialTheme.colors.onPrimary + ) + } } - } - Divider() + Divider() - Text(text = "Inbuilt Card", style = typography.subtitle1, modifier = Modifier.padding(8.dp)) - Card( - modifier = Modifier.padding(16.dp).fillMaxWidth(), - shape = RoundedCornerShape(4.dp), - elevation = 4.dp - ) { - Row { - Image( - painterResource(ImageResource("composeRes/images/p3.jpeg")), - contentDescription = null, - modifier = Modifier.requiredSize(60.dp) - ) - Text(text = item.title, modifier = Modifier.padding(16.dp)) + Text(text = "Inbuilt Card", style = typography.subtitle1, modifier = Modifier.padding(8.dp)) + Card( + modifier = Modifier.padding(16.dp).fillMaxWidth(), + shape = RoundedCornerShape(4.dp), + elevation = 4.dp + ) { + Row { + Image( + painterResource(Res.drawable.p3), + contentDescription = null, + modifier = Modifier.requiredSize(60.dp) + ) + Text(text = item.title, modifier = Modifier.padding(16.dp)) + } } - } - Divider() + Divider() - Text( - text = "In-built ListItems", - style = typography.subtitle1, - modifier = Modifier.padding(8.dp) - ) - ListItem(text = { Text(item.title) }, secondaryText = { Text(item.subtitle) }) - Divider(modifier = Modifier.padding(4.dp)) - ListItem( - text = { Text(item.title) }, - secondaryText = { Text(item.subtitle) }, - singleLineSecondaryText = false - ) - Divider(modifier = Modifier.padding(4.dp)) - ListItem(text = { Text(item.title) }, secondaryText = { Text(item.subtitle) }, icon = { - Image( - painterResource(ImageResource("composeRes/images/p3.jpeg")), - contentDescription = null + Text( + text = "In-built ListItems", + style = typography.subtitle1, + modifier = Modifier.padding(8.dp) ) - }) - Divider(modifier = Modifier.padding(4.dp)) - //I am not sure why this is not going multiline for secondaryText... - ListItem( - text = { Text(item.title) }, - secondaryText = { Text(item.subtitle) }, - icon = { Image(painterResource(ImageResource("composeRes/images/p1.jpeg")), contentDescription = null) }, - overlineText = { Text("Overline text") }, - singleLineSecondaryText = false - ) - Divider() - ListItem( - text = { Text(item.title) }, - secondaryText = { Text(item.subtitle) }, - icon = { Image(painterResource(ImageResource("composeRes/images/p2.jpeg")), contentDescription = null) }, - trailing = { Icon(Icons.Default.ShoppingCart, contentDescription = null) }, - singleLineSecondaryText = false - ) - Divider() - + ListItem(text = { Text(item.title) }, secondaryText = { Text(item.subtitle) }) + Divider(modifier = Modifier.padding(4.dp)) + ListItem( + text = { Text(item.title) }, + secondaryText = { Text(item.subtitle) }, + singleLineSecondaryText = false + ) + Divider(modifier = Modifier.padding(4.dp)) + ListItem(text = { Text(item.title) }, secondaryText = { Text(item.subtitle) }, icon = { + Image( + painterResource(Res.drawable.p3), + contentDescription = null + ) + }) + Divider(modifier = Modifier.padding(4.dp)) + //I am not sure why this is not going multiline for secondaryText... + ListItem( + text = { Text(item.title) }, + secondaryText = { Text(item.subtitle) }, + icon = { + Image( + painterResource(Res.drawable.p1), + contentDescription = null + ) + }, + overlineText = { Text("Overline text") }, + singleLineSecondaryText = false + ) + Divider() + ListItem( + text = { Text(item.title) }, + secondaryText = { Text(item.subtitle) }, + icon = { + Image( + painterResource(Res.drawable.p2), + contentDescription = null + ) + }, + trailing = { Icon(Icons.Default.ShoppingCart, contentDescription = null) }, + singleLineSecondaryText = false + ) + Divider() + } } \ No newline at end of file diff --git a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/ResizablePanel.kt b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/ResizablePanel.kt index 4fe446c26f..ba4e09306a 100644 --- a/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/ResizablePanel.kt +++ b/examples/widgets-gallery/shared/src/commonMain/kotlin/org/jetbrains/compose/demo/widgets/ui/utils/ResizablePanel.kt @@ -8,8 +8,8 @@ import androidx.compose.material.Icon import androidx.compose.material.LocalContentColor import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material.icons.filled.ArrowForward +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.ArrowForward import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -60,7 +60,10 @@ fun ResizablePanel( .clickable { state.isExpanded = !state.isExpanded } ) { Icon( - if (state.isExpanded) Icons.Default.ArrowBack else Icons.Default.ArrowForward, + imageVector = if (state.isExpanded) + Icons.AutoMirrored.Default.ArrowBack + else + Icons.AutoMirrored.Default.ArrowForward, contentDescription = if (state.isExpanded) "Collapse" else "Expand", tint = LocalContentColor.current, modifier = Modifier diff --git a/examples/widgets-gallery/shared/src/commonTest/kotlin/ExampleTest.kt b/examples/widgets-gallery/shared/src/commonTest/kotlin/ExampleTest.kt new file mode 100644 index 0000000000..4c6bf0d9ec --- /dev/null +++ b/examples/widgets-gallery/shared/src/commonTest/kotlin/ExampleTest.kt @@ -0,0 +1,34 @@ +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.test.* +import kotlin.test.Test + + +/** + * This is a simple, sample test. + */ +class ExampleTest { + @OptIn(ExperimentalTestApi::class) + @Test + fun myTest() = runComposeUiTest { + setContent { + var text by remember { mutableStateOf("Hello") } + Text( + text = text, + modifier = Modifier.testTag("text") + ) + Button( + onClick = { text = "Compose" }, + modifier = Modifier.testTag("button") + ){ + Text("Click me") + } + } + + onNodeWithTag("text").assertTextEquals("Hello") + onNodeWithTag("button").performClick() + onNodeWithTag("text").assertTextEquals("Compose") + } +} \ No newline at end of file diff --git a/examples/widgets-gallery/shared/src/commonTest/kotlin/WidgetsPanelTest.kt b/examples/widgets-gallery/shared/src/commonTest/kotlin/WidgetsPanelTest.kt new file mode 100644 index 0000000000..155b2dd167 --- /dev/null +++ b/examples/widgets-gallery/shared/src/commonTest/kotlin/WidgetsPanelTest.kt @@ -0,0 +1,28 @@ +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.runComposeUiTest +import org.jetbrains.compose.demo.widgets.ui.WidgetsPanel +import org.jetbrains.compose.demo.widgets.ui.WidgetsType +import org.jetbrains.compose.demo.widgets.ui.listItemTestTag +import kotlin.test.Test + + +@OptIn(ExperimentalTestApi::class) +class WidgetsPanelTest { + /** + * Tests that clicking on each widget type in the list shows the corresponding widgets view. + */ + @OptIn(ExperimentalTestApi::class) + @Test + fun clickingOnWidgetListItemShowsCorrectWidgetUi() = runComposeUiTest { + setContent { + WidgetsPanel() + } + + for (widgetsType in WidgetsType.entries) { + onNodeWithTag(widgetsType.listItemTestTag).performClick() + onNodeWithTag(widgetsType.testTag).assertExists() + } + } +} \ No newline at end of file