### Kotlin Interceptor Configuration Example Source: https://github.com/kakaocup/compose/blob/master/README.md Demonstrates how to configure interceptors at the Kakao-Compose runtime and individual `BaseNode` levels. It shows how to intercept `onAll`, `onCheck`, and `onPerform` calls, including overriding the chain with `onPerform(true)`. ```Kotlin class SomeTest { @Before fun setup() { KakaoCompose { // KakaoCompose runtime intercept { onComposeInteraction { onAll { list.add("ALL") } onCheck { _, _ -> list.add("CHECK") } onPerform { _, _ -> list.add("PERFORM") } } } } } @Test fun test() { onComposeScreen { intercept { onCheck { interaction, assertion -> // Intercept check() call Log.d("KAKAO", "$interaction is checking $assertion") } } myView { intercept { // Intercepting ComposeInteraction calls on this individual Node onPerform(true) { interaction, action -> // Intercept perform() call and overriding the chain // When performing actions on this view, Kakao level interceptor will not be called // and we have to manually call Espresso now. Log.d("KAKAO_NODE", "$interaction is performing $action") interaction.perform(action) } } } } } } ``` -------------------------------- ### Use IdlingDispatcher in ViewModel for Async Operations Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This Kotlin example demonstrates how to use the custom IdlingDispatcher within a ViewModel to manage asynchronous operations. It launches a coroutine that simulates a delay, ensuring that Espresso waits for its completion. ```kotlin import androidx.lifecycle.ViewModel import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch class MyViewModel : ViewModel() { private val idlingResource = CoroutineIdlingResource() private val idlingDispatcher = IdlingDispatcher(idlingResource) fun fetchData() { CoroutineScope(idlingDispatcher).launch { // Simulate a network request or long-running task kotlinx.coroutines.delay(2000) // Update UI or state } } fun getIdlingResource(): CoroutineIdlingResource { return idlingResource } } ``` -------------------------------- ### Kakao Compose Module Dependencies Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/introduction.md This diagram illustrates the dependencies between the four main modules of Kakao Compose: compose-test, compose, compose-ui, and compose-semantics. It also shows their relationships with Android Espresso and Android Compose. ```mermaid flowchart TD %% Nodes KTest("compose-test") KCompose("compose") KUI("compose-ui") KSemantics("compose-semantics") AEspresso("Espresso") ACompose("Android Compose") %% Connections KTest --> KCompose KUI --> KSemantics KTest --> KSemantics KSemantics --> ACompose KCompose --> ACompose KCompose --> AEspresso %% Style style AEspresso color:#FFFFFF, fill:#AA00FF, stroke:#AA00FF style ACompose color:#FFFFFF, fill:#AA00FF, stroke:#AA00FF ``` -------------------------------- ### Testing Lazy Lists with Kakao Compose Source: https://github.com/kakaocup/compose/blob/master/README.md Provides guidance on testing Jetpack Compose lazy lists using Kakao Compose. It explains how to define KLazyListNode, register item types, and use position matchers for accurate testing. ```Kotlin val list = KLazyListNode( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("LazyList") }, itemTypeBuilder = { itemType(::LazyListItemNode) itemType(::LazyListHeaderNode) }, positionMatcher = { position -> SemanticsMatcher.expectValue(LazyListItemPosition, position) } ) ``` ```Kotlin class LazyListItemNode( semanticsNode: SemanticsNode, semanticsProvider: SemanticsNodeInteractionsProvider, ) : KLazyListItemNode(semanticsNode, semanticsProvider) class LazyListHeaderNode( semanticsNode: SemanticsNode, semanticsProvider: SemanticsNodeInteractionsProvider, ) : KLazyListItemNode(semanticsNode, semanticsProvider) { val title: KNode = child { hasTestTag("LazyListHeaderTitle") } } ``` ```Kotlin LazyColumn( Modifier .fillMaxSize() .testTag("LazyList") ) { itemsIndexed(items) { index, item -> when (item) { is LazyListItem.Header -> ListItemHeader(item, Modifier.testTag("position=$index")) is LazyListItem.Item -> ListItemCell(item, Modifier.testTag("position=$index")) } } } ``` ```Kotlin positionMatcher = { position -> hasTestTag("position=$position") } ``` ```Kotlin val LazyListItemPosition = SemanticsPropertyKey("LazyListItemPosition") var SemanticsPropertyReceiver.lazyListItemPosition by LazyListItemPosition fun Modifier.lazyListItemPosition(position: Int): Modifier { return semantics { lazyListItemPosition = position } } ``` ```Kotlin positionMatcher = { position -> SemanticsMatcher.expectValue(LazyListItemPosition, position) } ``` ```Kotlin @Test fun lazyListTest() { onComposeScreen(composeTestRule) { list { firstChild { title.assertTextEquals("Items from 1 to 10") } childWith { hasText("Item 1") } perform { assertTextEquals("Item 1") } childAt(10) { assertTextEquals("Item 10") } } } } ``` -------------------------------- ### Add Dependencies for Coroutines and Espresso Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This snippet shows the necessary dependencies to include in your Android project's build.gradle file for using Kotlin Coroutines and Espresso for UI testing. ```kotlin dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") androidTestImplementation("androidx.test:runner:1.5.2") androidTestImplementation("androidx.test:rules:1.5.2") } ``` -------------------------------- ### Gradle Dependency for Kakao Compose (Kotlin) Source: https://github.com/kakaocup/compose/blob/master/README.md Illustrates the Gradle dependency declaration using Kotlin syntax for adding Kakao Compose to your Android project. ```Kotlin dependencies { androidTestImplementation("io.github.kakaocup:compose:") } ``` -------------------------------- ### Add Kakao Compose Core Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/kakao_compose_structure.md This snippet shows how to add the foundational Kakao Compose module to your project's dependencies. This module provides the core DSL wrapper for Espresso methods and ComposeScreen page objects. ```kotlin implementation("io.github.kakaocup:compose:1.0.0") ``` -------------------------------- ### Global Coroutine Tracking with IdlingRegistry (Kotlin) Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This code provides an alternative method for globally tracking coroutines by wrapping Dispatchers.Main or Dispatchers.IO using IdlingRegistry. This approach ensures all coroutines initiated through these dispatchers are monitored. ```kotlin import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asCoroutineDispatcher import java.util.concurrent.Executors object IdlingDispatcher { private val idlingResource = CoroutineIdlingResource() fun register() { Dispatchers.Main = IdlingDispatcherWrapper(Dispatchers.Main, idlingResource) Espresso.registerIdlingResources(idlingResource) } fun unregister() { Espresso.unregisterIdlingResources(idlingResource) } } ``` -------------------------------- ### Write Test for MainActivityScreen Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/screens.md This Kotlin code demonstrates how to use the MainActivityScreen Page Object in a UI test. It interacts with UI elements like text fields, asserts their display status, and checks their content using methods provided by the Page Object. ```kotlin class SimpleTest { @get:Rule val composeTestRule = createAndroidComposeRule() @Test fun simpleTest() { onComposeScreen(composeTestRule) { myText1 { assertIsDisplayed() assertTextContains("Simple text 1") } } } } ``` -------------------------------- ### Basic Interaction Test with Kakao Compose Source: https://github.com/kakaocup/compose/blob/master/README.md Demonstrates a simple test case using Kakao Compose to interact with UI elements. It shows how to assert if a button is displayed and contains specific text. ```Kotlin class ExampleInstrumentedTest { @Rule @JvmField val composeTestRule = createAndroidComposeRule() @Test fun simpleTest() { onComposeScreen(composeTestRule) { myButton { assertIsDisplayed() assertTextContains("Button 1") } onNode { hasTestTag("doesNotExist") }.invoke { assertDoesNotExist() } } } } ``` -------------------------------- ### Using waitUntil for Assertions (Kotlin) Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This snippet shows how to use the `waitUntil` function from the Kakao Compose library to perform assertions after a certain condition is met. It's presented as an alternative to setting up IdlingResources. ```kotlin mySimpleText { assertIsNotDisplayed() waitUntil { assertIsDisplayed() } assertIsDisplayed() } ``` -------------------------------- ### Gradle Dependency for Kakao Compose (Groovy) Source: https://github.com/kakaocup/compose/blob/master/README.md Shows the Gradle dependency declaration using Groovy syntax for integrating Kakao Compose into your Android project. ```Groovy dependencies { androidTestImplementation 'io.github.kakaocup:compose:' } ``` -------------------------------- ### Maven Dependency for Kakao Compose Source: https://github.com/kakaocup/compose/blob/master/README.md Provides the Maven dependency configuration required to include the Kakao Compose library in your project. ```XML io.github.kakaocup compose pom ``` -------------------------------- ### Combine Multiple Matchers for KNode Source: https://github.com/kakaocup/compose/blob/master/README.md Illustrates combining multiple matchers for a KNode to precisely target a UI element. This includes using `hasTestTag` and `hasText` simultaneously. ```Kotlin val myButton = KNode(this) { hasTestTag("myTestButton") hasText("Button 1") } ``` -------------------------------- ### Define MainActivityScreen Page Object Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/screens.md This Kotlin code defines a Page Object for the MainActivity screen using the Kakaocup library. It encapsulates UI elements like text fields and buttons, identified by test tags, providing an abstraction layer for test interactions. ```kotlin class MainActivityScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("MainScreen") }) { val myText1: KNode = child { hasTestTag("mySimpleText") } val clickCounter: KNode = child { hasTestTag("clickCounter") } } ``` -------------------------------- ### Add Kakao Compose UI Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/kakao_compose_structure.md This snippet shows the dependency for the compose-ui module, which wraps Compose's foundational components and applies semantics. Including this module introduces an indirect dependency on your project's Compose version. ```kotlin implementation("io.github.kakaocup:compose-ui:1.0.0") ``` -------------------------------- ### Kotlin Login UI Test with Page Objects Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/screens.md This Kotlin test script utilizes the Page Object pattern to test a login screen in a Jetpack Compose application. It defines interactions for input fields and a login button, and asserts the display of the main screen after a successful login. ```kotlin class LoginTest { @get:Rule val composeTestRule = createAndroidComposeRule() @Test fun simpleTest() { onComposeScreen(composeTestRule) { loginField { performTextInput("test@test.test") assertIsDisplayed() } passwordField { performTextInput("dummypass") } loginButton { performTouchInput { click() } } } onComposeScreen(composeTestRule) { assertIsDisplayed() } } } ``` -------------------------------- ### Define LoginScreen Page Object Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/screens.md This Kotlin code defines a Page Object for a Login screen. It abstracts UI elements such as login fields, password fields, and a login button, each identified by a specific test tag, facilitating interaction within tests. ```kotlin class LoginScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("LoginScreen") } ) { val loginField: KNode = child { hasTestTag("loginField") } val passwordField: KNode = child { hasTestTag("passwordField") } val loginButton: KNode = child { hasTestTag("loginButton") } } ``` -------------------------------- ### Create CoroutineIdlingResource for IdlingResource Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This Kotlin code defines a custom IdlingResource implementation that tracks the execution of coroutines. It uses an AtomicInteger to count active coroutines and notifies Espresso when the count reaches zero. ```kotlin import androidx.test.espresso.IdlingResource import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicInteger class CoroutineIdlingResource : IdlingResource { private val counter = AtomicInteger(0) private var resourceCallback: IdlingResource.ResourceCallback? = null override fun getName(): String { return CoroutineIdlingResource::class.java.name } override fun isIdleNow(): Boolean { return counter.get() == 0 } override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) { this.resourceCallback = callback } fun increment() { counter.getAndIncrement() } fun decrement() { val counterVal = counter.decrementAndGet() if (counterVal == 0) { resourceCallback?.onTransitionToIdle() } } } ``` -------------------------------- ### Add Kakao Compose Semantics Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/kakao_compose_structure.md This snippet demonstrates how to include the compose-semantics module, which contains default semantic keys used by other Kakao Compose modules. It's recommended for projects with design systems to avoid transitive dependencies on compose-ui. ```kotlin implementation("io.github.kakaocup:compose-semantics:1.0.0") ``` -------------------------------- ### Define ComposeScreen with Test Tag Source: https://github.com/kakaocup/compose/blob/master/README.md Demonstrates how to define a ComposeScreen in Kakao Compose, specifying a test tag for the root UI element. This is useful when the screen itself is associated with a specific test tag. ```Kotlin class MainActivityScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("MainScreen") } ) ``` -------------------------------- ### Define ComposeScreen without Test Tag Source: https://github.com/kakaocup/compose/blob/master/README.md Shows how to define a ComposeScreen without a specific test tag. This approach is suitable for screens that are abstractions and do not have a direct, identifiable UI node. ```Kotlin class MainActivityScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider ) ``` -------------------------------- ### Declare KNode with Explicit Matchers Source: https://github.com/kakaocup/compose/blob/master/README.md Shows how to declare a KNode using explicit matchers without relying on the `child` function. This provides flexibility in defining the target UI element. ```Kotlin class MainActivityScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("MainScreen") } ) { val myButton = KNode(this) { hasTestTag("myTestButton") } } ``` -------------------------------- ### Reduce Boilerplate with KakaoComposeTestRule Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/kakao_test_rule.md Demonstrates how to reduce boilerplate code in Compose UI tests by using KakaoComposeTestRule. This rule implicitly provides the composeTestRule to ComposeScreen and KNode calls, eliminating the need to pass it explicitly in each onComposeScreen call. ```kotlin class SimpleTestGlobalSemantic { @get:Rule val composeTestRule = createAndroidComposeRule() @get:Rule val kakaoComposeTestRule = KakaoComposeTestRule( semanticsProvider = composeTestRule ) @Test fun simpleTest() { onComposeScreen { myText1 { assertIsDisplayed() assertTextContains("Simple text 1") } } } } ``` -------------------------------- ### Add Kakao Compose Test Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/kakao_compose_structure.md This snippet provides the dependency for the compose-test module, which includes nodes for validating typed components like KButtonNode and KIconNode. This is typically used for test implementations. ```kotlin testImplementation("io.github.kakaocup:compose-test:1.0.0") ``` -------------------------------- ### Declare Child KNode with Parent Matcher Source: https://github.com/kakaocup/compose/blob/master/README.md Illustrates how to declare a child KNode within a ComposeScreen. The child node's matchers are combined with the parent's matchers, enabling targeted interaction with specific UI elements. ```Kotlin class MainActivityScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("MainScreen") } ) { val myButton: KNode = child { hasTestTag("myTestButton") } } ``` -------------------------------- ### Wrap CoroutineDispatcher with IdlingResource Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This Kotlin code creates a custom CoroutineDispatcher that integrates with the CoroutineIdlingResource. It increments the counter before a coroutine runs and decrements it after completion, ensuring proper synchronization. ```kotlin import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asCoroutineDispatcher import java.util.concurrent.Executors class IdlingDispatcher(private val idlingResource: CoroutineIdlingResource) : CoroutineDispatcher() { private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher() override fun dispatch(context: kotlin.coroutines.CoroutineContext, block: Runnable) { idlingResource.increment() dispatcher.dispatch(context, Runnable { try { block.run() } finally { idlingResource.decrement() } }) } } ``` -------------------------------- ### Register CoroutineIdlingResource in UI Test (Kotlin) Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/intermediate/async_code.md This snippet demonstrates how to register and unregister a CoroutineIdlingResource within a specific UI test class using JUnit and Espresso. It ensures that Espresso waits for coroutines to complete before proceeding with assertions. ```kotlin import androidx.test.espresso.Espresso import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.After import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class MyUITest { @get:Rule val activityRule = ActivityScenarioRule(MainActivity::class.java) private lateinit var idlingResource: CoroutineIdlingResource @Before fun registerIdlingResource() { activityRule.scenario.onActivity { activity -> val viewModel = (activity as MainActivity).viewModel idlingResource = viewModel.getIdlingResource() Espresso.registerIdlingResources(idlingResource) } } @Test fun testFetchData() { // Perform UI actions that trigger coroutines onView(withId(R.id.fetchDataButton)).perform(click()) // Espresso will wait until the coroutine finishes onView(withId(R.id.resultTextView)).check(matches(withText("Data Loaded"))) } @After fun unregisterIdlingResource() { Espresso.unregisterIdlingResources(idlingResource) } } ``` -------------------------------- ### Declare Nested Child KNode Source: https://github.com/kakaocup/compose/blob/master/README.md Demonstrates declaring a KNode as a child of another KNode, creating a hierarchy. This allows for testing nested UI components by combining multiple parent matchers. ```Kotlin class MainActivityScreen(semanticsProvider: SemanticsNodeInteractionsProvider) : ComposeScreen( semanticsProvider = semanticsProvider, viewBuilderAction = { hasTestTag("MainScreen") } ) { val myButton: KNode = child { hasTestTag("myTestButton") } val myButton2: KNode = myButton.child { hasTestTag("myTestButton2") } } ``` -------------------------------- ### Add Newline to End of File (Git) Source: https://github.com/kakaocup/compose/blob/master/CONTRIBUTING.md This Git command ensures that every file in the specified directory (library or sample projects) has a newline character at the end. This is a common code style requirement. ```Git git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done ``` -------------------------------- ### Global Override useUnmergedTree with KakaoComposeTestRule Source: https://github.com/kakaocup/compose/blob/master/documentation/docs/basics/kakao_test_rule.md Shows how to globally override the 'useUnmergedTree' setting in Compose UI tests using KakaoComposeTestRule. Setting 'useUnmergedTree' to true can prevent the framework from squashing views, which is often desirable for accurate testing. ```kotlin val composeTestRule = createAndroidComposeRule() val kakaoComposeTestRule = KakaoComposeTestRule( semanticsProvider = composeTestRule, useUnmergedTree = true ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.