KakaoCup / Compose

Nice and simple DSL for Espresso Compose UI testing in Kotlin
https://kakaocup.github.io/Compose/
Apache License 2.0
146 stars 15 forks source link

Can not assert child of KLazyListItemNode #81

Closed kongvorawut closed 7 months ago

kongvorawut commented 7 months ago

A KLazyListItemNode can have children like title and subtitle text, but can't to verify title node and subtitle node because nodes are merged.

Workaround: set useUnmergedTree is true

class KItem(
        semanticsNode: SemanticsNode,
        semanticsProvider: SemanticsNodeInteractionsProvider,
): KLazyListItemNode<KItem>(semanticsNode, semanticsProvider) {
      val title: KNode = child {
          useUnmergedTree = true   // add this
          hasTestTag("title")
      }
      val subtitle: KNode = child {
          useUnmergedTree = true   // add this
          hasTestTag("subtitle")
      }
}

Is there a way to make this code easier to use?

EvgenyMeltsaykin commented 7 months ago

Hi!

You can override the KNode constructor like in this issue

@Vacxe Can you explain why the useUnmergedTree flag has a default value of false? Perhaps it's worth pointing this out in the documentation and workaround examples?

Vacxe commented 7 months ago

@EvgenyMeltsaykin sure mate, actually the answer is quite simple: Kakao/KakaoCompose it's a DSL wrapper over Espresso library, with amount of extra custom matchers and assertions. We trying DO NOT change any default Espresso behavior. So, lets jump in to Espresso code

androidx.compose.ui.test.SemanticsNodeInteractionsProvider

package androidx.compose.ui.test

import androidx.compose.ui.test.internal.JvmDefaultWithCompatibility

/**
 * Provides the main entry point into testing.
 *
 * Typically implemented by a test rule.
 */
@JvmDefaultWithCompatibility
interface SemanticsNodeInteractionsProvider {
    /**
     * Finds a semantics node that matches the given condition.
     *
     * Any subsequent operation on its result will expect exactly one element found (unless
     * [SemanticsNodeInteraction.assertDoesNotExist] is used) and will throw [AssertionError] if
     * none or more than one element is found.
     *
     * For usage patterns and semantics concepts see [SemanticsNodeInteraction]
     *
     * @param matcher Matcher used for filtering
     * @param useUnmergedTree Find within merged composables like Buttons.
     * @see onAllNodes to work with multiple elements
     */
    fun onNode(
        matcher: SemanticsMatcher,
        useUnmergedTree: Boolean = false
    ): SemanticsNodeInteraction

    /**
     * Finds all semantics nodes that match the given condition.
     *
     * If you are working with elements that are not supposed to occur multiple times use [onNode]
     * instead.
     *
     * For usage patterns and semantics concepts see [SemanticsNodeInteraction]
     *
     * @param matcher Matcher used for filtering.
     * @param useUnmergedTree Find within merged composables like Buttons.
     * @see onNode
     */
    fun onAllNodes(
        matcher: SemanticsMatcher,
        useUnmergedTree: Boolean = false
    ): SemanticsNodeInteractionCollection
}

useUnmergedTree: Boolean = false - default Espresso behavior