package social.grain import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.runBlocking import kotlinx.serialization.json.Json import okhttp3.OkHttpClient import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import social.grain.data.api.XrpcClient import social.grain.data.api.getFeed import social.grain.data.model.GrainGallery import social.grain.data.model.GrainProfile import social.grain.ui.components.GalleryCard import social.grain.ui.theme.GrainTheme import java.util.concurrent.TimeUnit /** * The "favorited by" line is viewer-scoped, so it is absent from every * unauthenticated response and can't be observed from live data. These build * the shape the appview returns and check the three phrasings. */ @RunWith(AndroidJUnit4::class) class FacepileRenderTest { @get:Rule val composeRule = createComposeRule() private val client = XrpcClient( "https://grain.social", OkHttpClient.Builder().readTimeout(30, TimeUnit.SECONDS).build(), Json { ignoreUnknownKeys = true; explicitNulls = false; coerceInputValues = true }, ) private fun gallery(favedBy: List): GrainGallery = runBlocking { client.getFeed(feed = "recent", limit = 1).items.orEmpty().first() .copy(favedByFollowing = favedBy) } private fun people(count: Int): List = listOf("Alice", "Bob", "Carol").take(count).mapIndexed { index, name -> GrainProfile(did = "did:plc:facepile$index", handle = "${name.lowercase()}.test", displayName = name) } private fun render(count: Int) { val subject = gallery(people(count)) composeRule.setContent { GrainTheme { Surface { GalleryCard(gallery = subject, modifier = Modifier.fillMaxWidth()) } } } composeRule.waitForIdle() } @Test fun oneFavouriteNamesJustThatPerson() { render(1) composeRule.onNodeWithText("Favorited by Alice").assertExists() } @Test fun twoFavouritesAreJoinedWithAnd() { render(2) composeRule.onNodeWithText("Favorited by Alice and Bob").assertExists() } @Test fun threeOrMoreFallBackToAndOthers() { render(3) composeRule.onNodeWithText("Favorited by Alice, Bob and others you follow").assertExists() } @Test fun noFavouritesRendersNoRow() { val subject = gallery(emptyList()) composeRule.setContent { GrainTheme { Surface { GalleryCard(gallery = subject, modifier = Modifier.fillMaxWidth()) } } } composeRule.waitForIdle() composeRule.onNodeWithText("Favorited by", substring = true).assertDoesNotExist() } }