Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Enhanced StaffScreen testing. #502

Merged
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package io.github.droidkaigi.confsched.testing.robot

import androidx.compose.ui.test.assertContentDescriptionEquals
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.onChildren
import androidx.compose.ui.test.onFirst
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.performScrollToIndex
import io.github.droidkaigi.confsched.designsystem.theme.KaigiTheme
import io.github.droidkaigi.confsched.model.Staff
import io.github.droidkaigi.confsched.model.fakes
import io.github.droidkaigi.confsched.staff.StaffItemTestTagPrefix
import io.github.droidkaigi.confsched.staff.StaffScreen
import io.github.droidkaigi.confsched.staff.StaffScreenLazyColumnTestTag
import io.github.droidkaigi.confsched.staff.component.StaffItemImageTestTag
import io.github.droidkaigi.confsched.staff.component.StaffItemUserNameTextTestTag
import io.github.droidkaigi.confsched.testing.utils.assertCountAtLeast
import io.github.droidkaigi.confsched.testing.utils.hasTestTag
import javax.inject.Inject

class StaffScreenRobot @Inject constructor(
Expand All @@ -26,20 +35,81 @@ class StaffScreenRobot @Inject constructor(
waitUntilIdle()
}

fun checkExistsStaffItem() {
fun scrollToIndex10() {
composeTestRule
.onNode(hasTestTag(StaffScreenLazyColumnTestTag))
.onChildren()
.onFirst()
.assertExists()
.assertIsDisplayed()
.performScrollToIndex(10)
}

fun checkDoesNotExistsStaffItem() {
fun checkShowFirstAndSecondStaffs() {
checkRangeStaffItemsDisplayed(
fromTo = 0..2,
)
}

private fun checkRangeStaffItemsDisplayed(
fromTo: IntRange,
) {
val staffList = Staff.fakes().subList(fromTo.first, fromTo.last)
staffList.forEach { staff ->
composeTestRule
.onNode(hasTestTag(StaffItemTestTagPrefix.plus(staff.id)))
.assertExists()
.assertIsDisplayed()

composeTestRule
.onNode(
matcher = hasTestTag(StaffItemImageTestTag.plus(staff.username)),
useUnmergedTree = true,
)
.assertExists()
.assertIsDisplayed()
.assertContentDescriptionEquals(staff.username)

composeTestRule
.onNode(
matcher = hasTestTag(StaffItemUserNameTextTestTag.plus(staff.username)),
useUnmergedTree = true,
)
.assertExists()
.assertIsDisplayed()
.assertTextEquals(staff.username)
}
}

fun checkStaffItemsDisplayed() {
// Check there are two staffs
composeTestRule
.onNode(hasTestTag(StaffScreenLazyColumnTestTag))
.onChildren()
.onFirst()
.onAllNodes(hasTestTag(StaffItemTestTagPrefix, substring = true))
.assertCountAtLeast(2)
}

fun checkDoesNotFirstStaffItemDisplayed() {
val staff = Staff.fakes().first()
composeTestRule
.onNode(hasTestTag(StaffItemTestTagPrefix.plus(staff.id)))
.assertDoesNotExist()

composeTestRule
.onNode(
matcher = hasTestTag(StaffItemImageTestTag.plus(staff.username)),
useUnmergedTree = true,
)
.assertDoesNotExist()

composeTestRule
.onNode(
matcher = hasTestTag(StaffItemUserNameTextTestTag.plus(staff.username)),
useUnmergedTree = true,
)
.assertDoesNotExist()
}

fun checkErrorSnackbarDisplayed() {
composeTestRule
.onNode(
hasText("Fake IO Exception"),
useUnmergedTree = true,
).assertIsDisplayed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import io.github.droidkaigi.confsched.testing.DescribedBehavior
import io.github.droidkaigi.confsched.testing.describeBehaviors
import io.github.droidkaigi.confsched.testing.execute
import io.github.droidkaigi.confsched.testing.robot.StaffScreenRobot
import io.github.droidkaigi.confsched.testing.robot.StaffServerRobot.ServerStatus.Error
import io.github.droidkaigi.confsched.testing.robot.StaffServerRobot.ServerStatus.Operational
import io.github.droidkaigi.confsched.testing.robot.StaffServerRobot
import io.github.droidkaigi.confsched.testing.robot.runRobot
import io.github.droidkaigi.confsched.testing.rules.RobotTestRule
import org.junit.Rule
Expand Down Expand Up @@ -41,36 +40,46 @@ class StaffScreenTest(
return describeBehaviors<StaffScreenRobot>(name = "StaffScreen") {
describe("when server is operational") {
run {
setupStaffServer(Operational)
setupStaffServer(StaffServerRobot.ServerStatus.Operational)
}
describe("when launch") {
run {
setupScreenContent()
}
itShould("show staff screen") {
captureScreenWithChecks(
checks = {
checkExistsStaffItem()
},
)
itShould("show first and second staffs") {
captureScreenWithChecks {
checkShowFirstAndSecondStaffs()
}
}
}
}

describe("when server is down") {
run {
setupStaffServer(Error)
describe("when scroll to index 10") {
run {
scrollToIndex10()
}
itShould("show staffs") {
captureScreenWithChecks {
checkStaffItemsDisplayed()
}
}
}
}
describe("when launch") {

describe("when server is down") {
run {
setupScreenContent()
setupStaffServer(StaffServerRobot.ServerStatus.Error)
}
itShould("show snackbar") {
captureScreenWithChecks(
checks = {
checkDoesNotExistsStaffItem()
},
)
describe("when launch") {
run {
setupScreenContent()
}
itShould("does not show staff and show snackbar") {
captureScreenWithChecks(
checks = {
checkDoesNotFirstStaffItemDisplayed()
checkErrorSnackbarDisplayed()
},
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import org.jetbrains.compose.ui.tooling.preview.Preview
const val staffScreenRoute = "staff"
const val StaffScreenTestTag = "StaffScreenTestTag"
const val StaffScreenLazyColumnTestTag = "StaffScreenLazyColumnTestTag"
const val StaffItemTestTagPrefix = "StaffItemTestTag:"

fun NavGraphBuilder.staffScreens(
onNavigationIconClick: () -> Unit,
Expand Down Expand Up @@ -121,21 +122,23 @@ fun StaffScreen(
modifier = Modifier
.fillMaxSize()
.padding(top = padding.calculateTopPadding())
.testTag(StaffScreenLazyColumnTestTag)
.let {
if (scrollBehavior != null) {
it.nestedScroll(scrollBehavior.nestedScrollConnection)
} else {
it
}
},
}
.testTag(StaffScreenLazyColumnTestTag),
contentPadding = PaddingValues(bottom = padding.calculateBottomPadding()),
) {
items(uiState.staff) { staff ->
StaffItem(
staff = staff,
onStaffItemClick = onStaffItemClick,
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.testTag(StaffItemTestTagPrefix.plus(staff.id)),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import io.github.droidkaigi.confsched.designsystem.theme.KaigiTheme
Expand All @@ -29,6 +30,9 @@ import org.jetbrains.compose.ui.tooling.preview.Preview

private val staffIconShape = CircleShape

const val StaffItemImageTestTag = "StaffItemImageTestTag:"
const val StaffItemUserNameTextTestTag = "StaffItemUserNameTextTestTag:"

@Composable
fun StaffItem(
staff: Staff,
Expand All @@ -48,21 +52,23 @@ fun StaffItem(
painter = previewOverride(previewPainter = { rememberVectorPainter(image = Icons.Default.Person) }) {
rememberAsyncImagePainter(staff.iconUrl)
},
contentDescription = null,
contentDescription = staff.username,
modifier = Modifier
.size(52.dp)
.clip(staffIconShape)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.outline,
shape = staffIconShape,
),
)
.testTag(StaffItemImageTestTag.plus(staff.username)),
)
Text(
text = staff.username,
style = MaterialTheme.typography.bodyLarge,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.testTag(StaffItemUserNameTextTestTag.plus(staff.username)),
)
}
}
Expand Down
Loading