I found what I was looking for... Please let me know if anyone has a better solution.
This is what I did:
- Add this dependency in your
build.gradle
.
implementation "androidx.test.espresso.idling:idling-concurrent:3.5.0-alpha07"
This is necessary to use the IdlingThreadPoolExecutor
class.
- Declare the an
IdlingThreadPool
object like below:
object IdlingThreadPool: IdlingThreadPoolExecutor(
"coroutinesDispatchersThreadPool",
Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors(),
0L,
TimeUnit.MILLISECONDS,
LinkedBlockingQueue(),
Executors.defaultThreadFactory()
)
I get this hint from this issue in the Coil github page.
- Use the object declared above in the
ImageRequest
object.
@Composable
fun SvgImageSample() {
val painter = rememberAsyncImagePainter(
model = ImageRequest.Builder(LocalContext.current)
.dispatcher(IdlingThreadPool.asCoroutineDispatcher()) // << here
.decoderFactory(SvgDecoder.Factory())
.data("https://someserver.com/SVG_image.svg")
.size(Size.ORIGINAL)
.build()
)
Image(
painter = painter,
modifier = Modifier
.size(100.dp)
.semantics {
testTag = "myImg"
coilAsyncPainter = painter
},
contentDescription = null
)
}
Notice the IdlingThreadPool
object was used in the dispatcher
function. The other detail is coilAsyncPainter
property which is receiving the painter
object. It will be necessary during the test to check if the image was loaded.
- Declare the
coilAsyncPainter
semantic property.
val CoilAsyncPainter = SemanticsPropertyKey<AsyncImagePainter>("CoilAsyncPainter")
var SemanticsPropertyReceiver.coilAsyncPainter by CoilAsyncPainter
This is what you need to do in the application code.
- In the test code, declare a new
SemanticNodeInteration
.
fun SemanticsNodeInteraction.isAsyncPainterComplete(): SemanticsNodeInteraction {
assert(
SemanticsMatcher("Async Image is Success") { semanticsNode ->
val painter = semanticsNode.config.getOrElseNullable(CoilAsyncPainter) { null }
painter?.state is AsyncImagePainter.State.Success
}
)
return this;
}
So here, basically the painter object is obtained from the semantic property and then is checked if the current state is Success
.
- Finally, here it is the test.
class MyTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun async_image_was_displayed() {
composeTestRule.setContent {
MyAppThemeTheme {
SvgImageSample()
}
}
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("myImg")
.isAsyncPainterComplete()
}
}