package social.grain import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.v2.createComposeRule import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import social.grain.data.model.AspectRatio import social.grain.data.model.GrainGallery import social.grain.data.model.GrainPhoto import social.grain.data.model.GrainProfile import social.grain.ui.components.GalleryCard import social.grain.ui.theme.GrainTheme private const val ALT = "A heron standing in shallow water at dawn" /** Long enough to clear the platform's double-tap timeout. */ private const val DOUBLE_TAP_WINDOW_MS = 1000L /** * The card carries a photo's description itself. * * The feed no longer pushes a detail screen, so a tap on the photo has to be * what reveals the alt text — if this regresses, the description becomes * unreachable to anyone not using a screen reader. */ @RunWith(AndroidJUnit4::class) class GalleryCardAltTextTest { @get:Rule val composeRule = createComposeRule() private fun gallery(alt: String?) = GrainGallery( uri = "at://did:plc:test/social.grain.gallery/1", creator = GrainProfile(did = "did:plc:test", handle = "heron.example"), items = listOf( GrainPhoto( uri = "at://did:plc:test/social.grain.photo/1", alt = alt, aspectRatio = AspectRatio(3, 2), ), ), indexedAt = "2026-08-01T00:00:00Z", ) @Test fun tappingThePhotoTogglesTheAltText() { composeRule.setContent { GrainTheme { GalleryCard(gallery = gallery(ALT)) } } composeRule.onNodeWithText(ALT).assertDoesNotExist() composeRule.onNodeWithContentDescription(ALT).performClick() // The carousel also listens for a double tap, so a single tap is only // reported once that window has passed. composeRule.mainClock.advanceTimeBy(DOUBLE_TAP_WINDOW_MS) composeRule.onNodeWithText(ALT).assertIsDisplayed() composeRule.onNodeWithText(ALT).performClick() composeRule.waitForIdle() composeRule.onNodeWithText(ALT).assertDoesNotExist() } @Test fun theBadgeAlsoOpensTheAltText() { composeRule.setContent { GrainTheme { GalleryCard(gallery = gallery(ALT)) } } composeRule.onNodeWithContentDescription("Show alt text").performClick() composeRule.onNodeWithText(ALT).assertIsDisplayed() } @Test fun aPhotoWithNoAltShowsNoBadge() { composeRule.setContent { GrainTheme { GalleryCard(gallery = gallery(null)) } } composeRule.onNodeWithText("ALT").assertDoesNotExist() } }