Skip to content

Commit

Permalink
Merge pull request #5647 from grzesiek2010/COLLECT-5148
Browse files Browse the repository at this point in the history
Disable 'Save as draft' when 'Moving backwards' is disabled
  • Loading branch information
seadowg authored Jul 5, 2023
2 parents 5caa56c + 4f90c71 commit 982e981
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.odk.collect.android.feature.settings

import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.runner.RunWith
import org.odk.collect.android.R
import org.odk.collect.android.support.rules.CollectTestRule
import org.odk.collect.android.support.rules.TestRuleChain

@RunWith(AndroidJUnit4::class)
class MovingBackwardsTest {
private val rule = CollectTestRule()

@get:Rule
var ruleChain: RuleChain = TestRuleChain.chain().around(rule)

@Test
fun whenMovingBackwardDisabledWithPreventingUsersFormBypassingIt_relatedOptionsShouldBeUpdated() {
rule.startAtMainMenu()
.openProjectSettingsDialog()
.clickSettings()
.clickAccessControl()
.clickFormEntrySettings()
.clickOnString(R.string.finalize)

// before disabling moving backward
.assertGoToPromptEnabled()
.assertGoToPromptChecked()

.assertSaveAsDraftInFormEntryEnabled()
.assertSaveAsDraftInFormEntryChecked()

.assertSaveAsDraftInFormEndDisabled()
.assertSaveAsDraftInFormEndChecked()

.assertFinalizeEnabled()
.assertFinalizeUnchecked()

.clickMovingBackwards()
.clickOnString(R.string.yes)

// after disabling moving backward - the state of the 4 related options is reversed
.assertGoToPromptDisabled()
.assertGoToPromptUnchecked()

.assertSaveAsDraftInFormEntryDisabled()
.assertSaveAsDraftInFormEntryUnchecked()

.assertSaveAsDraftInFormEndDisabled()
.assertSaveAsDraftInFormEndUnchecked()

.assertFinalizeDisabled()
.assertFinalizeChecked()
}

@Test
fun whenMovingBackwardDisabledWithoutPreventingUsersFormBypassingIt_relatedOptionsShouldNotBeUpdated() {
rule.startAtMainMenu()
.openProjectSettingsDialog()
.clickSettings()
.clickAccessControl()
.clickFormEntrySettings()
.clickMovingBackwards()
.clickOnString(R.string.no)
.assertGoToPromptEnabled()
.assertSaveAsDraftInFormEntryEnabled()
.assertSaveAsDraftInFormEndEnabled()
.assertFinalizeEnabled()
.assertGoToPromptChecked()
.assertSaveAsDraftInFormEntryChecked()
.assertSaveAsDraftInFormEndChecked()
.assertFinalizeChecked()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void movingBackwards_shouldBeTurnedOn() {
.assertText(R.string.yes)
.assertText(R.string.no)
.clickOnString(R.string.yes)
.checkIfSaveAsDraftInFormEntryOptionIsDisabled()
.assertSaveAsDraftInFormEntryDisabled()
.pressBack(new AccessControlPage())
.pressBack(new ProjectSettingsPage())
.pressBack(new MainMenuPage())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package org.odk.collect.android.support.pages
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isChecked
import androidx.test.espresso.matcher.ViewMatchers.isEnabled
import androidx.test.espresso.matcher.ViewMatchers.isNotChecked
import androidx.test.espresso.matcher.ViewMatchers.withClassName
import androidx.test.espresso.matcher.ViewMatchers.withText
import org.hamcrest.Matchers.endsWith
import org.hamcrest.Matchers.not
import org.odk.collect.android.R
import org.odk.collect.android.support.matchers.CustomMatchers.withIndex
Expand All @@ -31,11 +35,86 @@ class AccessControlPage : Page<AccessControlPage>() {
return this
}

fun checkIfSaveAsDraftInFormEntryOptionIsDisabled(): AccessControlPage {
fun assertGoToPromptEnabled(): AccessControlPage {
onView(withText(getTranslatedString(R.string.view_hierarchy))).check(matches(isEnabled()))
return this
}

fun assertGoToPromptDisabled(): AccessControlPage {
onView(withText(getTranslatedString(R.string.view_hierarchy))).check(matches(not(isEnabled())))
return this
}

fun assertGoToPromptChecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 3)).check(matches(isChecked()))
return this
}

fun assertGoToPromptUnchecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 3)).check(matches(isNotChecked()))
return this
}

fun assertSaveAsDraftInFormEntryEnabled(): AccessControlPage {
onView(withIndex(withText(getTranslatedString(R.string.save_mid)), 0)).check(matches(isEnabled()))
return this
}

fun assertSaveAsDraftInFormEntryDisabled(): AccessControlPage {
onView(withIndex(withText(getTranslatedString(R.string.save_mid)), 0)).check(matches(not(isEnabled())))
return this
}

fun assertSaveAsDraftInFormEntryChecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 4)).check(matches(isChecked()))
return this
}

fun assertSaveAsDraftInFormEntryUnchecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 4)).check(matches(isNotChecked()))
return this
}

fun assertSaveAsDraftInFormEndEnabled(): AccessControlPage {
onView(withIndex(withText(getTranslatedString(R.string.save_as_draft)), 1)).check(matches(isEnabled()))
return this
}

fun assertSaveAsDraftInFormEndDisabled(): AccessControlPage {
onView(withIndex(withText(getTranslatedString(R.string.save_as_draft)), 1)).check(matches(not(isEnabled())))
return this
}

fun assertSaveAsDraftInFormEndChecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 5)).check(matches(isChecked()))
return this
}

fun assertSaveAsDraftInFormEndUnchecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 5)).check(matches(isNotChecked()))
return this
}

fun assertFinalizeEnabled(): AccessControlPage {
onView(withText(getTranslatedString(R.string.finalize))).check(matches(isEnabled()))
return this
}

fun assertFinalizeDisabled(): AccessControlPage {
onView(withText(getTranslatedString(R.string.finalize))).check(matches(not(isEnabled())))
return this
}

fun assertFinalizeChecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 6)).check(matches(isChecked()))
return this
}

fun assertFinalizeUnchecked(): AccessControlPage {
onView(withIndex(withClassName(endsWith("CheckBox")), 6)).check(matches(isNotChecked()))
return this
}

fun clickOnSaveAsDraftInFormEnd(): AccessControlPage {
onView(withIndex(withText(getTranslatedString(R.string.save_mid)), 1)).perform(click())
return this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class FormEntryAccessPreferencesFragment : BaseAdminPreferencesFragment() {
findPreference(ProtectedProjectKeys.KEY_SAVE_MID).isEnabled =
settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM)

findPreference(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT).isEnabled = findPreference(ProtectedProjectKeys.KEY_FINALIZE).isChecked
findPreference(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT).isEnabled =
settingsProvider.getProtectedSettings().getBoolean(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM) && findPreference(ProtectedProjectKeys.KEY_FINALIZE).isChecked
findPreference(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT).onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _: Preference, newValue: Any? ->
findPreference(ProtectedProjectKeys.KEY_FINALIZE).isEnabled = newValue as Boolean
Expand All @@ -60,20 +61,27 @@ class FormEntryAccessPreferencesFragment : BaseAdminPreferencesFragment() {
fun preventOtherWaysOfEditingForm() {
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM, false)
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_EDIT_SAVED, false)
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_SAVE_MID, false)
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT, false)
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_FINALIZE, true)
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.KEY_JUMP_TO, false)
settingsProvider.getUnprotectedSettings().save(ProjectKeys.KEY_CONSTRAINT_BEHAVIOR, ProjectKeys.CONSTRAINT_BEHAVIOR_ON_SWIPE)

findPreference(ProtectedProjectKeys.KEY_JUMP_TO).isEnabled = false
findPreference(ProtectedProjectKeys.KEY_SAVE_MID).isEnabled = false
findPreference(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT).isEnabled = false
findPreference(ProtectedProjectKeys.KEY_FINALIZE).isEnabled = false
findPreference(ProtectedProjectKeys.KEY_JUMP_TO).isChecked = false
findPreference(ProtectedProjectKeys.KEY_SAVE_MID).isChecked = false
findPreference(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT).isChecked = false
findPreference(ProtectedProjectKeys.KEY_FINALIZE).isChecked = true
}

private fun onMovingBackwardsEnabled() {
settingsProvider.getProtectedSettings().save(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM, true)
findPreference(ProtectedProjectKeys.KEY_JUMP_TO).isEnabled = true
findPreference(ProtectedProjectKeys.KEY_SAVE_MID).isEnabled = true
findPreference(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT).isEnabled = true
findPreference(ProtectedProjectKeys.KEY_FINALIZE).isEnabled = true
}

private fun findPreference(key: String): CheckBoxPreference {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static org.odk.collect.settings.migration.MigrationUtils.renameKey;
import static org.odk.collect.settings.migration.MigrationUtils.translateKey;
import static org.odk.collect.settings.migration.MigrationUtils.translateValue;
import static org.odk.collect.settings.migration.MigrationUtils.updateKeys;
import static java.util.Arrays.asList;

import org.odk.collect.settings.importing.SettingsMigrator;
Expand Down Expand Up @@ -167,7 +168,13 @@ public List<Migration> getProtectedMigrations() {
ProtectedProjectKeys.KEY_FINALIZE, true
),
removeKey("mark_as_finalized"),
removeKey("default_completed")
removeKey("default_completed"),
updateKeys(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM)
.withValues(false)
.toPairs(
ProtectedProjectKeys.KEY_SAVE_AS_DRAFT, false,
ProtectedProjectKeys.KEY_FINALIZE, true
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.odk.collect.settings.migration;

import static org.odk.collect.settings.migration.MigrationUtils.asPairs;

import org.odk.collect.shared.settings.Settings;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class KeyUpdater implements Migration {

String[] oldKeys;
Object[] tempOldValueArray;
List<Object[]> oldValueArrays = new ArrayList<>();
List<KeyValuePair[]> newKeyValuePairArrays = new ArrayList<>();

KeyUpdater(String... oldKeys) {
this.oldKeys = oldKeys;
}

public KeyUpdater withValues(Object... oldValues) {
tempOldValueArray = oldValues;
return this;
}

public KeyUpdater toPairs(Object... keysAndValues) {
oldValueArrays.add(tempOldValueArray);
newKeyValuePairArrays.add(asPairs(keysAndValues));
return this;
}

public void apply(Settings prefs) {
Map<String, ?> prefMap = prefs.getAll();
Object[] oldValues = new Object[oldKeys.length];
for (int i = 0; i < oldKeys.length; i++) {
oldValues[i] = prefMap.get(oldKeys[i]);
}
for (int i = 0; i < oldValueArrays.size(); i++) {
if (Arrays.equals(oldValues, oldValueArrays.get(i))) {
for (KeyValuePair keyValuePair : newKeyValuePairArrays.get(i)) {
prefs.save(keyValuePair.key, keyValuePair.value);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ public static KeyCombiner combineKeys(String... oldKeys) {
return new KeyCombiner(oldKeys);
}

/**
* It works like KeyCombiner BUT it does not remove the old keys
*/
public static KeyUpdater updateKeys(String... oldKeys) {
return new KeyUpdater(oldKeys);
}

public static KeyMover moveKey(String key) {
return new KeyMover(key);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,38 @@ public void when_markAsFinalized_wasEnabled_and_defaultCompleted_wasEnabled_then
assertThat(protectedSettings.contains("default_completed"), equalTo(false));
}

@Test
public void when_AllowOtherWaysOfEditingFormIsDisabled_thenSaveAsDraftShouldBeDisabledAndFinalizeShouldBeEnabled() {
initSettings(protectedSettings,
ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM, false,
ProtectedProjectKeys.KEY_SAVE_AS_DRAFT, true,
ProtectedProjectKeys.KEY_FINALIZE, false
);

runMigrations();

assertThat(protectedSettings.contains(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM), equalTo(true));
assertThat(protectedSettings.getBoolean(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM), equalTo(false));
assertThat(protectedSettings.getBoolean(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT), equalTo(false));
assertThat(protectedSettings.getBoolean(ProtectedProjectKeys.KEY_FINALIZE), equalTo(true));
}

@Test
public void when_AllowOtherWaysOfEditingFormIsEnabled_thenDoNotUpdateSaveAsDraftOrFinalize() {
initSettings(protectedSettings,
ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM, true,
ProtectedProjectKeys.KEY_SAVE_AS_DRAFT, true,
ProtectedProjectKeys.KEY_FINALIZE, false
);

runMigrations();

assertThat(protectedSettings.contains(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM), equalTo(true));
assertThat(protectedSettings.getBoolean(ProtectedProjectKeys.ALLOW_OTHER_WAYS_OF_EDITING_FORM), equalTo(true));
assertThat(protectedSettings.getBoolean(ProtectedProjectKeys.KEY_SAVE_AS_DRAFT), equalTo(true));
assertThat(protectedSettings.getBoolean(ProtectedProjectKeys.KEY_FINALIZE), equalTo(false));
}

private void runMigrations() {
new ODKAppSettingsMigrator(metaSettings).migrate(unprotectedSettings, protectedSettings);
}
Expand Down

0 comments on commit 982e981

Please sign in to comment.