From a60d77585933328063aedb527cc319735ebb19ff Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Wed, 13 Nov 2024 14:50:27 +0000 Subject: [PATCH 01/18] Add tests for view only behaviour --- .../feature/formentry/AddRepeatTest.java | 18 ++++++++- .../feature/formentry/FormHierarchyTest.java | 37 +++++++++++++++++-- .../odk/collect/android/support/pages/Page.kt | 5 +++ .../android/support/pages/ViewFormPage.kt | 17 +++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/AddRepeatTest.java b/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/AddRepeatTest.java index ab26c8291ac..3ae7abe25ac 100644 --- a/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/AddRepeatTest.java +++ b/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/AddRepeatTest.java @@ -12,6 +12,7 @@ import org.junit.runner.RunWith; import org.odk.collect.android.R; import org.odk.collect.android.support.pages.EndOfFormPage; +import org.odk.collect.android.support.pages.FormEndPage; import org.odk.collect.android.support.pages.FormEntryPage; import org.odk.collect.android.support.rules.CollectTestRule; import org.odk.collect.android.support.rules.TestRuleChain; @@ -106,7 +107,7 @@ public void whenInRepeatWithFixedCount_noPlusButtonAppears() { } @Test - public void whenInHierarchyForRepeat_clickingPlus_addsRepeatAtEndOfSeries() { + public void whenInHierarchyForRepeatGroup_clickingPlus_addsRepeatAtEndOfSeries() { rule.startAtMainMenu() .copyForm(ONE_QUESTION_REPEAT) .startBlankForm("One Question Repeat") @@ -130,4 +131,19 @@ public void whenInRepeatWithoutLabel_swipingNext_andClickingAdd_addsAnotherRepea .clickOnAdd(new FormEntryPage("Repeat without label")) .assertText("> 2"); } + + @Test + public void whenViewFormInHierarchyForRepeatGroup_noAddButtonAppears() { + rule.startAtMainMenu() + .copyForm(ONE_QUESTION_REPEAT) + .startBlankForm("One Question Repeat") + .swipeToNextQuestionWithRepeatGroup("Person") + .clickOnDoNotAdd(new FormEndPage("One Question Repeat")) + .clickFinalize() + + .clickSendFinalizedForm(1) + .clickOnForm("One Question Repeat") + .clickOnGroup("Person") + .assertNoId(R.id.menu_add_repeat); + } } diff --git a/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/FormHierarchyTest.java b/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/FormHierarchyTest.java index 73d7cf8f1cb..51f515f1859 100644 --- a/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/FormHierarchyTest.java +++ b/collect_app/src/androidTest/java/org/odk/collect/android/feature/formentry/FormHierarchyTest.java @@ -10,12 +10,14 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.odk.collect.android.R; -import org.odk.collect.android.support.rules.CollectTestRule; -import org.odk.collect.android.support.rules.TestRuleChain; -import org.odk.collect.testshared.RecyclerViewMatcher; import org.odk.collect.android.support.pages.AddNewRepeatDialog; +import org.odk.collect.android.support.pages.FormEndPage; import org.odk.collect.android.support.pages.FormEntryPage; import org.odk.collect.android.support.pages.FormHierarchyPage; +import org.odk.collect.android.support.pages.ViewFormPage; +import org.odk.collect.android.support.rules.CollectTestRule; +import org.odk.collect.android.support.rules.TestRuleChain; +import org.odk.collect.testshared.RecyclerViewMatcher; public class FormHierarchyTest { @@ -238,4 +240,33 @@ public void theListOfQuestionsShouldBeScrolledToTheLastDisplayedQuestionAfterOpe .assertTextDoesNotExist("t1") .assertTextDoesNotExist("t2"); } + + @Test + public void whenViewFormInHierarchyForRepeat_noDeleteButtonAppears() { + rule.startAtMainMenu() + .copyForm("one-question-repeat.xml") + .startBlankForm("One Question Repeat") + .swipeToNextQuestionWithRepeatGroup("Person") + .clickOnDoNotAdd(new FormEndPage("One Question Repeat")) + .clickFinalize() + + .clickSendFinalizedForm(1) + .clickOnForm("One Question Repeat") + .clickOnGroup("Person") + .clickOnGroup("Person > 1") + .assertNoId(R.id.menu_delete_child); + } + + @Test + public void whenViewFormInHierarchy_clickingOnQuestion_doesNothing() { + rule.startAtMainMenu() + .copyForm("one-question.xml") + .startBlankForm("One Question") + .fillOutAndFinalize() + + .clickSendFinalizedForm(1) + .clickOnForm("One Question") + .clickOnText("what is your age") + .assertOnPage(new ViewFormPage("One Question")); + } } diff --git a/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/Page.kt b/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/Page.kt index 3ca7476d672..5ed0938ccf5 100644 --- a/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/Page.kt +++ b/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/Page.kt @@ -574,6 +574,11 @@ abstract class Page> { return destination } + fun assertNoId(id: Int): T { + onView(withId(id)).check(doesNotExist()) + return this as T + } + companion object { private fun rotateToLandscape(): ViewAction { return RotateAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) diff --git a/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/ViewFormPage.kt b/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/ViewFormPage.kt index 5001409fe6a..aef51f38f0f 100644 --- a/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/ViewFormPage.kt +++ b/collect_app/src/androidTest/java/org/odk/collect/android/support/pages/ViewFormPage.kt @@ -1,5 +1,13 @@ package org.odk.collect.android.support.pages +import androidx.recyclerview.widget.RecyclerView +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.contrib.RecyclerViewActions.scrollTo +import androidx.test.espresso.matcher.ViewMatchers.hasDescendant +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import org.odk.collect.android.R + class ViewFormPage(private val formName: String) : Page() { override fun assertOnPage(): ViewFormPage { @@ -7,4 +15,13 @@ class ViewFormPage(private val formName: String) : Page() { assertText(org.odk.collect.strings.R.string.exit) return this } + + fun clickOnGroup(groupLabel: String): ViewFormPage { + onView(withId(R.id.list)).perform(scrollTo( + hasDescendant(withText(groupLabel))) + ) + + clickOnText(groupLabel) + return this + } } From c6754ea4f5e4d1f452c9b4128b6f1c8383dea18d Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 14 Nov 2024 09:17:30 +0000 Subject: [PATCH 02/18] Remove ViewOnlyHierarchyActivity --- collect_app/src/main/AndroidManifest.xml | 1 - .../activities/FormFillingActivity.java | 4 +- .../formhierarchy/FormHierarchyActivity.java | 57 ++++++++++++++----- .../ViewOnlyFormHierarchyActivity.kt | 56 ------------------ 4 files changed, 44 insertions(+), 74 deletions(-) delete mode 100644 collect_app/src/main/java/org/odk/collect/android/formhierarchy/ViewOnlyFormHierarchyActivity.kt diff --git a/collect_app/src/main/AndroidManifest.xml b/collect_app/src/main/AndroidManifest.xml index ea728bd55ee..ff0cf6e26f1 100644 --- a/collect_app/src/main/AndroidManifest.xml +++ b/collect_app/src/main/AndroidManifest.xml @@ -144,7 +144,6 @@ the specific language governing permissions and limitations under the License. android:name=".preferences.screens.ProjectPreferencesActivity" android:theme="@style/Theme.Collect.Settings" /> - { - formController.getAuditEventLogger().flush(); - formController.jumpToIndex(FormIndex.createBeginningOfFormIndex()); + if (viewOnly) { + Button exitButton = findViewById(R.id.exitButton); + exitButton.setOnClickListener(v -> getOnBackPressedDispatcher().onBackPressed()); + exitButton.setVisibility(View.VISIBLE); + jumpBeginningButton.setVisibility(View.GONE); + jumpEndButton.setVisibility(View.GONE); + } else { + jumpBeginningButton.setOnClickListener(v -> { + formController.getAuditEventLogger().flush(); + formController.jumpToIndex(FormIndex.createBeginningOfFormIndex()); - setResult(RESULT_OK); - finish(); - }); + setResult(RESULT_OK); + finish(); + }); - jumpEndButton.setOnClickListener(v -> { - formController.getAuditEventLogger().flush(); - formController.jumpToIndex(FormIndex.createEndOfFormIndex()); + jumpEndButton.setOnClickListener(v -> { + formController.getAuditEventLogger().flush(); + formController.jumpToIndex(FormIndex.createEndOfFormIndex()); + + setResult(RESULT_OK); + finish(); + }); + } - setResult(RESULT_OK); - finish(); - }); } /** @@ -854,6 +877,10 @@ public void onElementClick(HierarchyItem item) { * If the selected question is in a field list, show the entire field list. */ void onQuestionClicked(FormIndex index) { + if (viewOnly) { + return; + } + formEntryViewModel.getFormController().jumpToIndex(index); if (formEntryViewModel.getFormController().indexIsInFieldList()) { try { diff --git a/collect_app/src/main/java/org/odk/collect/android/formhierarchy/ViewOnlyFormHierarchyActivity.kt b/collect_app/src/main/java/org/odk/collect/android/formhierarchy/ViewOnlyFormHierarchyActivity.kt deleted file mode 100644 index d1647b15460..00000000000 --- a/collect_app/src/main/java/org/odk/collect/android/formhierarchy/ViewOnlyFormHierarchyActivity.kt +++ /dev/null @@ -1,56 +0,0 @@ -package org.odk.collect.android.formhierarchy - -import android.os.Bundle -import android.view.View -import android.widget.Button -import androidx.activity.OnBackPressedCallback -import org.javarosa.core.model.FormIndex -import org.odk.collect.android.R -import org.odk.collect.android.javarosawrapper.FormController - -/** - * Displays the structure of a form along with the answers for the current instance. Disables all - * features that allow the user to edit the form instance. - */ -class ViewOnlyFormHierarchyActivity : FormHierarchyActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - onBackPressedCallback.remove() - onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - setResult(RESULT_OK) - finish() - val sessionId = intent.getStringExtra(EXTRA_SESSION_ID)!! - formSessionRepository.clear(sessionId) - } - }) - } - - /** - * Hides buttons to jump to the beginning and to the end of the form instance to edit it. Adds - * an extra exit button that exits this activity. - */ - public override fun configureButtons(formController: FormController) { - val exitButton = findViewById