11/*
2- * Copyright 2023 Google LLC
2+ * Copyright 2025 Google LLC
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1414 * limitations under the License.
1515 */
1616
17- package com.google.android.fhir.datacapture.views.factories
17+ package com.google.android.fhir.datacapture.test.views
1818
19- import android.view.View
20- import android.widget.AutoCompleteTextView
2119import android.widget.FrameLayout
22- import android.widget.TextView
23- import androidx.test.espresso.Espresso.onView
24- import androidx.test.espresso.action.ViewActions
25- import androidx.test.espresso.assertion.ViewAssertions
26- import androidx.test.espresso.matcher.RootMatchers
27- import androidx.test.espresso.matcher.ViewMatchers
20+ import androidx.compose.ui.test.assertCountEquals
21+ import androidx.compose.ui.test.assertIsDisplayed
22+ import androidx.compose.ui.test.assertTextEquals
23+ import androidx.compose.ui.test.hasAnyAncestor
24+ import androidx.compose.ui.test.hasTestTag
25+ import androidx.compose.ui.test.hasTextExactly
26+ import androidx.compose.ui.test.isPopup
27+ import androidx.compose.ui.test.junit4.createEmptyComposeRule
28+ import androidx.compose.ui.test.onNodeWithTag
29+ import androidx.compose.ui.test.performClick
30+ import androidx.compose.ui.test.performTextReplacement
2831import androidx.test.ext.junit.rules.ActivityScenarioRule
2932import androidx.test.platform.app.InstrumentationRegistry
30- import com.google.android.fhir.datacapture.R
3133import com.google.android.fhir.datacapture.test.TestActivity
32- import com.google.android.fhir.datacapture.test.utilities.delayMainThread
3334import com.google.android.fhir.datacapture.validation.NotValidated
3435import com.google.android.fhir.datacapture.views.QuestionnaireViewItem
35- import com.google.android.material.chip.ChipGroup
36- import com.google.android.material.textfield.MaterialAutoCompleteTextView
36+ import com.google.android.fhir.datacapture.views.compose.DROP_DOWN_ANSWER_MENU_ITEM_TAG
37+ import com.google.android.fhir.datacapture.views.compose.MULTI_AUTO_COMPLETE_INPUT_CHIP_TAG
38+ import com.google.android.fhir.datacapture.views.compose.MULTI_AUTO_COMPLETE_TEXT_FIELD_TAG
39+ import com.google.android.fhir.datacapture.views.factories.AutoCompleteViewHolderFactory
40+ import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolder
3741import com.google.common.truth.Truth.assertThat
3842import org.hl7.fhir.r4.model.Coding
3943import org.hl7.fhir.r4.model.Questionnaire
@@ -43,19 +47,22 @@ import org.junit.Rule
4347import org.junit.Test
4448
4549class AutoCompleteViewHolderFactoryEspressoTest {
46- @Rule
47- @JvmField
50+ @get:Rule
4851 var activityScenarioRule: ActivityScenarioRule <TestActivity > =
4952 ActivityScenarioRule (TestActivity ::class .java)
5053
51- private lateinit var parent: FrameLayout
54+ @get:Rule val composeTestRule = createEmptyComposeRule()
55+
5256 private lateinit var viewHolder: QuestionnaireItemViewHolder
5357
5458 @Before
5559 fun setup () {
56- activityScenarioRule.scenario.onActivity { activity -> parent = FrameLayout (activity) }
57- viewHolder = AutoCompleteViewHolderFactory .create(parent)
58- setTestLayout(viewHolder.itemView)
60+ activityScenarioRule.scenario.onActivity { activity ->
61+ viewHolder = AutoCompleteViewHolderFactory .create(FrameLayout (activity))
62+ activity.setContentView(viewHolder.itemView)
63+ }
64+
65+ InstrumentationRegistry .getInstrumentation().waitForIdleSync()
5966 }
6067
6168 @Test
@@ -67,16 +74,11 @@ class AutoCompleteViewHolderFactoryEspressoTest {
6774 validationResult = NotValidated ,
6875 answersChangedCallback = { _, _, _, _ -> },
6976 )
70- runOnUI { viewHolder.bind(questionnaireViewItem) }
71-
72- onView(ViewMatchers .withId(R .id.autoCompleteTextView)).perform(ViewActions .typeText(" Coding 1" ))
73- assertThat(
74- viewHolder.itemView
75- .findViewById<MaterialAutoCompleteTextView >(R .id.autoCompleteTextView)
76- .adapter
77- .count,
78- )
79- .isEqualTo(1 )
77+ viewHolder.bind(questionnaireViewItem)
78+ composeTestRule
79+ .onNodeWithTag(MULTI_AUTO_COMPLETE_TEXT_FIELD_TAG )
80+ .performTextReplacement(" Coding 1" )
81+ composeTestRule.onAllNodes(hasTestTag(DROP_DOWN_ANSWER_MENU_ITEM_TAG )).assertCountEquals(1 )
8082 }
8183
8284 @Test
@@ -89,23 +91,24 @@ class AutoCompleteViewHolderFactoryEspressoTest {
8991 validationResult = NotValidated ,
9092 answersChangedCallback = { _, _, answers, _ -> answerHolder = answers },
9193 )
92- runOnUI { viewHolder.bind(questionnaireViewItem) }
94+ viewHolder.bind(questionnaireViewItem)
9395
94- onView(ViewMatchers .withId(R .id.autoCompleteTextView)).perform(ViewActions .typeText(" Coding 3" ))
95- runOnUI {
96- viewHolder.itemView
97- .findViewById<AutoCompleteTextView >(R .id.autoCompleteTextView)
98- .showDropDown()
99- }
100- onView(ViewMatchers .withId(R .id.autoCompleteTextView)).perform(delayMainThread())
101- onView(ViewMatchers .withText(" Coding 3" ))
102- .inRoot(RootMatchers .isPlatformPopup())
103- .check(ViewAssertions .matches(ViewMatchers .isDisplayed()))
104- .perform(ViewActions .click())
105- assertThat(
106- viewHolder.itemView.findViewById<TextView >(R .id.autoCompleteTextView).text.toString(),
96+ composeTestRule
97+ .onNodeWithTag(MULTI_AUTO_COMPLETE_TEXT_FIELD_TAG )
98+ .performTextReplacement(" Coding 3" )
99+
100+ composeTestRule
101+ .onNode(
102+ hasTestTag(DROP_DOWN_ANSWER_MENU_ITEM_TAG ) and
103+ hasTextExactly(" Coding 3" ) and
104+ hasAnyAncestor(isPopup()),
107105 )
108- .isEmpty()
106+ .assertIsDisplayed()
107+ .performClick()
108+
109+ composeTestRule.onNodeWithTag(MULTI_AUTO_COMPLETE_TEXT_FIELD_TAG ).assertTextEquals(" " )
110+
111+ composeTestRule.waitUntil { answerHolder != null }
109112 assertThat(answerHolder!! .map { it.valueCoding.display })
110113 .containsExactly(" Coding 1" , " Coding 5" , " Coding 3" )
111114 }
@@ -119,21 +122,8 @@ class AutoCompleteViewHolderFactoryEspressoTest {
119122 validationResult = NotValidated ,
120123 answersChangedCallback = { _, _, _, _ -> },
121124 )
122- runOnUI { viewHolder.bind(questionnaireViewItem) }
123-
124- assertThat(viewHolder.itemView.findViewById<ChipGroup >(R .id.chipContainer).childCount)
125- .isEqualTo(2 )
126- }
127-
128- /* * Method to run code snippet on UI/main thread */
129- private fun runOnUI (action : () -> Unit ) {
130- activityScenarioRule.scenario.onActivity { action() }
131- }
132-
133- /* * Method to set content view for test activity */
134- private fun setTestLayout (view : View ) {
135- activityScenarioRule.scenario.onActivity { activity -> activity.setContentView(view) }
136- InstrumentationRegistry .getInstrumentation().waitForIdleSync()
125+ viewHolder.bind(questionnaireViewItem)
126+ composeTestRule.onAllNodes(hasTestTag(MULTI_AUTO_COMPLETE_INPUT_CHIP_TAG )).assertCountEquals(2 )
137127 }
138128
139129 private fun answerOptions (repeats : Boolean , vararg options : String ) =
0 commit comments