pedrovgs / Shot

Screenshot testing library for Android
Apache License 2.0
1.18k stars 115 forks source link

Waiting for remote image fetch #326

Open DerekBeam opened 1 year ago

DerekBeam commented 1 year ago

Expected behaviour

For reference, I am using Coil to load images over the network. I've provided each of these images with a fallback and a loading state via the code below:

@Composable
fun AsyncImageStateful(
    modifier: Modifier = Modifier,
    image: String,
    fallback: Painter,
    contentScale: ContentScale,
    contentDescription: String = ""
) {
    SubcomposeAsyncImage(
        modifier = modifier,
        model = ImageRequest.Builder(context = LocalContext.current)
            .data(
                data = image
            )
            .decoderFactory(
                factory = SvgDecoder.Factory()
            )
            .crossfade(enable = true)
            .build(),
        contentDescription = contentDescription,
        contentScale = contentScale,
        alignment = Alignment.TopCenter
    ) {
        when (painter.state) {
            is AsyncImagePainter.State.Loading -> {
                Box(
                    modifier = modifier
                        .placeholder(
                            visible = true,
                            color = Charcoal100,
                            highlight = PlaceholderHighlight.shimmer(
                                highlightColor = Color.White
                            )
                        )
                )
            }
            is AsyncImagePainter.State.Success -> {
                SubcomposeAsyncImageContent()
            }
            else -> {
                SubcomposeAsyncImageContent(
                    painter = fallback
                )
            }
        }
    }
}

This essentially adds my shimmer when the image is loading, and reverts to the provided fallback image if the image doesn't load or doesn't point to anything.

I expect there to be a way to wait for this to complete before taking the snapshot.

Actual behaviour

I am seeing inconsistent behavior where sometimes the snapshots complete with an actual image (when a real URL is provided) and some complete with the fallback image (when the URL is invalid) and some don't complete at all (remains in loading). This causes my snapshots to inconsistently fail for different reasons.

I have tried adding coroutine delays in prepareUIForScreenshot without any luck. I don't know how else to have it wait so these remain consistent.

Steps to reproduce

  1. Add accompanist placeholder and coil to app build.gradle
implementation 'com.google.accompanist:accompanist-placeholder:0.28.0'`
implementation 'io.coil-kt:coil-compose:2.2.2'
implementation 'io.coil-kt:coil-svg:2.2.2'
  1. Use the above composable in a snapshot test
AsyncImageStateful(
    modifier = Modifier
        .size(
            width = 95.dp,
            height = 85.dp
        )
        .clip(shape = RoundedCornerShape(size = 8.dp))
        .loadingPlaceholder(visible = displayModel.isLoading),
    image = displayModel.image,
    contentScale = ContentScale.Crop,
    contentDescription = "${displayModel.name} Image",
    fallback = painterResource(id = R.drawable.fallback)
)
  1. Provide a fallback image (i.e. R.drawable.fallback)
  2. Record the snapshots
  3. Observe that verification of snapshots sometimes fails due to the image not loading in time

Version of the library

Shot 5.14.1

nelson-glauber commented 9 months ago

Any news about this issue? I'm facing the same problem.