mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Implement acceptance tests for some basic features
This commit is contained in:
4
build.sh
4
build.sh
@@ -147,9 +147,9 @@ install_test_apk() {
|
|||||||
run_instrumented_tests() {
|
run_instrumented_tests() {
|
||||||
log_info "Running instrumented tests"
|
log_info "Running instrumented tests"
|
||||||
$ADB shell am instrument \
|
$ADB shell am instrument \
|
||||||
-r -e coverage true \
|
-r -e coverage true -e size medium \
|
||||||
-w ${PACKAGE_NAME}.test/android.support.test.runner.AndroidJUnitRunner \
|
-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/
|
mkdir -p ${OUTPUTS_DIR}/code-coverage/connected/
|
||||||
$ADB pull /data/user/0/${PACKAGE_NAME}/files/coverage.ec \
|
$ADB pull /data/user/0/${PACKAGE_NAME}/files/coverage.ec \
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ dependencies {
|
|||||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
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.uiautomator:uiautomator-v18:2.1.1'
|
||||||
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
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'
|
androidTestCompile 'com.linkedin.testbutler:test-butler-library:1.3.1'
|
||||||
|
|
||||||
implementation('com.opencsv:opencsv:3.9') {
|
implementation('com.opencsv:opencsv:3.9') {
|
||||||
|
|||||||
27
uhabits-android/src/androidTest/AndroidManifest.xml
Normal file
27
uhabits-android/src/androidTest/AndroidManifest.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
~
|
||||||
|
~ 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 <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<manifest
|
||||||
|
package="org.isoron.uhabits"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<instrumentation>
|
||||||
|
<meta-data android:name="notPackage" android:value="net.bytebuddy"/>
|
||||||
|
</instrumentation>
|
||||||
|
</manifest>
|
||||||
BIN
uhabits-android/src/androidTest/assets/test.db
Normal file
BIN
uhabits-android/src/androidTest/assets/test.db
Normal file
Binary file not shown.
@@ -25,6 +25,7 @@ import android.content.res.*;
|
|||||||
import android.os.*;
|
import android.os.*;
|
||||||
import android.support.annotation.*;
|
import android.support.annotation.*;
|
||||||
import android.support.test.*;
|
import android.support.test.*;
|
||||||
|
import android.support.test.filters.*;
|
||||||
import android.util.*;
|
import android.util.*;
|
||||||
|
|
||||||
import junit.framework.*;
|
import junit.framework.*;
|
||||||
@@ -44,6 +45,7 @@ import java.util.concurrent.*;
|
|||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.hamcrest.MatcherAssert.*;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
|
||||||
|
@MediumTest
|
||||||
public class BaseAndroidTest extends TestCase
|
public class BaseAndroidTest extends TestCase
|
||||||
{
|
{
|
||||||
// 8:00am, January 25th, 2015 (UTC)
|
// 8:00am, January 25th, 2015 (UTC)
|
||||||
|
|||||||
@@ -20,46 +20,66 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
|
import android.support.test.filters.*;
|
||||||
import android.support.test.uiautomator.*;
|
import android.support.test.uiautomator.*;
|
||||||
|
|
||||||
import com.linkedin.android.testbutler.*;
|
import com.linkedin.android.testbutler.*;
|
||||||
|
|
||||||
import org.isoron.androidbase.*;
|
import org.isoron.androidbase.*;
|
||||||
|
import org.isoron.androidbase.utils.*;
|
||||||
|
import org.isoron.uhabits.preferences.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
import static android.support.test.InstrumentationRegistry.*;
|
import static android.support.test.InstrumentationRegistry.*;
|
||||||
import static android.support.test.uiautomator.UiDevice.*;
|
import static android.support.test.uiautomator.UiDevice.*;
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
public class BaseUIAutomatorTest
|
public class BaseUIAutomatorTest
|
||||||
{
|
{
|
||||||
static final String PKG = "org.isoron.uhabits";
|
private static final String PKG = "org.isoron.uhabits";
|
||||||
|
|
||||||
protected UiDevice device;
|
public static UiDevice device;
|
||||||
|
|
||||||
|
private HabitsComponent component;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp()
|
public void setUp() throws IOException
|
||||||
{
|
{
|
||||||
TestButler.setup(getTargetContext());
|
TestButler.setup(getTargetContext());
|
||||||
|
TestButler.verifyAnimationsDisabled(getTargetContext());
|
||||||
device = getInstance(getInstrumentation());
|
device = getInstance(getInstrumentation());
|
||||||
|
|
||||||
HabitsComponent component = DaggerHabitsComponent
|
component = DaggerHabitsComponent
|
||||||
.builder()
|
.builder()
|
||||||
.appModule(new AppModule(getTargetContext()))
|
.appModule(new AppModule(getTargetContext()))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
AndroidPreferences prefs = component.getPreferences();
|
||||||
|
prefs.reset();
|
||||||
|
prefs.setFirstRun(false);
|
||||||
|
|
||||||
HabitsApplication.setComponent(component);
|
HabitsApplication.setComponent(component);
|
||||||
|
|
||||||
|
FileUtils.copy(getContext().getAssets().open("test.db"),
|
||||||
|
DatabaseUtils.getDatabaseFile(getTargetContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown()
|
public void tearDown() throws Exception
|
||||||
{
|
{
|
||||||
|
device.pressHome();
|
||||||
|
device.waitForIdle();
|
||||||
TestButler.teardown(getTargetContext());
|
TestButler.teardown(getTargetContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startActivity(Class cls)
|
public static void startActivity(Class cls)
|
||||||
{
|
{
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setComponent(new ComponentName(PKG, cls.getCanonicalName()));
|
intent.setComponent(new ComponentName(PKG, cls.getCanonicalName()));
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
getContext().startActivity(intent);
|
getContext().startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<View> getConstraints()
|
||||||
|
{
|
||||||
|
return isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription()
|
||||||
|
{
|
||||||
|
return "perform on children";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void perform(UiController uiController, View view)
|
||||||
|
{
|
||||||
|
LinkedList<ViewGroup> 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.integration;
|
package org.isoron.uhabits.integration;
|
||||||
|
|
||||||
|
import android.support.test.filters.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.activities.about.*;
|
import org.isoron.uhabits.activities.about.*;
|
||||||
import org.isoron.uhabits.activities.habits.list.*;
|
import org.isoron.uhabits.activities.habits.list.*;
|
||||||
@@ -26,6 +28,7 @@ import org.junit.*;
|
|||||||
|
|
||||||
import static java.lang.Thread.*;
|
import static java.lang.Thread.*;
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
public class SavedStateTest extends BaseUIAutomatorTest
|
public class SavedStateTest extends BaseUIAutomatorTest
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -85,8 +85,8 @@ public class HabitsApplication extends Application
|
|||||||
|
|
||||||
if (isTestMode())
|
if (isTestMode())
|
||||||
{
|
{
|
||||||
File db = DatabaseUtils.getDatabaseFile(context);
|
// File db = DatabaseUtils.getDatabaseFile(context);
|
||||||
if (db.exists()) db.delete();
|
// if (db.exists()) db.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -23,11 +23,13 @@ import android.support.annotation.*;
|
|||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
|
|
||||||
import org.isoron.androidbase.activities.*;
|
import org.isoron.androidbase.activities.*;
|
||||||
import org.isoron.uhabits.intents.*;
|
|
||||||
import org.isoron.uhabits.core.ui.screens.about.*;
|
import org.isoron.uhabits.core.ui.screens.about.*;
|
||||||
|
import org.isoron.uhabits.intents.*;
|
||||||
|
|
||||||
import javax.inject.*;
|
import javax.inject.*;
|
||||||
|
|
||||||
|
import static org.isoron.uhabits.core.ui.screens.about.AboutBehavior.Message.*;
|
||||||
|
|
||||||
public class AboutScreen extends BaseScreen implements AboutBehavior.Screen
|
public class AboutScreen extends BaseScreen implements AboutBehavior.Screen
|
||||||
{
|
{
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -44,7 +46,9 @@ public class AboutScreen extends BaseScreen implements AboutBehavior.Screen
|
|||||||
@Override
|
@Override
|
||||||
public void showMessage(AboutBehavior.Message message)
|
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
|
@Override
|
||||||
|
|||||||
@@ -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)
|
public void setDefaultOrder(HabitList.Order order)
|
||||||
{
|
{
|
||||||
prefs.edit().putString("pref_default_order", order.name()).apply();
|
prefs.edit().putString("pref_default_order", order.name()).apply();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class AboutBehavior
|
|||||||
public void onPressDeveloperCountdown()
|
public void onPressDeveloperCountdown()
|
||||||
{
|
{
|
||||||
developerCountdown--;
|
developerCountdown--;
|
||||||
if (developerCountdown <= 0)
|
if (developerCountdown == 0)
|
||||||
{
|
{
|
||||||
prefs.setDeveloper(true);
|
prefs.setDeveloper(true);
|
||||||
screen.showMessage(Message.YOU_ARE_NOW_A_DEVELOPER);
|
screen.showMessage(Message.YOU_ARE_NOW_A_DEVELOPER);
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user