diff --git a/build.sh b/build.sh
index 12df11b39..15d46f661 100755
--- a/build.sh
+++ b/build.sh
@@ -147,9 +147,9 @@ install_test_apk() {
run_instrumented_tests() {
log_info "Running instrumented tests"
$ADB shell am instrument \
- -r -e coverage true \
+ -r -e coverage true -e size medium \
-w ${PACKAGE_NAME}.test/android.support.test.runner.AndroidJUnitRunner \
- > ${OUTPUTS_DIR}/instrument.txt
+ | tee ${OUTPUTS_DIR}/instrument.txt
mkdir -p ${OUTPUTS_DIR}/code-coverage/connected/
$ADB pull /data/user/0/${PACKAGE_NAME}/files/coverage.ec \
diff --git a/uhabits-android/build.gradle b/uhabits-android/build.gradle
index 633568fab..0bf33ad84 100644
--- a/uhabits-android/build.gradle
+++ b/uhabits-android/build.gradle
@@ -94,6 +94,7 @@ dependencies {
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
+ androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2'
androidTestCompile 'com.linkedin.testbutler:test-butler-library:1.3.1'
implementation('com.opencsv:opencsv:3.9') {
diff --git a/uhabits-android/src/androidTest/AndroidManifest.xml b/uhabits-android/src/androidTest/AndroidManifest.xml
new file mode 100644
index 000000000..f5c89202e
--- /dev/null
+++ b/uhabits-android/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/uhabits-android/src/androidTest/assets/test.db b/uhabits-android/src/androidTest/assets/test.db
new file mode 100644
index 000000000..531903063
Binary files /dev/null and b/uhabits-android/src/androidTest/assets/test.db differ
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java
index b71625295..b731888f5 100644
--- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseAndroidTest.java
@@ -25,6 +25,7 @@ import android.content.res.*;
import android.os.*;
import android.support.annotation.*;
import android.support.test.*;
+import android.support.test.filters.*;
import android.util.*;
import junit.framework.*;
@@ -44,6 +45,7 @@ import java.util.concurrent.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
+@MediumTest
public class BaseAndroidTest extends TestCase
{
// 8:00am, January 25th, 2015 (UTC)
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUIAutomatorTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUIAutomatorTest.java
index 0f23f0b55..1d674e21d 100644
--- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUIAutomatorTest.java
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/BaseUIAutomatorTest.java
@@ -20,46 +20,66 @@
package org.isoron.uhabits;
import android.content.*;
+import android.support.test.filters.*;
import android.support.test.uiautomator.*;
import com.linkedin.android.testbutler.*;
import org.isoron.androidbase.*;
+import org.isoron.androidbase.utils.*;
+import org.isoron.uhabits.preferences.*;
+import org.isoron.uhabits.utils.*;
import org.junit.*;
+import java.io.*;
+
import static android.support.test.InstrumentationRegistry.*;
import static android.support.test.uiautomator.UiDevice.*;
+@LargeTest
public class BaseUIAutomatorTest
{
- static final String PKG = "org.isoron.uhabits";
+ private static final String PKG = "org.isoron.uhabits";
+
+ public static UiDevice device;
- protected UiDevice device;
+ private HabitsComponent component;
@Before
- public void setUp()
+ public void setUp() throws IOException
{
TestButler.setup(getTargetContext());
+ TestButler.verifyAnimationsDisabled(getTargetContext());
device = getInstance(getInstrumentation());
- HabitsComponent component = DaggerHabitsComponent
+ component = DaggerHabitsComponent
.builder()
.appModule(new AppModule(getTargetContext()))
.build();
+ AndroidPreferences prefs = component.getPreferences();
+ prefs.reset();
+ prefs.setFirstRun(false);
+
HabitsApplication.setComponent(component);
+
+ FileUtils.copy(getContext().getAssets().open("test.db"),
+ DatabaseUtils.getDatabaseFile(getTargetContext()));
}
@After
- public void tearDown()
+ public void tearDown() throws Exception
{
+ device.pressHome();
+ device.waitForIdle();
TestButler.teardown(getTargetContext());
}
- protected void startActivity(Class cls)
+ public static void startActivity(Class cls)
{
Intent intent = new Intent();
intent.setComponent(new ComponentName(PKG, cls.getCanonicalName()));
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
getContext().startActivity(intent);
}
}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/AboutTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/AboutTest.java
new file mode 100644
index 000000000..35d5722ab
--- /dev/null
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/AboutTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.acceptance;
+
+import org.isoron.uhabits.*;
+import org.junit.*;
+
+import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
+
+public class AboutTest extends BaseUIAutomatorTest
+{
+ @Test
+ public void shouldDisplayAboutScreen()
+ {
+ launchApp();
+ clickMenu(ABOUT);
+ verifyDisplaysText("Loop Habit Tracker");
+ verifyDisplaysText("Rate this app on Google Play");
+ verifyDisplaysText("Developers");
+ verifyDisplaysText("Translators");
+
+ launchApp();
+ clickMenu(SETTINGS);
+ clickText("About");
+ verifyDisplaysText("Translators");
+ }
+}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java
new file mode 100644
index 000000000..bad651adf
--- /dev/null
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/HabitsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.acceptance;
+
+import org.isoron.uhabits.*;
+import org.junit.*;
+
+import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
+import static org.isoron.uhabits.acceptance.steps.EditHabitSteps.*;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.*;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
+
+public class HabitsTest extends BaseUIAutomatorTest
+{
+ @Test
+ public void shouldCreateHabit() throws Exception
+ {
+ launchApp();
+ clickMenu(CREATE_HABIT);
+ typeName("Hello world");
+ typeQuestion("Did you say hello to the world today?");
+ pickFrequency("Every week");
+ pickColor(5);
+ clickSave();
+ verifyDisplaysText("Hello world");
+ }
+
+ @Test
+ public void shouldShowHabitStatistics() throws Exception
+ {
+ launchApp();
+ clickText("Track time");
+ verifyDisplayGraphs();
+ }
+
+ @Test
+ public void shouldDeleteHabit() throws Exception
+ {
+ launchApp();
+ longClickText("Track time");
+ clickMenu(DELETE);
+ clickOK();
+ verifyDoesNotDisplayText("Track time");
+ }
+
+ @Test
+ public void shouldEditHabit() throws Exception
+ {
+ launchApp();
+ longClickText("Track time");
+ clickMenu(EDIT_HABIT);
+ typeName("Take a walk");
+ typeQuestion("Did you take a walk today?");
+ clickSave();
+ verifyDisplaysText("Take a walk");
+ verifyDoesNotDisplayText("Track time");
+ }
+
+ @Test
+ public void shouldEditHabit_fromStatisticsScreen() throws Exception
+ {
+ launchApp();
+ clickText("Track time");
+ clickMenu(EDIT_HABIT);
+ typeName("Take a walk");
+ typeQuestion("Did you take a walk today?");
+ pickColor(10);
+ clickSave();
+ verifyDisplaysText("Take a walk");
+ pressBack();
+ verifyDisplaysText("Take a walk");
+ verifyDoesNotDisplayText("Track time");
+ }
+
+ @Test
+ public void shouldArchiveAndUnarchiveHabits() throws Exception
+ {
+ launchApp();
+ longClickText("Track time");
+ clickMenu(ARCHIVE);
+ verifyDoesNotDisplayText("Track time");
+ clickMenu(HIDE_ARCHIVED);
+ verifyDisplaysText("Track time");
+
+ longClickText("Track time");
+ clickMenu(UNARCHIVE);
+ clickMenu(HIDE_ARCHIVED);
+ verifyDisplaysText("Track time");
+ }
+}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/LinksTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/LinksTest.java
new file mode 100644
index 000000000..ad788acf4
--- /dev/null
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/LinksTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.acceptance;
+
+import org.isoron.uhabits.*;
+import org.junit.*;
+
+import static org.isoron.uhabits.acceptance.steps.CommonSteps.*;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.*;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.ABOUT;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.HELP;
+import static org.isoron.uhabits.acceptance.steps.ListHabitsSteps.MenuItem.SETTINGS;
+
+public class LinksTest extends BaseUIAutomatorTest
+{
+ @Test
+ public void shouldLinkToSourceCode() throws Exception
+ {
+ launchApp();
+ clickMenu(ABOUT);
+ clickText("View source code at GitHub");
+ verifyOpensWebsite("https://github.com/iSoron/uhabits");
+ }
+
+ @Test
+ public void shouldLinkToTranslationWebsite() throws Exception
+ {
+ launchApp();
+ clickMenu(ABOUT);
+ clickText("Help translate this app");
+ verifyOpensWebsite("translate.loophabits.org");
+ }
+
+ @Test
+ public void shouldLinkToHelp() throws Exception
+ {
+ launchApp();
+ clickMenu(HELP);
+ verifyOpensWebsite("loophabits.org/faq.html");
+
+ launchApp();
+ clickMenu(SETTINGS);
+ clickText("Help & FAQ");
+ verifyOpensWebsite("loophabits.org/faq.html");
+ }
+}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java
new file mode 100644
index 000000000..d41d6f5c0
--- /dev/null
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/CommonSteps.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.acceptance.steps;
+
+import android.support.annotation.*;
+import android.support.test.espresso.*;
+import android.support.test.espresso.contrib.*;
+import android.support.test.uiautomator.*;
+import android.support.v7.widget.*;
+
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.activities.habits.list.*;
+
+import static android.support.test.espresso.Espresso.*;
+import static android.support.test.espresso.action.ViewActions.*;
+import static android.support.test.espresso.assertion.ViewAssertions.*;
+import static android.support.test.espresso.matcher.ViewMatchers.*;
+import static junit.framework.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+
+public class CommonSteps extends BaseUIAutomatorTest
+{
+ public static void clickOK()
+ {
+ clickText("OK");
+ }
+
+ public static void pressBack()
+ {
+ device.pressBack();
+ }
+
+ public static void clickText(String text)
+ {
+ scrollToText(text);
+ onView(withText(text)).perform(click());
+ }
+
+ public static void clickText(@StringRes int id)
+ {
+ onView(withText(id)).perform(click());
+ }
+
+ public static void launchApp()
+ {
+ startActivity(ListHabitsActivity.class);
+ assertTrue(
+ device.wait(Until.hasObject(By.pkg("org.isoron.uhabits")), 5000));
+ device.waitForIdle();
+ }
+
+ public static void longClickText(String text)
+ {
+ scrollToText(text);
+ onView(withText(text)).perform(longClick());
+ }
+
+ public static void scrollToText(String text)
+ {
+ try
+ {
+ if (device
+ .findObject(new UiSelector().className(RecyclerView.class))
+ .exists())
+ {
+ onView(instanceOf(RecyclerView.class)).perform(
+ RecyclerViewActions.scrollTo(
+ hasDescendant(withText(text))));
+ }
+ else
+ {
+ onView(withText(text)).perform(scrollTo());
+ }
+ }
+ catch (PerformException e)
+ {
+ //ignored
+ }
+ }
+
+ public static void verifyDisplayGraphs()
+ {
+ verifyDisplaysView("HistoryCard");
+ verifyDisplaysView("ScoreCard");
+ }
+
+ public static void verifyDisplaysText(String text)
+ {
+ scrollToText(text);
+ onView(withText(text)).check(matches(isEnabled()));
+ }
+
+ private static void verifyDisplaysView(String className)
+ {
+ onView(withClassName(endsWith(className))).check(matches(isEnabled()));
+ }
+
+ public static void verifyDoesNotDisplayText(String text)
+ {
+ onView(withText(text)).check(doesNotExist());
+ }
+
+ public static void verifyOpensWebsite(String url) throws Exception
+ {
+ assertTrue(
+ device.wait(Until.hasObject(By.pkg("com.android.chrome")), 5000));
+ device.waitForIdle();
+ assertTrue(device.findObject(new UiSelector().text(url)).exists());
+ }
+}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java
new file mode 100644
index 000000000..9b4774427
--- /dev/null
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/EditHabitSteps.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.acceptance.steps;
+
+import android.support.test.uiautomator.*;
+
+import org.isoron.uhabits.*;
+
+import static android.support.test.espresso.Espresso.*;
+import static android.support.test.espresso.action.ViewActions.*;
+import static android.support.test.espresso.matcher.ViewMatchers.*;
+import static org.isoron.uhabits.BaseUIAutomatorTest.device;
+
+public class EditHabitSteps
+{
+ public static void clickSave()
+ {
+ onView(withId(R.id.buttonSave)).perform(click());
+ }
+
+ public static void pickFrequency(String freq)
+ {
+ onView(withId(R.id.spinner)).perform(click());
+ device.findObject(By.text(freq)).click();
+ }
+
+ public static void pickColor(int color)
+ {
+ onView(withId(R.id.buttonPickColor)).perform(click());
+ device.findObject(By.descStartsWith(String.format("Color %d", color))).click();
+ }
+
+ public static void typeName(String name)
+ {
+ typeTextWithId(R.id.tvName, name);
+ }
+
+ public static void typeQuestion(String name)
+ {
+ typeTextWithId(R.id.tvDescription, name);
+ }
+
+ private static void typeTextWithId(int id, String name)
+ {
+ onView(withId(id)).perform(clearText(), typeText(name));
+ }
+}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java
new file mode 100644
index 000000000..f3328d146
--- /dev/null
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/acceptance/steps/ListHabitsSteps.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.acceptance.steps;
+
+import android.support.test.espresso.*;
+import android.support.test.uiautomator.*;
+import android.view.*;
+
+import org.hamcrest.*;
+import org.isoron.uhabits.R;
+import org.isoron.uhabits.activities.habits.list.views.*;
+
+import java.util.*;
+
+import static android.support.test.InstrumentationRegistry.*;
+import static android.support.test.espresso.Espresso.*;
+import static android.support.test.espresso.action.ViewActions.*;
+import static android.support.test.espresso.matcher.ViewMatchers.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.isoron.uhabits.BaseUIAutomatorTest.device;
+import static org.isoron.uhabits.acceptance.steps.CommonSteps.clickText;
+
+public abstract class ListHabitsSteps
+{
+ public static void clickMenu(MenuItem item)
+ {
+ switch (item)
+ {
+ case ABOUT:
+ clickTextInsideOverflowMenu(R.string.about);
+ break;
+
+ case HELP:
+ clickTextInsideOverflowMenu(R.string.help);
+ break;
+
+ case SETTINGS:
+ clickTextInsideOverflowMenu(R.string.settings);
+ break;
+
+ case CREATE_HABIT:
+ clickViewWithId(R.id.actionAdd);
+ break;
+
+ case EDIT_HABIT:
+ clickViewWithId(R.id.action_edit_habit);
+ break;
+
+ case DELETE:
+ clickTextInsideOverflowMenu(R.string.delete);
+ break;
+
+ case ARCHIVE:
+ clickTextInsideOverflowMenu(R.string.archive);
+ break;
+
+ case UNARCHIVE:
+ clickTextInsideOverflowMenu(R.string.unarchive);
+ break;
+
+ case HIDE_ARCHIVED:
+ clickViewWithId(R.id.action_filter);
+ clickText(R.string.hide_archived);
+ break;
+ }
+ }
+
+ private static void clickTextInsideOverflowMenu(int id)
+ {
+ UiObject toolbar = device.findObject(
+ new UiSelector().resourceId("org.isoron.uhabits:id/toolbar"));
+ if(toolbar.exists())
+ {
+ onView(allOf(withContentDescription("More options"), withParent
+ (withParent(withId(R.id.toolbar))))).perform(click());
+ }
+ else
+ {
+ openActionBarOverflowOrOptionsMenu(getTargetContext());
+ }
+
+ onView(withText(id)).perform(click());
+ }
+
+ private static void clickViewWithId(int id)
+ {
+ onView(withId(id)).perform(click());
+ }
+
+ private static ViewAction longClickEveryDescendantWithClass(Class cls)
+ {
+ return new ViewAction()
+ {
+
+ @Override
+ public Matcher getConstraints()
+ {
+ return isEnabled();
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return "perform on children";
+ }
+
+ @Override
+ public void perform(UiController uiController, View view)
+ {
+ LinkedList stack = new LinkedList<>();
+ if (view instanceof ViewGroup) stack.push((ViewGroup) view);
+
+ while (!stack.isEmpty())
+ {
+ ViewGroup vg = stack.pop();
+ for (int i = 0; i < vg.getChildCount(); i++)
+ {
+ View v = vg.getChildAt(i);
+ if (v instanceof ViewGroup) stack.push((ViewGroup) v);
+ if (cls.isInstance(v))
+ {
+ v.performLongClick();
+ uiController.loopMainThreadUntilIdle();
+ }
+ }
+ }
+ }
+ };
+ }
+
+ public static void longPressCheckmarks(String habit)
+ {
+ CommonSteps.scrollToText(habit);
+ onView(allOf(hasDescendant(withText(habit)),
+ withClassName(endsWith("HabitCardView")))).perform(
+ longClickEveryDescendantWithClass(CheckmarkButtonView.class));
+ }
+
+ public enum MenuItem
+ {
+ ABOUT, HELP, SETTINGS, EDIT_HABIT, DELETE, ARCHIVE, HIDE_ARCHIVED,
+ UNARCHIVE, CREATE_HABIT
+ }
+}
diff --git a/uhabits-android/src/androidTest/java/org/isoron/uhabits/integration/SavedStateTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/integration/SavedStateTest.java
index 7250c62bd..8bc086e2f 100644
--- a/uhabits-android/src/androidTest/java/org/isoron/uhabits/integration/SavedStateTest.java
+++ b/uhabits-android/src/androidTest/java/org/isoron/uhabits/integration/SavedStateTest.java
@@ -19,6 +19,8 @@
package org.isoron.uhabits.integration;
+import android.support.test.filters.*;
+
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.about.*;
import org.isoron.uhabits.activities.habits.list.*;
@@ -26,6 +28,7 @@ import org.junit.*;
import static java.lang.Thread.*;
+@LargeTest
public class SavedStateTest extends BaseUIAutomatorTest
{
/**
diff --git a/app/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java b/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java
similarity index 100%
rename from app/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java
rename to uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java
diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.java b/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.java
index caaf25957..91bfbd037 100644
--- a/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.java
+++ b/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.java
@@ -85,8 +85,8 @@ public class HabitsApplication extends Application
if (isTestMode())
{
- File db = DatabaseUtils.getDatabaseFile(context);
- if (db.exists()) db.delete();
+// File db = DatabaseUtils.getDatabaseFile(context);
+// if (db.exists()) db.delete();
}
try
diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.java b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.java
index de7037dfc..c8c5808c4 100644
--- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.java
+++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/about/AboutScreen.java
@@ -23,11 +23,13 @@ import android.support.annotation.*;
import android.widget.*;
import org.isoron.androidbase.activities.*;
-import org.isoron.uhabits.intents.*;
import org.isoron.uhabits.core.ui.screens.about.*;
+import org.isoron.uhabits.intents.*;
import javax.inject.*;
+import static org.isoron.uhabits.core.ui.screens.about.AboutBehavior.Message.*;
+
public class AboutScreen extends BaseScreen implements AboutBehavior.Screen
{
@NonNull
@@ -44,7 +46,9 @@ public class AboutScreen extends BaseScreen implements AboutBehavior.Screen
@Override
public void showMessage(AboutBehavior.Message message)
{
- Toast.makeText(activity, "OK", Toast.LENGTH_LONG).show();
+ if (message == YOU_ARE_NOW_A_DEVELOPER) Toast
+ .makeText(activity, "You are now a developer", Toast.LENGTH_LONG)
+ .show();
}
@Override
diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/preferences/AndroidPreferences.java b/uhabits-android/src/main/java/org/isoron/uhabits/preferences/AndroidPreferences.java
index 76aad2696..4e4641aec 100644
--- a/uhabits-android/src/main/java/org/isoron/uhabits/preferences/AndroidPreferences.java
+++ b/uhabits-android/src/main/java/org/isoron/uhabits/preferences/AndroidPreferences.java
@@ -80,6 +80,13 @@ public class AndroidPreferences
}
}
+ public void reset()
+ {
+ if(!HabitsApplication.isTestMode()) throw new IllegalStateException(
+ "this method can only be used while testing");
+ prefs.edit().clear().commit();
+ }
+
public void setDefaultOrder(HabitList.Order order)
{
prefs.edit().putString("pref_default_order", order.name()).apply();
diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/about/AboutBehavior.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/about/AboutBehavior.java
index 996084e40..6fc091fad 100644
--- a/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/about/AboutBehavior.java
+++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/about/AboutBehavior.java
@@ -42,7 +42,7 @@ public class AboutBehavior
public void onPressDeveloperCountdown()
{
developerCountdown--;
- if (developerCountdown <= 0)
+ if (developerCountdown == 0)
{
prefs.setDeveloper(true);
screen.showMessage(Message.YOU_ARE_NOW_A_DEVELOPER);
diff --git a/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/about/AboutBehaviorTest.java b/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/about/AboutBehaviorTest.java
new file mode 100644
index 000000000..f39984abb
--- /dev/null
+++ b/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/screens/about/AboutBehaviorTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 Álinson Santos Xavier
+ *
+ * This file is part of Loop Habit Tracker.
+ *
+ * Loop Habit Tracker is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Loop Habit Tracker is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+package org.isoron.uhabits.core.ui.screens.about;
+
+import org.isoron.uhabits.*;
+import org.isoron.uhabits.core.preferences.*;
+import org.junit.*;
+import org.mockito.*;
+
+import static org.isoron.uhabits.core.ui.screens.about.AboutBehavior.Message.YOU_ARE_NOW_A_DEVELOPER;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class AboutBehaviorTest extends BaseUnitTest
+{
+ private AboutBehavior behavior;
+
+ @Mock
+ private Preferences prefs;
+
+ @Mock
+ private AboutBehavior.Screen screen;
+
+ @Before
+ public void setUp()
+ {
+ behavior = new AboutBehavior(prefs, screen);
+ }
+
+ @Test
+ public void onPressDeveloperCountdown() throws Exception
+ {
+ behavior.onPressDeveloperCountdown();
+ behavior.onPressDeveloperCountdown();
+ behavior.onPressDeveloperCountdown();
+ behavior.onPressDeveloperCountdown();
+ verifyZeroInteractions(screen);
+ verifyZeroInteractions(prefs);
+
+ behavior.onPressDeveloperCountdown();
+ verify(screen).showMessage(YOU_ARE_NOW_A_DEVELOPER);
+ verify(prefs).setDeveloper(true);
+
+ behavior.onPressDeveloperCountdown();
+ verifyZeroInteractions(screen);
+ verifyZeroInteractions(prefs);
+ }
+
+ @Test
+ public void onRateApp() throws Exception
+ {
+ behavior.onRateApp();
+ verify(screen).showRateAppWebsite();
+ }
+
+ @Test
+ public void onSendFeedback() throws Exception
+ {
+ behavior.onSendFeedback();
+ verify(screen).showSendFeedbackScreen();
+ }
+
+ @Test
+ public void onTranslateApp() throws Exception
+ {
+ behavior.onTranslateApp();
+ verify(screen).showTranslationWebsite();
+ }
+
+ @Test
+ public void onViewSourceCode() throws Exception
+ {
+ behavior.onViewSourceCode();
+ verify(screen).showSourceCodeWebsite();
+ }
+
+}
\ No newline at end of file