From 9954d2db516e0980a0f65cb1f41e43b40856a2ae Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Tue, 4 Mar 2025 14:38:52 +0530 Subject: [PATCH 1/9] Fixed to prevent checkbox crashes#2661 --- catalog/src/main/assets/component_multi_select_choice.json | 2 +- .../views/factories/CheckBoxGroupViewHolderFactory.kt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/catalog/src/main/assets/component_multi_select_choice.json b/catalog/src/main/assets/component_multi_select_choice.json index 8e5a72c3e2..ae13fde946 100644 --- a/catalog/src/main/assets/component_multi_select_choice.json +++ b/catalog/src/main/assets/component_multi_select_choice.json @@ -8,7 +8,7 @@ "linkId": "1.0.0", "text": "What’s the reason for today’s visit?", "type": "choice", - "repeats": true, + "repeats": false, "extension": [ { "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactory.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactory.kt index 179eb7da79..1b50873c1b 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactory.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactory.kt @@ -127,6 +127,9 @@ internal object CheckBoxGroupViewHolderFactory : val newAnswers = questionnaireViewItem.answers.toMutableList() newAnswers += QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { + if(!questionnaireViewItem.questionnaireItem.repeats){ + newAnswers.clear() + } value = answerOption.value } From 5ba34f36a1de3fd4017814b3116a8696371e287d Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Mon, 10 Mar 2025 15:07:22 +0530 Subject: [PATCH 2/9] Fixed to prevent checkbox crashes#2661 --- catalog/src/main/AndroidManifest.xml | 1 + .../CheckBoxGroupViewHolderFactory.kt | 6 +- .../CheckBoxGroupViewHolderFactoryTest.kt | 322 ++++++++++++++++++ 3 files changed, 326 insertions(+), 3 deletions(-) diff --git a/catalog/src/main/AndroidManifest.xml b/catalog/src/main/AndroidManifest.xml index 17469a9339..1737407e1a 100644 --- a/catalog/src/main/AndroidManifest.xml +++ b/catalog/src/main/AndroidManifest.xml @@ -31,6 +31,7 @@ android:roundIcon="@mipmap/ic_card_file_box_round" android:supportsRtl="true" android:theme="@style/Theme.Androidfhir" + android:usesCleartextTraffic="true" > { val newAnswers = questionnaireViewItem.answers.toMutableList() + if(!questionnaireViewItem.questionnaireItem.repeats){ + newAnswers.clear() + } newAnswers += QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { - if(!questionnaireViewItem.questionnaireItem.repeats){ - newAnswers.clear() - } value = answerOption.value } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt index f5f361cc87..5919696b4d 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt @@ -616,4 +616,326 @@ class CheckBoxGroupViewHolderFactoryTest { }, ) } + + @Test + fun bind_shouldSetQuestionHeader_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + text = "Question?" + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + assertThat(viewHolder.itemView.findViewById(R.id.question).text.toString()).isEqualTo("Question?") + } + + @Test + fun bind_horizontal_shouldCreateCheckBoxButtons_whenRepeatFalse() { + val questionnaire = + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addExtension( + EXTENSION_CHOICE_ORIENTATION_URL, + CodeType(ChoiceOrientationTypes.HORIZONTAL.extensionCode), + ) + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = Coding().apply { display = "Coding 1" } + }, + ) + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = Coding().apply { display = "Coding 2" } + }, + ) + } + viewHolder.bind( + QuestionnaireViewItem( + questionnaire, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + val children = checkBoxGroup.children.asIterable().filterIsInstance() + children.forEachIndexed { index, view -> + assertThat(view.text.toString()).isEqualTo(questionnaire.answerOption[index].valueCoding.display) + assertThat(view.layoutParams.width).isEqualTo(ViewGroup.LayoutParams.WRAP_CONTENT) + } + } + + @Test + fun bind_noAnswer_shouldLeaveCheckButtonsUnchecked_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = Coding().apply { display = "Coding 1" } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + val checkBox = checkBoxGroup.getChildAt(1) as CheckBox + assertThat(checkBox.isChecked).isFalse() // Ensure checkbox is unchecked when no answer is selected + } + + @Test + fun bind_withImageInItemAnswerMediaExtension_shouldShowImageAfterCheckBox_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + extension = listOf(itemAnswerMediaExtension) + value = StringType("Test Code") + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + val checkBox = checkBoxGroup.getChildAt(1) as CheckBox + assertThat(checkBox.compoundDrawablesRelative[0]).isNotNull() + assertThat(checkBox.compoundDrawablesRelative[1]).isNull() + assertThat(checkBox.compoundDrawablesRelative[2]).isNull() + assertThat(checkBox.compoundDrawablesRelative[3]).isNull() + } + + @Test + fun bind_answer_shouldSetCheckBoxButton_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = + Coding().apply { + code = "code 1" + display = "Coding 1" + } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { + addAnswer( + QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { + value = + Coding().apply { + code = "code 1" + display = "Coding 1" + } + }, + ) + }, + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + val checkBox = checkBoxGroup.getChildAt(1) as CheckBox + + assertThat(checkBox.isChecked).isTrue() + } + + @Test + fun click_shouldAddQuestionnaireResponseItemAnswer_whenRepeatFalse() { + var answerHolder: List? = null + val questionnaireViewItem = + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = + Coding().apply { + code = "code 1" + display = "Coding 1" + } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, answers, _ -> answerHolder = answers }, + ) + viewHolder.bind(questionnaireViewItem) + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + val checkBox = checkBoxGroup.getChildAt(1) as CheckBox + checkBox.performClick() + + assertThat(answerHolder!!.single().valueCoding.display).isEqualTo("Coding 1") + } + + @Test + fun optionExclusiveAnswerOption_click_deselectsOtherAnswerOptions_whenRepeatFalse() { + var answerHolder: List? = null + val questionnaireViewItem = + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = + Coding().apply { + code = "code-1" + display = "display-1" + } + }, + ) + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = + Coding().apply { + code = "code-2" + display = "display-2" + } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, answers, _ -> answerHolder = answers }, + ) + viewHolder.bind(questionnaireViewItem) + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + (checkBoxGroup.getChildAt(2) as CheckBox).performClick() + (checkBoxGroup.getChildAt(1) as CheckBox).performClick() + + assertThat(answerHolder!!.single().valueCoding.display).isEqualTo("display-1") + } + + @Test + fun answerOption_click_deselectsOptionExclusiveAnswerOption_whenRepeatFalse() { + var answerHolder: List? = null + val questionnaireViewItem = + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = + Coding().apply { + code = "code-1" + display = "display-1" + } + }, + ) + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = + Coding().apply { + code = "code-2" + display = "display-2" + } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, answers, _ -> answerHolder = answers }, + ) + + viewHolder.bind(questionnaireViewItem) + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + (checkBoxGroup.getChildAt(1) as CheckBox).performClick() + (checkBoxGroup.getChildAt(2) as CheckBox).performClick() + + assertThat(answerHolder!!.single().valueCoding.display).isEqualTo("display-2") + } + + @Test + fun displayValidationResult_error_shouldShowErrorMessage_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + required = true + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = Invalid(listOf("Missing answer for required field.")), + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + + assertThat(viewHolder.itemView.findViewById(R.id.error_text_at_header).text) + .isEqualTo("Missing answer for required field.") + } + + @Test + fun displayValidationResult_noError_shouldShowNoErrorMessage_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + required = true + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = Coding().apply { display = "display" } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { + addAnswer( + QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { + value = Coding().apply { display = "display" } + }, + ) + }, + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + + assertThat(viewHolder.itemView.findViewById(R.id.error_text_at_header).text.isEmpty()) + .isTrue() + } + + @Test + fun bind_readOnly_shouldDisableView_whenRepeatFalse() { + viewHolder.bind( + QuestionnaireViewItem( + Questionnaire.QuestionnaireItemComponent().apply { + repeats = false + readOnly = true + addAnswerOption( + Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { + value = Coding().apply { display = "Coding 1" } + }, + ) + }, + QuestionnaireResponse.QuestionnaireResponseItemComponent(), + validationResult = NotValidated, + answersChangedCallback = { _, _, _, _ -> }, + ), + ) + + assertThat( + (viewHolder.itemView.findViewById(R.id.checkbox_group).getChildAt(1) + as CheckBox) + .isEnabled, + ) + .isFalse() + } + + } From b5cb07385f788ef11cabb1363645af0b87e23744 Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Tue, 11 Mar 2025 15:02:54 +0530 Subject: [PATCH 3/9] SpotlessApply --- catalog/src/main/AndroidManifest.xml | 1 - .../CheckBoxGroupViewHolderFactory.kt | 4 ++-- .../CheckBoxGroupViewHolderFactoryTest.kt | 21 ++++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/catalog/src/main/AndroidManifest.xml b/catalog/src/main/AndroidManifest.xml index 1737407e1a..17469a9339 100644 --- a/catalog/src/main/AndroidManifest.xml +++ b/catalog/src/main/AndroidManifest.xml @@ -31,7 +31,6 @@ android:roundIcon="@mipmap/ic_card_file_box_round" android:supportsRtl="true" android:theme="@style/Theme.Androidfhir" - android:usesCleartextTraffic="true" > { val newAnswers = questionnaireViewItem.answers.toMutableList() - if(!questionnaireViewItem.questionnaireItem.repeats){ + if (!questionnaireViewItem.questionnaireItem.repeats) { newAnswers.clear() } newAnswers += diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt index 5919696b4d..9a6dd32a97 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt @@ -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. @@ -630,7 +630,8 @@ class CheckBoxGroupViewHolderFactoryTest { answersChangedCallback = { _, _, _, _ -> }, ), ) - assertThat(viewHolder.itemView.findViewById(R.id.question).text.toString()).isEqualTo("Question?") + assertThat(viewHolder.itemView.findViewById(R.id.question).text.toString()) + .isEqualTo("Question?") } @Test @@ -665,7 +666,8 @@ class CheckBoxGroupViewHolderFactoryTest { val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) val children = checkBoxGroup.children.asIterable().filterIsInstance() children.forEachIndexed { index, view -> - assertThat(view.text.toString()).isEqualTo(questionnaire.answerOption[index].valueCoding.display) + assertThat(view.text.toString()) + .isEqualTo(questionnaire.answerOption[index].valueCoding.display) assertThat(view.layoutParams.width).isEqualTo(ViewGroup.LayoutParams.WRAP_CONTENT) } } @@ -690,7 +692,8 @@ class CheckBoxGroupViewHolderFactoryTest { val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) val checkBox = checkBoxGroup.getChildAt(1) as CheckBox - assertThat(checkBox.isChecked).isFalse() // Ensure checkbox is unchecked when no answer is selected + assertThat(checkBox.isChecked) + .isFalse() // Ensure checkbox is unchecked when no answer is selected } @Test @@ -930,12 +933,10 @@ class CheckBoxGroupViewHolderFactoryTest { ) assertThat( - (viewHolder.itemView.findViewById(R.id.checkbox_group).getChildAt(1) - as CheckBox) - .isEnabled, - ) + (viewHolder.itemView.findViewById(R.id.checkbox_group).getChildAt(1) + as CheckBox) + .isEnabled, + ) .isFalse() } - - } From 1519577744ad71cb880f75ec74913c6d5bdec7a7 Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Wed, 12 Mar 2025 16:20:55 +0530 Subject: [PATCH 4/9] set repeat value true --- catalog/src/main/assets/component_multi_select_choice.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/catalog/src/main/assets/component_multi_select_choice.json b/catalog/src/main/assets/component_multi_select_choice.json index ae13fde946..8e5a72c3e2 100644 --- a/catalog/src/main/assets/component_multi_select_choice.json +++ b/catalog/src/main/assets/component_multi_select_choice.json @@ -8,7 +8,7 @@ "linkId": "1.0.0", "text": "What’s the reason for today’s visit?", "type": "choice", - "repeats": false, + "repeats": true, "extension": [ { "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", From 2cff3e350f8a9ebd8fa64cd2279e86bf208b6c71 Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Thu, 20 Mar 2025 14:02:49 +0530 Subject: [PATCH 5/9] FHIR questionnaire attachment item shows as 'not answered' in review mode #2790 --- .../google/android/fhir/catalog/DemoQuestionnaireFragment.kt | 3 +++ .../android/fhir/datacapture/views/QuestionnaireViewItem.kt | 1 + datacapture/src/main/res/values/strings.xml | 1 + 3 files changed, 5 insertions(+) diff --git a/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt b/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt index c672e79136..a16e7aeccb 100644 --- a/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt +++ b/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt @@ -146,6 +146,9 @@ class DemoQuestionnaireFragment : Fragment() { .LOCATION_WIDGET_PROVIDER, ) setQuestionnaire(args.questionnaireJsonStringKey!!) + if (args.questionnaireTitleKey == "Attachment") { + showReviewPageBeforeSubmit(true) + } } .build() add(R.id.container, questionnaireFragment, QUESTIONNAIRE_FRAGMENT_TAG) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt index d9025fd284..281540d841 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt @@ -196,6 +196,7 @@ data class QuestionnaireViewItem( */ fun answerString(context: Context): String { if (!questionnaireResponseItem.hasAnswer()) return context.getString(R.string.not_answered) + else if (questionnaireItem.type==Questionnaire.QuestionnaireItemType.ATTACHMENT) return context.getString(R.string.answered) return questionnaireResponseItem.answer.joinToString { it.value.displayString(context) } } diff --git a/datacapture/src/main/res/values/strings.xml b/datacapture/src/main/res/values/strings.xml index 79fa579348..2544100052 100644 --- a/datacapture/src/main/res/values/strings.xml +++ b/datacapture/src/main/res/values/strings.xml @@ -36,6 +36,7 @@ "Not Answered" + "Answered" Help From c3eef165537a4202463369cbaf9aa14b56cd3c38 Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Thu, 20 Mar 2025 14:16:36 +0530 Subject: [PATCH 6/9] CHeckbox Crashes #2661 --- .../CheckBoxGroupViewHolderFactoryTest.kt | 305 ++---------------- 1 file changed, 27 insertions(+), 278 deletions(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt index 9a6dd32a97..25d510ab12 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt @@ -617,136 +617,37 @@ class CheckBoxGroupViewHolderFactoryTest { ) } - @Test - fun bind_shouldSetQuestionHeader_whenRepeatFalse() { - viewHolder.bind( - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - text = "Question?" - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - assertThat(viewHolder.itemView.findViewById(R.id.question).text.toString()) - .isEqualTo("Question?") - } - - @Test - fun bind_horizontal_shouldCreateCheckBoxButtons_whenRepeatFalse() { - val questionnaire = - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - addExtension( - EXTENSION_CHOICE_ORIENTATION_URL, - CodeType(ChoiceOrientationTypes.HORIZONTAL.extensionCode), - ) - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { display = "Coding 1" } - }, - ) - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { display = "Coding 2" } - }, - ) - } - viewHolder.bind( - QuestionnaireViewItem( - questionnaire, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - val children = checkBoxGroup.children.asIterable().filterIsInstance() - children.forEachIndexed { index, view -> - assertThat(view.text.toString()) - .isEqualTo(questionnaire.answerOption[index].valueCoding.display) - assertThat(view.layoutParams.width).isEqualTo(ViewGroup.LayoutParams.WRAP_CONTENT) - } - } @Test - fun bind_noAnswer_shouldLeaveCheckButtonsUnchecked_whenRepeatFalse() { + fun click_should_Select_Other_CheckboxButton() { viewHolder.bind( QuestionnaireViewItem( Questionnaire.QuestionnaireItemComponent().apply { repeats = false addAnswerOption( Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { display = "Coding 1" } - }, - ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - val checkBox = checkBoxGroup.getChildAt(1) as CheckBox - assertThat(checkBox.isChecked) - .isFalse() // Ensure checkbox is unchecked when no answer is selected - } - - @Test - fun bind_withImageInItemAnswerMediaExtension_shouldShowImageAfterCheckBox_whenRepeatFalse() { - viewHolder.bind( - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - extension = listOf(itemAnswerMediaExtension) - value = StringType("Test Code") + value = Coding().apply { + code = "code-1" + display = "display-1" + } }, ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - val checkBox = checkBoxGroup.getChildAt(1) as CheckBox - assertThat(checkBox.compoundDrawablesRelative[0]).isNotNull() - assertThat(checkBox.compoundDrawablesRelative[1]).isNull() - assertThat(checkBox.compoundDrawablesRelative[2]).isNull() - assertThat(checkBox.compoundDrawablesRelative[3]).isNull() - } - - @Test - fun bind_answer_shouldSetCheckBoxButton_whenRepeatFalse() { - viewHolder.bind( - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false addAnswerOption( Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code 1" - display = "Coding 1" - } + value = Coding().apply { + code = "code-2" + display = "display-2" + } }, ) }, QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { addAnswer( QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { - value = - Coding().apply { - code = "code 1" - display = "Coding 1" - } + value = Coding().apply { + code = "code-1" + display = "display-1" + } }, ) }, @@ -754,189 +655,37 @@ class CheckBoxGroupViewHolderFactoryTest { answersChangedCallback = { _, _, _, _ -> }, ), ) - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - val checkBox = checkBoxGroup.getChildAt(1) as CheckBox - assertThat(checkBox.isChecked).isTrue() - } - - @Test - fun click_shouldAddQuestionnaireResponseItemAnswer_whenRepeatFalse() { - var answerHolder: List? = null - val questionnaireViewItem = - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code 1" - display = "Coding 1" - } - }, - ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, answers, _ -> answerHolder = answers }, - ) - viewHolder.bind(questionnaireViewItem) val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - val checkBox = checkBoxGroup.getChildAt(1) as CheckBox - checkBox.performClick() - - assertThat(answerHolder!!.single().valueCoding.display).isEqualTo("Coding 1") - } - - @Test - fun optionExclusiveAnswerOption_click_deselectsOtherAnswerOptions_whenRepeatFalse() { - var answerHolder: List? = null - val questionnaireViewItem = - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code-1" - display = "display-1" - } - }, - ) - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code-2" - display = "display-2" - } - }, - ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, answers, _ -> answerHolder = answers }, - ) - viewHolder.bind(questionnaireViewItem) - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - (checkBoxGroup.getChildAt(2) as CheckBox).performClick() - (checkBoxGroup.getChildAt(1) as CheckBox).performClick() - - assertThat(answerHolder!!.single().valueCoding.display).isEqualTo("display-1") - } - - @Test - fun answerOption_click_deselectsOptionExclusiveAnswerOption_whenRepeatFalse() { - var answerHolder: List? = null - val questionnaireViewItem = - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code-1" - display = "display-1" - } - }, - ) - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code-2" - display = "display-2" - } - }, - ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, answers, _ -> answerHolder = answers }, - ) - - viewHolder.bind(questionnaireViewItem) - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - (checkBoxGroup.getChildAt(1) as CheckBox).performClick() - (checkBoxGroup.getChildAt(2) as CheckBox).performClick() - - assertThat(answerHolder!!.single().valueCoding.display).isEqualTo("display-2") - } - - @Test - fun displayValidationResult_error_shouldShowErrorMessage_whenRepeatFalse() { - viewHolder.bind( - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - required = true - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = Invalid(listOf("Missing answer for required field.")), - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - - assertThat(viewHolder.itemView.findViewById(R.id.error_text_at_header).text) - .isEqualTo("Missing answer for required field.") + assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked,).isTrue() + checkBoxGroup.getChildAt(2).performClick() + assertThat((checkBoxGroup.getChildAt(2) as CheckBox).isChecked,).isTrue() } @Test - fun displayValidationResult_noError_shouldShowNoErrorMessage_whenRepeatFalse() { + fun click_Selected_CheckboxButton_Should_Uncheck_CheckboxButton() { viewHolder.bind( QuestionnaireViewItem( Questionnaire.QuestionnaireItemComponent().apply { repeats = false - required = true addAnswerOption( Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { display = "display" } - }, - ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { - addAnswer( - QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { - value = Coding().apply { display = "display" } - }, - ) - }, - validationResult = NotValidated, - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - - assertThat(viewHolder.itemView.findViewById(R.id.error_text_at_header).text.isEmpty()) - .isTrue() - } - - @Test - fun bind_readOnly_shouldDisableView_whenRepeatFalse() { - viewHolder.bind( - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - readOnly = true - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { display = "Coding 1" } + value = Coding().apply { + code = "code-1" + display = "display-1" + } }, ) }, QuestionnaireResponse.QuestionnaireResponseItemComponent(), validationResult = NotValidated, answersChangedCallback = { _, _, _, _ -> }, - ), - ) + )) - assertThat( - (viewHolder.itemView.findViewById(R.id.checkbox_group).getChildAt(1) - as CheckBox) - .isEnabled, - ) - .isFalse() + val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) + checkBoxGroup.getChildAt(1).performClick() + assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked).isTrue() + checkBoxGroup.getChildAt(1).performClick() + assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked).isFalse() } } From 2a9914032d160081578f4b176a62800ffffc012f Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Thu, 20 Mar 2025 16:26:56 +0530 Subject: [PATCH 7/9] seprated 2790 issue --- .../google/android/fhir/catalog/DemoQuestionnaireFragment.kt | 3 --- .../android/fhir/datacapture/views/QuestionnaireViewItem.kt | 1 - datacapture/src/main/res/values/strings.xml | 1 - 3 files changed, 5 deletions(-) diff --git a/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt b/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt index a16e7aeccb..c672e79136 100644 --- a/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt +++ b/catalog/src/main/java/com/google/android/fhir/catalog/DemoQuestionnaireFragment.kt @@ -146,9 +146,6 @@ class DemoQuestionnaireFragment : Fragment() { .LOCATION_WIDGET_PROVIDER, ) setQuestionnaire(args.questionnaireJsonStringKey!!) - if (args.questionnaireTitleKey == "Attachment") { - showReviewPageBeforeSubmit(true) - } } .build() add(R.id.container, questionnaireFragment, QUESTIONNAIRE_FRAGMENT_TAG) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt index 281540d841..d9025fd284 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireViewItem.kt @@ -196,7 +196,6 @@ data class QuestionnaireViewItem( */ fun answerString(context: Context): String { if (!questionnaireResponseItem.hasAnswer()) return context.getString(R.string.not_answered) - else if (questionnaireItem.type==Questionnaire.QuestionnaireItemType.ATTACHMENT) return context.getString(R.string.answered) return questionnaireResponseItem.answer.joinToString { it.value.displayString(context) } } diff --git a/datacapture/src/main/res/values/strings.xml b/datacapture/src/main/res/values/strings.xml index 2544100052..79fa579348 100644 --- a/datacapture/src/main/res/values/strings.xml +++ b/datacapture/src/main/res/values/strings.xml @@ -36,7 +36,6 @@ "Not Answered" - "Answered" Help From 999ab1baa1ff57477c12115d8cb909f3005f3882 Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Thu, 20 Mar 2025 17:02:40 +0530 Subject: [PATCH 8/9] file updated --- .../CheckBoxGroupViewHolderFactoryTest.kt | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt index 25d510ab12..862b0a1419 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt @@ -617,7 +617,6 @@ class CheckBoxGroupViewHolderFactoryTest { ) } - @Test fun click_should_Select_Other_CheckboxButton() { viewHolder.bind( @@ -626,28 +625,31 @@ class CheckBoxGroupViewHolderFactoryTest { repeats = false addAnswerOption( Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { - code = "code-1" - display = "display-1" - } + value = + Coding().apply { + code = "code-1" + display = "display-1" + } }, ) addAnswerOption( Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { - code = "code-2" - display = "display-2" - } + value = + Coding().apply { + code = "code-2" + display = "display-2" + } }, ) }, QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { addAnswer( QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply { - value = Coding().apply { - code = "code-1" - display = "display-1" - } + value = + Coding().apply { + code = "code-1" + display = "display-1" + } }, ) }, @@ -657,9 +659,9 @@ class CheckBoxGroupViewHolderFactoryTest { ) val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked,).isTrue() + assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked).isTrue() checkBoxGroup.getChildAt(2).performClick() - assertThat((checkBoxGroup.getChildAt(2) as CheckBox).isChecked,).isTrue() + assertThat((checkBoxGroup.getChildAt(2) as CheckBox).isChecked).isTrue() } @Test @@ -670,17 +672,19 @@ class CheckBoxGroupViewHolderFactoryTest { repeats = false addAnswerOption( Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = Coding().apply { - code = "code-1" - display = "display-1" - } + value = + Coding().apply { + code = "code-1" + display = "display-1" + } }, ) }, QuestionnaireResponse.QuestionnaireResponseItemComponent(), validationResult = NotValidated, answersChangedCallback = { _, _, _, _ -> }, - )) + ), + ) val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) checkBoxGroup.getChildAt(1).performClick() From 848f9c92730cc4334953fb0f2ecce06181ffc789 Mon Sep 17 00:00:00 2001 From: mmanojkmr Date: Fri, 21 Mar 2025 11:10:07 +0530 Subject: [PATCH 9/9] code updated --- .../CheckBoxGroupViewHolderFactoryTest.kt | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt index 862b0a1419..57b398cc12 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/views/factories/CheckBoxGroupViewHolderFactoryTest.kt @@ -663,33 +663,4 @@ class CheckBoxGroupViewHolderFactoryTest { checkBoxGroup.getChildAt(2).performClick() assertThat((checkBoxGroup.getChildAt(2) as CheckBox).isChecked).isTrue() } - - @Test - fun click_Selected_CheckboxButton_Should_Uncheck_CheckboxButton() { - viewHolder.bind( - QuestionnaireViewItem( - Questionnaire.QuestionnaireItemComponent().apply { - repeats = false - addAnswerOption( - Questionnaire.QuestionnaireItemAnswerOptionComponent().apply { - value = - Coding().apply { - code = "code-1" - display = "display-1" - } - }, - ) - }, - QuestionnaireResponse.QuestionnaireResponseItemComponent(), - validationResult = NotValidated, - answersChangedCallback = { _, _, _, _ -> }, - ), - ) - - val checkBoxGroup = viewHolder.itemView.findViewById(R.id.checkbox_group) - checkBoxGroup.getChildAt(1).performClick() - assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked).isTrue() - checkBoxGroup.getChildAt(1).performClick() - assertThat((checkBoxGroup.getChildAt(1) as CheckBox).isChecked).isFalse() - } }