Thread
#compose-wear
    y

    yschimke

    6 months ago
    A question about Compose Tests building on Wear Compose / Material. I ended up with a test like
    @Test
        fun testAutoHide() {
            composeTestRule.setContent {
                VolumePositionIndicator(
                    modifier = Modifier.testTag(TEST_TAG),
                    volumeState = { volumeState },
                    autoHide = true
                )
            }
    
            val positionIndicator = composeTestRule.onNodeWithTag(TEST_TAG)
    
            positionIndicator.assertDoesNotExist()
    
            volumeState = volumeState.copy(current = 51)
    
            composeTestRule.mainClock.advanceTimeByFrame()
            composeTestRule.mainClock.advanceTimeBy(500L)
    
            composeTestRule.onRoot(useUnmergedTree = true).printToLog("testAutoHide")
    
            positionIndicator.assertIsDisplayed()
        }
    Two questions
    1. I found the advanceTimeByFrame + advanceTimeBy pattern in stackoverflow, without the frame advance, the animations don't seem to run. Is this known, expected?
    2. It's awkward trying to test again classes like PositionIndicator. The Scroll State classes that you use internally to validate the behaviour are internal. Are there any patterns used in mobile compose - for validating the state of core library classes like PositionIndicator?
    I guess I'm asking for this - https://developer.android.com/jetpack/compose/testing#custom-semantics-properties Maybe with an optional flag to enable?
    John Nichol

    John Nichol

    6 months ago
    @Steve Bower [G]
    Steve Bower [G]

    Steve Bower [G]

    6 months ago
    Hi - I would expect to see
    composeTestRule.mainClock.autoAdvance = false
    at the start of the test if the clock is going to be manually driven. In which case, yes, the clock will be fixed and the animations won't run until the clock is advanced manually. For (2), could you be more specific about the tests you want to run against PositionIndicator? There are a number of overloads for which the scroll state is public (e.g. ScalingLazyListState) or you can add your own PositionIndicatorState implementation.
    y

    yschimke

    6 months ago
    Yep - I've got multiple tests so using.
    @get:Rule
        val composeTestRule = createComposeRule().apply {
            mainClock.autoAdvance = false
        }
    I'm trying to test my own component which uses PositionIndicator. Specifically the float one.
    @Composable
    public fun PositionIndicator(
        value: () -> Float,
        modifier: Modifier = Modifier,
        range: ClosedFloatingPointRange<Float> = 0f..1f,
        color: Color = MaterialTheme.colors.onBackground,
        reverseDirection: Boolean = false
    ) = PositionIndicator(
        state = FractionPositionIndicatorState {
            (value() - range.start) / (range.endInclusive - range.start)
        },
    FractionPositionIndicatorState is internal but created inside anyway.
    I was imagining that Composable's with testTag could output state that shows up in SemanticNodeInteraction.printToLog and can be tested against. But I think you raise a great point, normally you test via real objects, not poking around quasi-internal api through the semantics node. It's very brittle if you don't own those objects.
    Steve Bower [G]

    Steve Bower [G]

    6 months ago
    Yep - better to pass in a mock or stub test object, then you can record whatever interactions were expected.