Skip to content

Commit 07da8c6

Browse files
committed
fix(test): Resolve navigation test case issues caused by altering start destination
1 parent f3f2067 commit 07da8c6

File tree

8 files changed

+84
-15
lines changed

8 files changed

+84
-15
lines changed

app/src/androidTest/java/com/wei/amazingtalker/ui/AtAppStateTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ class AtAppStateTest {
8989
}
9090

9191
assertThat(state.topLevelDestinations).hasSize(3)
92-
assertThat(state.topLevelDestinations[0].name).ignoringCase().contains("schedule")
93-
assertThat(state.topLevelDestinations[1].name).ignoringCase().contains("home")
92+
assertThat(state.topLevelDestinations[0].name).ignoringCase().contains("home")
93+
assertThat(state.topLevelDestinations[1].name).ignoringCase().contains("schedule")
9494
assertThat(state.topLevelDestinations[2].name).ignoringCase().contains("contact_me")
9595
}
9696

app/src/androidTest/java/com/wei/amazingtalker/ui/NavigationRobot.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ internal open class NavigationRobot(
6868
composeTestRule.waitForIdle()
6969
}
7070

71-
private fun clickNavHome() {
71+
internal fun clickNavHome() {
7272
navHome.performClick()
7373
// 等待任何動畫完成
7474
composeTestRule.waitForIdle()

app/src/androidTest/java/com/wei/amazingtalker/ui/NavigationTest.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ class NavigationTest {
5151
}
5252

5353
@Test
54-
fun isScheduleScreen_afterLogin() {
54+
fun isHomeScreen_afterLogin() {
5555
welcomeEndToEndRobot(composeTestRule) {
5656
} getStartedClick {
5757
} login {
58-
verifyScheduleTopAppBarDisplayed()
58+
verifyMenuButtonDisplayed()
5959
}
6060
}
6161

@@ -77,11 +77,11 @@ class NavigationTest {
7777
}
7878

7979
/*
80-
* When pressing back from any top level destination except "Schedule", the app navigates back
81-
* to the "Schedule" destination, no matter which destinations you visited in between.
80+
* When pressing back from any top level destination except "Home", the app navigates back
81+
* to the "Home" destination, no matter which destinations you visited in between.
8282
*/
8383
@Test
84-
fun navigationBar_backFromAnyDestination_returnsToSchedule() {
84+
fun navigationBar_backFromAnyDestination_returnsToHome() {
8585
welcomeEndToEndRobot(composeTestRule) {
8686
} getStartedClick {
8787
} login {
@@ -91,7 +91,7 @@ class NavigationTest {
9191
// WHEN the user uses the system button/gesture to go back
9292
Espresso.pressBack()
9393
}
94-
verifyScheduleTopAppBarDisplayed()
94+
verifyMenuButtonDisplayed()
9595
}
9696
}
9797

@@ -106,8 +106,8 @@ class NavigationTest {
106106
navigationRobot(composeTestRule) {
107107
// GIVEN the user navigates to the Contact Me destination
108108
clickNavContactMe()
109-
// and then navigates to the Schedule destination
110-
clickNavSchedule()
109+
// and then navigates to the Home destination
110+
clickNavHome()
111111
// WHEN the user uses the system button/gesture to go back
112112
Espresso.pressBack()
113113
// THEN the app quits
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.wei.amazingtalker.ui.robot
2+
3+
import androidx.annotation.StringRes
4+
import androidx.compose.ui.semantics.Role
5+
import androidx.compose.ui.semantics.SemanticsProperties
6+
import androidx.compose.ui.semantics.getOrNull
7+
import androidx.compose.ui.test.SemanticsMatcher
8+
import androidx.compose.ui.test.assertIsDisplayed
9+
import androidx.compose.ui.test.hasContentDescription
10+
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
11+
import androidx.test.ext.junit.rules.ActivityScenarioRule
12+
import com.wei.amazingtalker.MainActivity
13+
import kotlin.properties.ReadOnlyProperty
14+
import com.wei.amazingtalker.feature.home.R as FeatureHomeR
15+
16+
/**
17+
* Screen Robot for End To End Test.
18+
*
19+
* 遵循此模型,找到測試使用者介面元素、檢查其屬性、和透過測試規則執行動作:
20+
* composeTestRule{.finder}{.assertion}{.action}
21+
*
22+
* Testing cheatsheet:
23+
* https://developer.android.com/jetpack/compose/testing-cheatsheet
24+
*/
25+
internal fun homeEndToEndRobot(
26+
composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<MainActivity>, MainActivity>,
27+
func: HomeEndToEndRobot.() -> Unit,
28+
) = HomeEndToEndRobot(composeTestRule).apply(func)
29+
30+
internal open class HomeEndToEndRobot(
31+
private val composeTestRule: AndroidComposeTestRule<ActivityScenarioRule<MainActivity>, MainActivity>,
32+
) {
33+
private fun AndroidComposeTestRule<*, *>.stringResource(@StringRes resId: Int) =
34+
ReadOnlyProperty<Any?, String> { _, _ -> activity.getString(resId) }
35+
36+
private fun withRole(role: Role) = SemanticsMatcher("${SemanticsProperties.Role.name} contains '$role'") {
37+
val roleProperty = it.config.getOrNull(SemanticsProperties.Role) ?: false
38+
roleProperty == role
39+
}
40+
41+
// The strings used for matching in these tests
42+
private val menuDescription by composeTestRule.stringResource(FeatureHomeR.string.menu)
43+
44+
private val menuButton by lazy {
45+
composeTestRule.onNode(
46+
withRole(Role.Button)
47+
.and(hasContentDescription(menuDescription)),
48+
)
49+
}
50+
51+
fun verifyMenuButtonDisplayed() {
52+
menuButton.assertExists().assertIsDisplayed()
53+
}
54+
55+
fun isMenuButtonDisplayed(): Boolean {
56+
return try {
57+
verifyMenuButtonDisplayed()
58+
true
59+
} catch (e: AssertionError) {
60+
false
61+
}
62+
}
63+
}

app/src/androidTest/java/com/wei/amazingtalker/ui/robot/LoginEndToEndRobot.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ internal open class LoginEndToEndRobotRobot(
6363
}
6464
}
6565

66-
infix fun login(func: ScheduleEndToEndRobot.() -> Unit): ScheduleEndToEndRobot {
66+
infix fun login(func: HomeEndToEndRobot.() -> Unit): HomeEndToEndRobot {
6767
loginButton.performClick()
68-
return scheduleEndToEndRobot(composeTestRule) {
68+
return homeEndToEndRobot(composeTestRule) {
6969
// 等待任何動畫完成
70-
composeTestRule.waitUntil(3_000) { isScheduleTopAppBarDisplayed() }
70+
composeTestRule.waitUntil(3_000) { isMenuButtonDisplayed() }
7171
func()
7272
}
7373
}

feature/home/src/main/java/com/wei/amazingtalker/feature/home/home/HomeScreen.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,14 @@ fun loadImageUsingCoil(resId: Int, isPreview: Boolean): Painter {
314314
private fun MenuButton(
315315
onMenuClick: () -> Unit,
316316
) {
317+
val menu = stringResource(R.string.menu)
318+
317319
IconButton(
318320
onClick = onMenuClick,
319321
modifier = Modifier
320322
.clip(CircleShape)
321323
.background(MaterialTheme.colorScheme.surfaceVariant)
322-
.semantics { contentDescription = "" },
324+
.semantics { contentDescription = menu },
323325
) {
324326
Icon(
325327
imageVector = AtIcons.Menu,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
3+
<!-- 首頁 -->
34
<string name="profile_picture">%s 的大頭貼</string>
5+
<string name="menu">選單</string>
46
</resources>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
3+
<!-- 首頁 -->
34
<string name="profile_picture">%s\'s profile picture</string>
5+
<string name="menu">Menu</string>
46
</resources>

0 commit comments

Comments
 (0)