Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions catalog/src/main/assets/component_text_fields.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,59 @@
]
}
]
},
{
"linkId": "6",
"type": "text",
"item": [
{
"linkId": "6.1",
"text": "Enter text (multiline)",
"type": "display",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
"valueCodeableConcept": {
"coding": [
{
"system": "http://hl7.org/fhir/questionnaire-item-control",
"code": "flyover",
"display": "Fly-over"
}
],
"text": "Flyover"
}
}
]
}
]
},
{
"linkId": "7",
"type": "string",
"readOnly": true,
"item": [
{
"linkId": "7.1",
"text": "Enter a string (readonly)",
"type": "display",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl",
"valueCodeableConcept": {
"coding": [
{
"system": "http://hl7.org/fhir/questionnaire-item-control",
"code": "flyover",
"display": "Fly-over"
}
],
"text": "Flyover"
}
}
]
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023-2024 Google LLC
* Copyright 2023-2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,7 +19,15 @@ package com.google.android.fhir.datacapture.contrib.views
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import androidx.test.annotation.UiThreadTest
import androidx.compose.ui.test.IdlingResource
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.junit4.createEmptyComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performTextReplacement
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
Expand All @@ -30,42 +38,54 @@ import com.google.android.fhir.datacapture.test.TestActivity
import com.google.android.fhir.datacapture.validation.Invalid
import com.google.android.fhir.datacapture.validation.NotValidated
import com.google.android.fhir.datacapture.views.QuestionnaireViewItem
import com.google.android.fhir.datacapture.views.compose.EDIT_TEXT_FIELD_TEST_TAG
import com.google.android.fhir.datacapture.views.factories.QuestionnaireItemViewHolder
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.common.truth.Truth.assertThat
import org.hl7.fhir.r4.model.IntegerType
import org.hl7.fhir.r4.model.Questionnaire
import org.hl7.fhir.r4.model.QuestionnaireResponse
import org.hl7.fhir.r4.model.StringType
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class PhoneNumberViewHolderFactoryInstrumentedTest {

@Rule
@JvmField
var activityScenarioRule: ActivityScenarioRule<TestActivity> =
@get:Rule
val activityScenarioRule: ActivityScenarioRule<TestActivity> =
ActivityScenarioRule(TestActivity::class.java)

@get:Rule val composeTestRule = createEmptyComposeRule()

private lateinit var parent: FrameLayout
private lateinit var viewHolder: QuestionnaireItemViewHolder
private lateinit var questionnaireEditAdapter: QuestionnaireEditAdapter

private var pendingTextChange = 0
private val handlingTextIdlingResource =
object : IdlingResource {
override val isIdleNow: Boolean
get() = pendingTextChange == 0
}

@Before
fun setUp() {
activityScenarioRule.scenario.onActivity { activity -> parent = FrameLayout(activity) }
viewHolder = PhoneNumberViewHolderFactory.create(parent)
setTestLayout(viewHolder.itemView)
questionnaireEditAdapter = QuestionnaireEditAdapter()
composeTestRule.registerIdlingResource(handlingTextIdlingResource)
}

@After
fun tearDown() {
composeTestRule.unregisterIdlingResource(handlingTextIdlingResource)
}

@Test
fun createViewHolder_phoneNumberViewHolderFactory_returnsViewHolder() {
val questionnaireEditAdapter = QuestionnaireEditAdapter()
val viewHolderFromAdapter =
questionnaireEditAdapter.createViewHolder(
parent,
Expand All @@ -75,16 +95,14 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
)
.viewType,
) as QuestionnaireEditAdapter.ViewHolder.QuestionHolder

assertThat(
viewHolderFromAdapter.holder.itemView
.findViewById<TextInputEditText>(R.id.text_input_edit_text)
.visibility,
viewHolderFromAdapter.holder.itemView.visibility,
)
.isEqualTo(View.VISIBLE)
}

@Test
@UiThreadTest
fun shouldSetTextViewText() {
viewHolder.bind(
QuestionnaireViewItem(
Expand All @@ -94,13 +112,14 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
answersChangedCallback = { _, _, _, _ -> },
),
)
// Synchronize
composeTestRule.waitForIdle()

assertThat(viewHolder.itemView.findViewById<TextView>(R.id.question).text.toString())
.isEqualTo("Question?")
}

@Test
@UiThreadTest
fun shouldSetInputText() {
viewHolder.bind(
QuestionnaireViewItem(
Expand All @@ -116,17 +135,10 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
),
)

assertThat(
viewHolder.itemView
.findViewById<TextInputEditText>(R.id.text_input_edit_text)
.text
.toString(),
)
.isEqualTo("+12345678910")
composeTestRule.onNodeWithTag(EDIT_TEXT_FIELD_TEST_TAG).assertTextEquals("+12345678910")
}

@Test
@UiThreadTest
fun shouldSetInputTextToEmpty() {
viewHolder.bind(
QuestionnaireViewItem(
Expand All @@ -150,36 +162,33 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
),
)

assertThat(
viewHolder.itemView
.findViewById<TextInputEditText>(R.id.text_input_edit_text)
.text
.toString(),
)
.isEqualTo("")
composeTestRule.onNodeWithTag(EDIT_TEXT_FIELD_TEST_TAG).assertTextEquals("")
}

@Test
@UiThreadTest
@Ignore("https://github.com/google/android-fhir/issues/1494")
fun shouldSetQuestionnaireResponseItemAnswer() {
var answers: List<QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent> = emptyList()
val questionnaireViewItem =
QuestionnaireViewItem(
Questionnaire.QuestionnaireItemComponent(),
QuestionnaireResponse.QuestionnaireResponseItemComponent(),
validationResult = NotValidated,
answersChangedCallback = { _, _, _, _ -> },
answersChangedCallback = { _, _, newAnswers, _ ->
answers = newAnswers
pendingTextChange -= if (pendingTextChange > 0) 1 else 0
},
)
viewHolder.bind(questionnaireViewItem)
viewHolder.itemView
.findViewById<TextInputEditText>(R.id.text_input_edit_text)
.setText("+12345678910")
assertThat(questionnaireViewItem.answers.single().valueStringType.value)
.isEqualTo("+12345678910")
composeTestRule
.onNodeWithTag(EDIT_TEXT_FIELD_TEST_TAG)
.performTextReplacement("+12345678910")
.also { pendingTextChange += 1 }

composeTestRule.waitForIdle()
assertThat(answers.single().valueStringType.value).isEqualTo("+12345678910")
}

@Test
@UiThreadTest
fun shouldSetQuestionnaireResponseItemAnswerToEmpty() {
val questionnaireViewItem =
QuestionnaireViewItem(
Expand All @@ -190,13 +199,12 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
)

viewHolder.bind(questionnaireViewItem)
viewHolder.itemView.findViewById<TextInputEditText>(R.id.text_input_edit_text).setText("")
composeTestRule.onNodeWithTag(EDIT_TEXT_FIELD_TEST_TAG).performTextReplacement("")

assertThat(questionnaireViewItem.answers).isEmpty()
}

@Test
@UiThreadTest
fun displayValidationResult_noError_shouldShowNoErrorMessage() {
viewHolder.bind(
QuestionnaireViewItem(
Expand All @@ -218,12 +226,10 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
),
)

assertThat(viewHolder.itemView.findViewById<TextInputLayout>(R.id.text_input_layout).error)
.isNull()
composeTestRule.onNodeWithContentDescription("Error").assertDoesNotExist()
}

@Test
@UiThreadTest
fun displayValidationResult_error_shouldShowErrorMessage() {
viewHolder.bind(
QuestionnaireViewItem(
Expand All @@ -242,12 +248,14 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
answersChangedCallback = { _, _, _, _ -> },
),
)
assertThat(viewHolder.itemView.findViewById<TextInputLayout>(R.id.text_input_layout).error)
.isEqualTo("The maximum number of characters that are permitted in the answer is: 10")

composeTestRule.onNodeWithContentDescription("Error").assertIsDisplayed()
composeTestRule
.onNodeWithText("The maximum number of characters that are permitted in the answer is: 10")
.assertIsDisplayed()
}

@Test
@UiThreadTest
fun bind_readOnly_shouldDisableView() {
viewHolder.bind(
QuestionnaireViewItem(
Expand All @@ -257,11 +265,7 @@ class PhoneNumberViewHolderFactoryInstrumentedTest {
answersChangedCallback = { _, _, _, _ -> },
),
)

assertThat(
viewHolder.itemView.findViewById<TextInputEditText>(R.id.text_input_edit_text).isEnabled,
)
.isFalse()
composeTestRule.onNodeWithTag(EDIT_TEXT_FIELD_TEST_TAG).assertIsNotEnabled()
}

/** Method to set content view for test activity */
Expand Down
Loading
Loading