@ -1,36 +1,22 @@
|
||||
#built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
|
||||
# files for the dex VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.apk
|
||||
*.class
|
||||
|
||||
# generated files
|
||||
bin/
|
||||
gen/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Windows thumbnail db
|
||||
Thumbs.db
|
||||
|
||||
# OSX files
|
||||
*.dex
|
||||
*.iml
|
||||
*.local.*
|
||||
*.swp
|
||||
*.trace
|
||||
*~
|
||||
.DS_Store
|
||||
|
||||
# Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# Android Studio
|
||||
.idea
|
||||
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
|
||||
.gradle
|
||||
build/
|
||||
*.iml
|
||||
|
||||
.idea
|
||||
.project
|
||||
Thumbs.db
|
||||
art/
|
||||
*.actual.png
|
||||
bin/
|
||||
build/
|
||||
captures/
|
||||
docs/
|
||||
gen/
|
||||
local.properties
|
||||
|
@ -1,3 +0,0 @@
|
||||
[submodule "libs/drag-sort-listview"]
|
||||
path = libs/drag-sort-listview
|
||||
url = https://github.com/iSoron/drag-sort-listview.git
|
@ -0,0 +1,3 @@
|
||||
-dontwarn java.beans.**
|
||||
-dontwarn java.lang.**
|
||||
-dontobfuscate
|
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 551 B |
After Width: | Height: | Size: 505 B |
After Width: | Height: | Size: 559 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits;
|
||||
|
||||
|
||||
import org.isoron.uhabits.models.sqlite.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
|
||||
import dagger.*;
|
||||
|
||||
@AppScope
|
||||
@Component(modules = {
|
||||
AppModule.class, SingleThreadTaskRunner.class, SQLModelFactory.class
|
||||
})
|
||||
public interface AndroidTestComponent extends AppComponent
|
||||
{
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import android.appwidget.*;
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.test.*;
|
||||
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.preferences.*;
|
||||
import org.isoron.uhabits.tasks.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class BaseAndroidTest
|
||||
{
|
||||
// 8:00am, January 25th, 2015 (UTC)
|
||||
public static final long FIXED_LOCAL_TIME = 1422172800000L;
|
||||
|
||||
private static boolean isLooperPrepared;
|
||||
|
||||
protected Context testContext;
|
||||
|
||||
protected Context targetContext;
|
||||
|
||||
protected Preferences prefs;
|
||||
|
||||
protected HabitList habitList;
|
||||
|
||||
protected TaskRunner taskRunner;
|
||||
|
||||
protected HabitLogger logger;
|
||||
|
||||
protected HabitFixtures fixtures;
|
||||
|
||||
protected CountDownLatch latch;
|
||||
|
||||
protected AndroidTestComponent component;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
if (!isLooperPrepared)
|
||||
{
|
||||
Looper.prepare();
|
||||
isLooperPrepared = true;
|
||||
}
|
||||
|
||||
targetContext = InstrumentationRegistry.getTargetContext();
|
||||
testContext = InstrumentationRegistry.getContext();
|
||||
|
||||
DateUtils.setFixedLocalTime(FIXED_LOCAL_TIME);
|
||||
setTheme(R.style.AppBaseTheme);
|
||||
|
||||
component = DaggerAndroidTestComponent
|
||||
.builder()
|
||||
.appModule(new AppModule(targetContext.getApplicationContext()))
|
||||
.build();
|
||||
|
||||
HabitsApplication.setComponent(component);
|
||||
prefs = component.getPreferences();
|
||||
habitList = component.getHabitList();
|
||||
taskRunner = component.getTaskRunner();
|
||||
logger = component.getHabitsLogger();
|
||||
|
||||
ModelFactory modelFactory = component.getModelFactory();
|
||||
fixtures = new HabitFixtures(modelFactory, habitList);
|
||||
|
||||
latch = new CountDownLatch(1);
|
||||
}
|
||||
|
||||
protected void assertWidgetProviderIsInstalled(Class componentClass)
|
||||
{
|
||||
ComponentName provider =
|
||||
new ComponentName(targetContext, componentClass);
|
||||
AppWidgetManager manager = AppWidgetManager.getInstance(targetContext);
|
||||
|
||||
List<ComponentName> installedProviders = new LinkedList<>();
|
||||
for (AppWidgetProviderInfo info : manager.getInstalledProviders())
|
||||
installedProviders.add(info.provider);
|
||||
|
||||
assertThat(installedProviders, hasItems(provider));
|
||||
}
|
||||
|
||||
protected void awaitLatch() throws InterruptedException
|
||||
{
|
||||
assertTrue(latch.await(60, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
protected void setTheme(@StyleRes int themeId)
|
||||
{
|
||||
targetContext.setTheme(themeId);
|
||||
StyledResources.setFixedTheme(themeId);
|
||||
}
|
||||
|
||||
protected void sleep(int time)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(time);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Looper;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
|
||||
import org.isoron.uhabits.helpers.DateHelper;
|
||||
import org.isoron.uhabits.helpers.UIHelper;
|
||||
import org.isoron.uhabits.tasks.BaseTask;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class BaseTest
|
||||
{
|
||||
protected Context testContext;
|
||||
protected Context targetContext;
|
||||
private static boolean isLooperPrepared;
|
||||
|
||||
public static final long FIXED_LOCAL_TIME = 1422172800000L; // 8:00am, January 25th, 2015 (UTC)
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
if(!isLooperPrepared)
|
||||
{
|
||||
Looper.prepare();
|
||||
isLooperPrepared = true;
|
||||
}
|
||||
|
||||
targetContext = InstrumentationRegistry.getTargetContext();
|
||||
testContext = InstrumentationRegistry.getContext();
|
||||
|
||||
UIHelper.setFixedTheme(R.style.AppBaseTheme);
|
||||
DateHelper.setFixedLocalTime(FIXED_LOCAL_TIME);
|
||||
}
|
||||
|
||||
protected void waitForAsyncTasks() throws InterruptedException, TimeoutException
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
return;
|
||||
}
|
||||
|
||||
BaseTask.waitForTasks(10000);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.DateUtils;
|
||||
|
||||
public class HabitFixtures
|
||||
{
|
||||
public boolean NON_DAILY_HABIT_CHECKS[] = {
|
||||
true, false, false, true, true, true, false, false, true, true
|
||||
};
|
||||
|
||||
private ModelFactory modelFactory;
|
||||
|
||||
private final HabitList habitList;
|
||||
|
||||
public HabitFixtures(ModelFactory modelFactory, HabitList habitList)
|
||||
{
|
||||
this.modelFactory = modelFactory;
|
||||
this.habitList = habitList;
|
||||
}
|
||||
|
||||
public Habit createEmptyHabit()
|
||||
{
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
habit.setName("Meditate");
|
||||
habit.setDescription("Did you meditate this morning?");
|
||||
habit.setColor(3);
|
||||
habit.setFrequency(Frequency.DAILY);
|
||||
habitList.add(habit);
|
||||
return habit;
|
||||
}
|
||||
|
||||
public Habit createLongHabit()
|
||||
{
|
||||
Habit habit = createEmptyHabit();
|
||||
habit.setFrequency(new Frequency(3, 7));
|
||||
habit.setColor(4);
|
||||
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
long today = DateUtils.getStartOfToday();
|
||||
int marks[] = { 0, 1, 3, 5, 7, 8, 9, 10, 12, 14, 15, 17, 19, 20, 26, 27,
|
||||
28, 50, 51, 52, 53, 54, 58, 60, 63, 65, 70, 71, 72, 73, 74, 75, 80,
|
||||
81, 83, 89, 90, 91, 95, 102, 103, 108, 109, 120};
|
||||
|
||||
for (int mark : marks)
|
||||
habit.getRepetitions().toggleTimestamp(today - mark * day);
|
||||
|
||||
return habit;
|
||||
}
|
||||
|
||||
public Habit createShortHabit()
|
||||
{
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
habit.setName("Wake up early");
|
||||
habit.setDescription("Did you wake up before 6am?");
|
||||
habit.setFrequency(new Frequency(2, 3));
|
||||
habitList.add(habit);
|
||||
|
||||
long timestamp = DateUtils.getStartOfToday();
|
||||
for (boolean c : NON_DAILY_HABIT_CHECKS)
|
||||
{
|
||||
if (c) habit.getRepetitions().toggleTimestamp(timestamp);
|
||||
timestamp -= DateUtils.millisecondsInOneDay;
|
||||
}
|
||||
|
||||
return habit;
|
||||
}
|
||||
|
||||
public void purgeHabits(HabitList habitList)
|
||||
{
|
||||
for (Habit h : habitList)
|
||||
habitList.remove(h);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits;
|
||||
|
||||
import android.os.*;
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.activities.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class HabitLoggerTest extends BaseAndroidTest
|
||||
{
|
||||
@Test
|
||||
public void testLogReminderScheduled() throws IOException
|
||||
{
|
||||
if (!isLogcatAvailable()) return;
|
||||
|
||||
long time = 1422277200000L; // 13:00 jan 26, 2015 (UTC)
|
||||
Habit habit = fixtures.createEmptyHabit();
|
||||
habit.setName("Write journal");
|
||||
|
||||
logger.logReminderScheduled(habit, time);
|
||||
|
||||
String expectedMsg = "Setting alarm (2015-01-26 130000): Wri\n";
|
||||
assertLogcatContains(expectedMsg);
|
||||
}
|
||||
|
||||
protected void assertLogcatContains(String expectedMsg) throws IOException
|
||||
{
|
||||
BaseSystem system = new BaseSystem(targetContext);
|
||||
String logcat = system.getLogcat();
|
||||
assertThat(logcat, containsString(expectedMsg));
|
||||
}
|
||||
|
||||
protected boolean isLogcatAvailable()
|
||||
{
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.common.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class HistoryChartTest extends BaseViewTest
|
||||
{
|
||||
private static final String BASE_PATH = "common/HistoryChart/";
|
||||
|
||||
private HistoryChart chart;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
fixtures.purgeHabits(habitList);
|
||||
Habit habit = fixtures.createLongHabit();
|
||||
|
||||
chart = new HistoryChart(targetContext);
|
||||
chart.setCheckmarks(habit.getCheckmarks().getAllValues());
|
||||
chart.setColor(ColorUtils.getAndroidTestColor(habit.getColor()));
|
||||
measureView(chart, dpToPixels(400), dpToPixels(200));
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void tapDate_atInvalidLocations() throws Throwable
|
||||
// {
|
||||
// int expectedCheckmarkValues[] = habit.getCheckmarks().getAllValues();
|
||||
//
|
||||
// chart.setIsEditable(true);
|
||||
// tap(chart, 118, 13); // header
|
||||
// tap(chart, 336, 60); // tomorrow's square
|
||||
// tap(chart, 370, 60); // right axis
|
||||
// waitForAsyncTasks();
|
||||
//
|
||||
// int actualCheckmarkValues[] = habit.getCheckmarks().getAllValues();
|
||||
// assertThat(actualCheckmarkValues, equalTo(expectedCheckmarkValues));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void tapDate_withEditableView() throws Throwable
|
||||
// {
|
||||
// chart.setIsEditable(true);
|
||||
// tap(chart, 340, 40); // today's square
|
||||
// waitForAsyncTasks();
|
||||
//
|
||||
// long today = DateUtils.getStartOfToday();
|
||||
// assertFalse(habit.getRepetitions().containsTimestamp(today));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void tapDate_withReadOnlyView() throws Throwable
|
||||
// {
|
||||
// chart.setIsEditable(false);
|
||||
// tap(chart, 340, 40); // today's square
|
||||
// waitForAsyncTasks();
|
||||
//
|
||||
// long today = DateUtils.getStartOfToday();
|
||||
// assertTrue(habit.getRepetitions().containsTimestamp(today));
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testRender() throws Throwable
|
||||
{
|
||||
assertRenders(chart, BASE_PATH + "render.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_withDataOffset() throws Throwable
|
||||
{
|
||||
chart.onScroll(null, null, -dpToPixels(150), 0);
|
||||
chart.invalidate();
|
||||
|
||||
assertRenders(chart, BASE_PATH + "renderDataOffset.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_withDifferentSize() throws Throwable
|
||||
{
|
||||
measureView(chart, dpToPixels(200), dpToPixels(200));
|
||||
assertRenders(chart, BASE_PATH + "renderDifferentSize.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_withTransparentBackground() throws Throwable
|
||||
{
|
||||
chart.setIsBackgroundTransparent(true);
|
||||
assertRenders(chart, BASE_PATH + "renderTransparent.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.list.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class CheckmarkButtonViewTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/list/CheckmarkButtonView/";
|
||||
|
||||
private CountDownLatch latch;
|
||||
|
||||
private CheckmarkButtonView view;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
setSimilarityCutoff(0.03f);
|
||||
|
||||
latch = new CountDownLatch(1);
|
||||
view = new CheckmarkButtonView(targetContext);
|
||||
view.setValue(Checkmark.UNCHECKED);
|
||||
view.setColor(ColorUtils.getAndroidTestColor(7));
|
||||
|
||||
measureView(view, dpToPixels(40), dpToPixels(40));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_explicitCheck() throws Exception
|
||||
{
|
||||
view.setValue(Checkmark.CHECKED_EXPLICITLY);
|
||||
assertRendersCheckedExplicitly();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_implicitCheck() throws Exception
|
||||
{
|
||||
view.setValue(Checkmark.CHECKED_IMPLICITLY);
|
||||
assertRendersCheckedImplicitly();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_unchecked() throws Exception
|
||||
{
|
||||
view.setValue(Checkmark.UNCHECKED);
|
||||
assertRendersUnchecked();
|
||||
}
|
||||
|
||||
protected void assertRendersCheckedExplicitly() throws IOException
|
||||
{
|
||||
assertRenders(view, PATH + "render_explicit_check.png");
|
||||
}
|
||||
|
||||
protected void assertRendersCheckedImplicitly() throws IOException
|
||||
{
|
||||
assertRenders(view, PATH + "render_implicit_check.png");
|
||||
}
|
||||
|
||||
protected void assertRendersUnchecked() throws IOException
|
||||
{
|
||||
assertRenders(view, PATH + "render_unchecked.png");
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testLongClick() throws Exception
|
||||
// {
|
||||
// setOnToggleListener();
|
||||
// view.performLongClick();
|
||||
// waitForLatch();
|
||||
// assertRendersCheckedExplicitly();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testClick_withShortToggle_fromUnchecked() throws Exception
|
||||
// {
|
||||
// Preferences.getInstance().setShortToggleEnabled(true);
|
||||
// view.setValue(Checkmark.UNCHECKED);
|
||||
// setOnToggleListenerAndPerformClick();
|
||||
// assertRendersCheckedExplicitly();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testClick_withShortToggle_fromChecked() throws Exception
|
||||
// {
|
||||
// Preferences.getInstance().setShortToggleEnabled(true);
|
||||
// view.setValue(Checkmark.CHECKED_EXPLICITLY);
|
||||
// setOnToggleListenerAndPerformClick();
|
||||
// assertRendersUnchecked();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testClick_withShortToggle_withoutListener() throws Exception
|
||||
// {
|
||||
// Preferences.getInstance().setShortToggleEnabled(true);
|
||||
// view.setValue(Checkmark.CHECKED_EXPLICITLY);
|
||||
// view.setController(null);
|
||||
// view.performClick();
|
||||
// assertRendersUnchecked();
|
||||
// }
|
||||
//
|
||||
// protected void setOnToggleListenerAndPerformClick() throws InterruptedException
|
||||
// {
|
||||
// setOnToggleListener();
|
||||
// view.performClick();
|
||||
// waitForLatch();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testClick_withoutShortToggle() throws Exception
|
||||
// {
|
||||
// Preferences.getInstance().setShortToggleEnabled(false);
|
||||
// setOnInvalidToggleListener();
|
||||
// view.performClick();
|
||||
// waitForLatch();
|
||||
// assertRendersUnchecked();
|
||||
// }
|
||||
|
||||
// protected void setOnInvalidToggleListener()
|
||||
// {
|
||||
// view.setController(new CheckmarkButtonView.Controller()
|
||||
// {
|
||||
// @Override
|
||||
// public void onToggleCheckmark(CheckmarkButtonView view, long timestamp)
|
||||
// {
|
||||
// fail();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onInvalidToggle(CheckmarkButtonView v)
|
||||
// {
|
||||
// assertThat(v, equalTo(view));
|
||||
// latch.countDown();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// protected void setOnToggleListener()
|
||||
// {
|
||||
// view.setController(new CheckmarkButtonView.Controller()
|
||||
// {
|
||||
// @Override
|
||||
// public void onToggleCheckmark(CheckmarkButtonView v, long t)
|
||||
// {
|
||||
// assertThat(v, equalTo(view));
|
||||
// assertThat(t, equalTo(DateUtils.getStartOfToday()));
|
||||
// latch.countDown();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onInvalidToggle(CheckmarkButtonView view)
|
||||
// {
|
||||
// fail();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.list.views;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.models.Checkmark;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.BaseViewTest;
|
||||
import org.isoron.uhabits.utils.ColorUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class CheckmarkPanelViewTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/list/CheckmarkPanelView/";
|
||||
|
||||
private CountDownLatch latch;
|
||||
private CheckmarkPanelView view;
|
||||
private int checkmarks[];
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
setSimilarityCutoff(0.03f);
|
||||
prefs.setShouldReverseCheckmarks(false);
|
||||
|
||||
Habit habit = fixtures.createEmptyHabit();
|
||||
|
||||
latch = new CountDownLatch(1);
|
||||
checkmarks = new int[]{
|
||||
Checkmark.CHECKED_EXPLICITLY, Checkmark.UNCHECKED,
|
||||
Checkmark.CHECKED_IMPLICITLY, Checkmark.CHECKED_EXPLICITLY};
|
||||
|
||||
view = new CheckmarkPanelView(targetContext);
|
||||
view.setHabit(habit);
|
||||
view.setCheckmarkValues(checkmarks);
|
||||
view.setColor(ColorUtils.getAndroidTestColor(7));
|
||||
|
||||
measureView(view, dpToPixels(200), dpToPixels(200));
|
||||
}
|
||||
|
||||
// protected void waitForLatch() throws InterruptedException
|
||||
// {
|
||||
// assertTrue("Latch timeout", latch.await(1, TimeUnit.SECONDS));
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testToggleCheckmark_withLeftToRight() throws Exception
|
||||
// {
|
||||
// setToggleListener();
|
||||
// view.getButton(1).performToggle();
|
||||
// waitForLatch();
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testToggleCheckmark_withReverseCheckmarks() throws Exception
|
||||
// {
|
||||
// prefs.setShouldReverseCheckmarks(true);
|
||||
// view.setCheckmarkValues(checkmarks); // refresh after preference change
|
||||
//
|
||||
// setToggleListener();
|
||||
// view.getButton(2).performToggle();
|
||||
// waitForLatch();
|
||||
// }
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.list.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class HabitCardViewTest extends BaseViewTest
|
||||
{
|
||||
private HabitCardView view;
|
||||
|
||||
public static final String PATH = "habits/list/HabitCardView/";
|
||||
|
||||
private HabitCardView.Controller controller;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
setTheme(R.style.AppBaseTheme);
|
||||
|
||||
habit = fixtures.createLongHabit();
|
||||
CheckmarkList checkmarks = habit.getCheckmarks();
|
||||
|
||||
long today = DateUtils.getStartOfToday();
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
int[] values = checkmarks.getValues(today - 5 * day, today);
|
||||
|
||||
controller = mock(HabitCardView.Controller.class);
|
||||
|
||||
view = new HabitCardView(targetContext);
|
||||
view.setHabit(habit);
|
||||
view.setCheckmarkValues(values);
|
||||
view.setSelected(false);
|
||||
view.setScore(habit.getScores().getTodayValue());
|
||||
view.setController(controller);
|
||||
measureView(view, dpToPixels(400), dpToPixels(50));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender_selected() throws Exception
|
||||
{
|
||||
view.setSelected(true);
|
||||
measureView(view, dpToPixels(400), dpToPixels(50));
|
||||
assertRenders(view, PATH + "render_selected.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeModel() throws Exception
|
||||
{
|
||||
habit.setName("Wake up early");
|
||||
habit.setColor(2);
|
||||
habit.getObservable().notifyListeners();
|
||||
assertRenders(view, PATH + "render_changed.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.list.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.activities.habits.list.model.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class HintViewTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/list/HintView/";
|
||||
|
||||
private HintView view;
|
||||
|
||||
private HintList list;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
view = new HintView(targetContext);
|
||||
list = mock(HintList.class);
|
||||
view.setHints(list);
|
||||
measureView(view, 400, 200);
|
||||
|
||||
String text =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
|
||||
|
||||
when(list.shouldShow()).thenReturn(true);
|
||||
when(list.pop()).thenReturn(text);
|
||||
|
||||
view.showNext();
|
||||
skipAnimation(view);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClick() throws Exception
|
||||
{
|
||||
assertThat(view.getAlpha(), equalTo(1f));
|
||||
view.performClick();
|
||||
skipAnimation(view);
|
||||
assertThat(view.getAlpha(), equalTo(0f));
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.show.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class FrequencyCardTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/show/FrequencyCard/";
|
||||
|
||||
private FrequencyCard view;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = (FrequencyCard) LayoutInflater
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById(R.id.frequencyCard);
|
||||
|
||||
view.setHabit(habit);
|
||||
view.refreshData();
|
||||
|
||||
measureView(view, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.show.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class HistoryCardTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/show/HistoryCard/";
|
||||
|
||||
private HistoryCard view;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = (HistoryCard) LayoutInflater
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById(R.id.historyCard);
|
||||
|
||||
view.setHabit(habit);
|
||||
view.refreshData();
|
||||
|
||||
measureView(view, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.show.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class OverviewCardTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/show/OverviewCard/";
|
||||
|
||||
private OverviewCard view;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = (OverviewCard) LayoutInflater
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById(R.id.overviewCard);
|
||||
|
||||
view.setHabit(habit);
|
||||
view.refreshData();
|
||||
measureView(view, 800, 300);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.show.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class ScoreCardTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/show/ScoreCard/";
|
||||
|
||||
private ScoreCard view;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = (ScoreCard) LayoutInflater
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById(R.id.scoreCard);
|
||||
|
||||
view.setHabit(habit);
|
||||
view.refreshData();
|
||||
measureView(view, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.show.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class StreakCardTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/show/StreakCard/";
|
||||
|
||||
private StreakCard view;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
habit = fixtures.createLongHabit();
|
||||
|
||||
view = (StreakCard) LayoutInflater
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById(R.id.streakCard);
|
||||
|
||||
view.setHabit(habit);
|
||||
view.refreshData();
|
||||
|
||||
measureView(view, 800, 600);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.activities.habits.show.views;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
import android.view.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class SubtitleCardTest extends BaseViewTest
|
||||
{
|
||||
public static final String PATH = "habits/show/SubtitleCard/";
|
||||
|
||||
private SubtitleCard view;
|
||||
|
||||
private Habit habit;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
habit = fixtures.createLongHabit();
|
||||
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
|
||||
|
||||
view = (SubtitleCard) LayoutInflater
|
||||
.from(targetContext)
|
||||
.inflate(R.layout.show_habit, null)
|
||||
.findViewById(R.id.subtitleCard);
|
||||
|
||||
view.setHabit(habit);
|
||||
view.refreshData();
|
||||
|
||||
measureView(view, 800, 200);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRender() throws Exception
|
||||
{
|
||||
assertRenders(view, PATH + "render.png");
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.espresso;
|
||||
|
||||
import android.support.test.espresso.*;
|
||||
import android.support.test.espresso.contrib.*;
|
||||
|
||||
import org.hamcrest.*;
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static android.support.test.espresso.Espresso.*;
|
||||
import static android.support.test.espresso.Espresso.pressBack;
|
||||
import static android.support.test.espresso.action.ViewActions.*;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.*;
|
||||
import static android.support.test.espresso.matcher.RootMatchers.*;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.Visibility.*;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class MainActivityActions
|
||||
{
|
||||
public static String addHabit()
|
||||
{
|
||||
return addHabit(false);
|
||||
}
|
||||
|
||||
public static String addHabit(boolean openDialogs)
|
||||
{
|
||||
String name = "New Habit " + new Random().nextInt(1000000);
|
||||
String description = "Did you perform your new habit today?";
|
||||
String num = "4";
|
||||
String den = "8";
|
||||
|
||||
onView(withId(R.id.actionAdd)).perform(click());
|
||||
|
||||
typeHabitData(name, description, num, den);
|
||||
|
||||
if (openDialogs)
|
||||
{
|
||||
onView(withId(R.id.buttonPickColor)).perform(click());
|
||||
pressBack();
|
||||
onView(withId(R.id.tvReminderTime)).perform(click());
|
||||
onView(withText("Done")).perform(click());
|
||||
onView(withId(R.id.tvReminderDays)).perform(click());
|
||||
onView(withText("OK")).perform(click());
|
||||
}
|
||||
|
||||
onView(withId(R.id.buttonSave)).perform(click());
|
||||
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name))).onChildView(withId(R.id.label));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static void assertHabitExists(String name)
|
||||
{
|
||||
List<String> names = new LinkedList<>();
|
||||
names.add(name);
|
||||
assertHabitsExist(names);
|
||||
}
|
||||
|
||||
public static void assertHabitsDontExist(List<String> names)
|
||||
{
|
||||
for (String name : names)
|
||||
onView(withId(R.id.listView)).check(matches(Matchers.not(
|
||||
HabitMatchers.containsHabit(HabitMatchers.withName(name)))));
|
||||
}
|
||||
|
||||
public static void assertHabitsExist(List<String> names)
|
||||
{
|
||||
for (String name : names)
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name))).check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
private static void clickHiddenMenuItem(int stringId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try the ActionMode overflow menu first
|
||||
onView(allOf(withContentDescription("More options"), withParent(
|
||||
withParent(withClassName(containsString("Action")))))).perform(
|
||||
click());
|
||||
}
|
||||
catch (Exception e1)
|
||||
{
|
||||
// Try the toolbar overflow menu
|
||||
onView(allOf(withContentDescription("More options"), withParent(
|
||||
withParent(withClassName(containsString("Toolbar")))))).perform(
|
||||
click());
|
||||
}
|
||||
|
||||
onView(withText(stringId)).perform(click());
|
||||
}
|
||||
|
||||
public static void clickMenuItem(int stringId)
|
||||
{
|
||||
try
|
||||
{
|
||||
onView(withText(stringId)).perform(click());
|
||||
}
|
||||
catch (Exception e1)
|
||||
{
|
||||
try
|
||||
{
|
||||
onView(withContentDescription(stringId)).perform(click());
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
clickHiddenMenuItem(stringId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void clickSettingsItem(String text)
|
||||
{
|
||||
onView(withClassName(containsString("RecyclerView"))).perform(
|
||||
RecyclerViewActions.actionOnItem(
|
||||
hasDescendant(withText(containsString(text))), click()));
|
||||
}
|
||||
|
||||
public static void deleteHabit(String name)
|
||||
{
|
||||
deleteHabits(Collections.singletonList(name));
|
||||
}
|
||||
|
||||
public static void deleteHabits(List<String> names)
|
||||
{
|
||||
selectHabits(names);
|
||||
clickMenuItem(R.string.delete);
|
||||
onView(withText("OK")).perform(click());
|
||||
assertHabitsDontExist(names);
|
||||
}
|
||||
|
||||
public static void selectHabit(String name)
|
||||
{
|
||||
selectHabits(Collections.singletonList(name));
|
||||
}
|
||||
|
||||
public static void selectHabits(List<String> names)
|
||||
{
|
||||
boolean first = true;
|
||||
for (String name : names)
|
||||
{
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(first ? longClick() : click());
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void typeHabitData(String name,
|
||||
String description,
|
||||
String num,
|
||||
String den)
|
||||
{
|
||||
onView(withId(R.id.tvName)).perform(replaceText(name));
|
||||
onView(withId(R.id.tvDescription)).perform(replaceText(description));
|
||||
|
||||
try
|
||||
{
|
||||
onView(allOf(withId(R.id.sFrequency),
|
||||
withEffectiveVisibility(VISIBLE))).perform(click());
|
||||
onData(allOf(instanceOf(String.class), startsWith("Custom")))
|
||||
.inRoot(isPlatformPopup())
|
||||
.perform(click());
|
||||
}
|
||||
catch (NoMatchingViewException e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
onView(withId(R.id.tvFreqNum)).perform(replaceText(num));
|
||||
onView(withId(R.id.tvFreqDen)).perform(replaceText(den));
|
||||
}
|
||||
}
|
@ -0,0 +1,317 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.espresso;
|
||||
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.support.test.*;
|
||||
import android.support.test.espresso.*;
|
||||
import android.support.test.espresso.intent.rule.*;
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.hamcrest.*;
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.activities.habits.list.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static android.support.test.espresso.Espresso.*;
|
||||
import static android.support.test.espresso.Espresso.pressBack;
|
||||
import static android.support.test.espresso.action.ViewActions.*;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.*;
|
||||
import static android.support.test.espresso.intent.Intents.*;
|
||||
import static android.support.test.espresso.intent.matcher.IntentMatchers.*;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.isoron.uhabits.espresso.HabitViewActions.*;
|
||||
import static org.isoron.uhabits.espresso.MainActivityActions.*;
|
||||
import static org.isoron.uhabits.espresso.ShowHabitActivityActions.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class MainTest
|
||||
{
|
||||
private SystemHelper sys;
|
||||
|
||||
@Rule
|
||||
public IntentsTestRule<ListHabitsActivity> activityRule =
|
||||
new IntentsTestRule<>(ListHabitsActivity.class);
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
Context context =
|
||||
InstrumentationRegistry.getInstrumentation().getContext();
|
||||
sys = new SystemHelper(context);
|
||||
sys.disableAllAnimations();
|
||||
sys.acquireWakeLock();
|
||||
sys.unlockScreen();
|
||||
|
||||
Instrumentation.ActivityResult okResult =
|
||||
new Instrumentation.ActivityResult(Activity.RESULT_OK,
|
||||
new Intent());
|
||||
|
||||
intending(hasAction(equalTo(Intent.ACTION_SEND))).respondWith(okResult);
|
||||
intending(hasAction(equalTo(Intent.ACTION_SENDTO))).respondWith(
|
||||
okResult);
|
||||
intending(hasAction(equalTo(Intent.ACTION_VIEW))).respondWith(okResult);
|
||||
|
||||
skipTutorial();
|
||||
}
|
||||
|
||||
public void skipTutorial()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
onView(allOf(withClassName(endsWith("AppCompatImageButton")),
|
||||
isDisplayed())).perform(click());
|
||||
}
|
||||
catch (NoMatchingViewException e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown()
|
||||
{
|
||||
sys.releaseWakeLock();
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens menu, clicks about, sees about screen.
|
||||
*/
|
||||
@Test
|
||||
public void testAbout()
|
||||
{
|
||||
clickMenuItem(R.string.about);
|
||||
onView(isRoot()).perform(swipeUp());
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, toggles a bunch of checkmarks, clicks the habit to
|
||||
* open the statistics screen, scrolls down to some views, then scrolls the
|
||||
* views backwards and forwards in time.
|
||||
*/
|
||||
@Test
|
||||
public void testAddHabitAndViewStats() throws InterruptedException
|
||||
{
|
||||
String name = addHabit(true);
|
||||
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name)))
|
||||
.onChildView(withId(R.id.checkmarkPanel))
|
||||
.perform(toggleAllCheckmarks());
|
||||
|
||||
Thread.sleep(1200);
|
||||
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(click());
|
||||
|
||||
onView(withId(R.id.scoreView)).perform(scrollTo(), swipeRight());
|
||||
|
||||
onView(withId(R.id.frequencyChart)).perform(scrollTo(), swipeRight());
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens the app, clicks the add button, types some bogus information,
|
||||
* tries to save, dialog displays an error.
|
||||
*/
|
||||
@Test
|
||||
public void testAddInvalidHabit()
|
||||
{
|
||||
onView(withId(R.id.actionAdd)).perform(click());
|
||||
|
||||
typeHabitData("", "", "15", "7");
|
||||
|
||||
onView(withId(R.id.buttonSave)).perform(click());
|
||||
onView(withId(R.id.tvName)).check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens the app, creates some habits, selects them, archives them,
|
||||
* select 'show archived' on the menu, selects the previously archived
|
||||
* habits and then deletes them.
|
||||
*/
|
||||
@Test
|
||||
public void testArchiveHabits()
|
||||
{
|
||||
List<String> names = new LinkedList<>();
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
names.add(addHabit());
|
||||
|
||||
selectHabits(names);
|
||||
|
||||
clickMenuItem(R.string.archive);
|
||||
assertHabitsDontExist(names);
|
||||
|
||||
clickMenuItem(R.string.show_archived);
|
||||
|
||||
assertHabitsExist(names);
|
||||
selectHabits(names);
|
||||
clickMenuItem(R.string.unarchive);
|
||||
|
||||
clickMenuItem(R.string.show_archived);
|
||||
|
||||
assertHabitsExist(names);
|
||||
deleteHabits(names);
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, selects the habit, clicks edit button, changes some
|
||||
* information about the habit, click save button, sees changes on the main
|
||||
* window, selects habit again, changes color, then deletes the habit.
|
||||
*/
|
||||
@Test
|
||||
public void testEditHabit()
|
||||
{
|
||||
String name = addHabit();
|
||||
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(longClick());
|
||||
|
||||
clickMenuItem(R.string.edit);
|
||||
|
||||
String modifiedName = "Modified " + new Random().nextInt(10000);
|
||||
typeHabitData(modifiedName, "", "1", "1");
|
||||
|
||||
onView(withId(R.id.buttonSave)).perform(click());
|
||||
|
||||
assertHabitExists(modifiedName);
|
||||
|
||||
selectHabit(modifiedName);
|
||||
clickMenuItem(R.string.color_picker_default_title);
|
||||
pressBack();
|
||||
|
||||
deleteHabit(modifiedName);
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, opens statistics page, clicks button to edit
|
||||
* history, adds some checkmarks, closes dialog, sees the modified history
|
||||
* calendar.
|
||||
*/
|
||||
@Test
|
||||
public void testEditHistory()
|
||||
{
|
||||
String name = addHabit();
|
||||
|
||||
onData(Matchers.allOf(is(instanceOf(Habit.class)),
|
||||
HabitMatchers.withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(click());
|
||||
|
||||
openHistoryEditor();
|
||||
onView(withClassName(endsWith("HabitHistoryView"))).perform(
|
||||
clickAtRandomLocations(20));
|
||||
|
||||
pressBack();
|
||||
onView(withId(R.id.historyChart)).perform(scrollTo(), swipeRight(),
|
||||
swipeLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, opens settings, clicks export as CSV, is asked what
|
||||
* activity should handle the file.
|
||||
*/
|
||||
@Test
|
||||
public void testExportCSV()
|
||||
{
|
||||
addHabit();
|
||||
clickMenuItem(R.string.settings);
|
||||
clickSettingsItem("Export as CSV");
|
||||
intended(hasAction(Intent.ACTION_SEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, exports full backup, deletes the habit, restores
|
||||
* backup, sees that the previously created habit has appeared back.
|
||||
*/
|
||||
@Test
|
||||
public void testExportImportDB()
|
||||
{
|
||||
String name = addHabit();
|
||||
|
||||
clickMenuItem(R.string.settings);
|
||||
|
||||
String date =
|
||||
DateFormats.getBackupDateFormat().format(DateUtils.getLocalTime());
|
||||
date = date.substring(0, date.length() - 2);
|
||||
|
||||
clickSettingsItem("Export full backup");
|
||||
intended(hasAction(Intent.ACTION_SEND));
|
||||
|
||||
deleteHabit(name);
|
||||
|
||||
clickMenuItem(R.string.settings);
|
||||
clickSettingsItem("Import data");
|
||||
|
||||
onData(
|
||||
allOf(is(instanceOf(String.class)), startsWith("Backups"))).perform(
|
||||
click());
|
||||
|
||||
onData(
|
||||
allOf(is(instanceOf(String.class)), containsString(date))).perform(
|
||||
click());
|
||||
|
||||
selectHabit(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens the settings and generates a bug report.
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateBugReport()
|
||||
{
|
||||
clickMenuItem(R.string.settings);
|
||||
clickSettingsItem("Generate bug report");
|
||||
intended(hasAction(Intent.ACTION_SEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens menu, clicks Help, sees website.
|
||||
*/
|
||||
@Test
|
||||
public void testHelp()
|
||||
{
|
||||
clickMenuItem(R.string.help);
|
||||
intended(hasAction(Intent.ACTION_VIEW));
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens menu, clicks settings, sees settings screen.
|
||||
*/
|
||||
@Test
|
||||
public void testSettings()
|
||||
{
|
||||
clickMenuItem(R.string.settings);
|
||||
}
|
||||
}
|
@ -1,4 +1,23 @@
|
||||
package org.isoron.uhabits.ui;
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.espresso;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.io;
|
||||
|
||||
import android.content.*;
|
||||
import android.support.test.*;
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class ImportTest extends BaseAndroidTest
|
||||
{
|
||||
private File baseDir;
|
||||
|
||||
private Context context;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
DateUtils.setFixedLocalTime(null);
|
||||
|
||||
fixtures.purgeHabits(habitList);
|
||||
context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
baseDir = FileUtils.getFilesDir("Backups");
|
||||
if (baseDir == null) fail("baseDir should not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHabitBullCSV() throws IOException
|
||||
{
|
||||
importFromFile("habitbull.csv");
|
||||
|
||||
assertThat(habitList.size(), equalTo(4));
|
||||
|
||||
Habit habit = habitList.getByPosition(0);
|
||||
assertThat(habit.getName(), equalTo("Breed dragons"));
|
||||
assertThat(habit.getDescription(), equalTo("with love and fire"));
|
||||
assertThat(habit.getFrequency(), equalTo(Frequency.DAILY));
|
||||
assertTrue(containsRepetition(habit, 2016, 3, 18));
|
||||
assertTrue(containsRepetition(habit, 2016, 3, 19));
|
||||
assertFalse(containsRepetition(habit, 2016, 3, 20));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoopDB() throws IOException
|
||||
{
|
||||
importFromFile("loop.db");
|
||||
|
||||
assertThat(habitList.size(), equalTo(9));
|
||||
|
||||
Habit habit = habitList.getByPosition(0);
|
||||
assertThat(habit.getName(), equalTo("Wake up early"));
|
||||
assertThat(habit.getFrequency(),
|
||||
equalTo(Frequency.THREE_TIMES_PER_WEEK));
|
||||
assertTrue(containsRepetition(habit, 2016, 3, 14));
|
||||
assertTrue(containsRepetition(habit, 2016, 3, 16));
|
||||
assertFalse(containsRepetition(habit, 2016, 3, 17));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRewireDB() throws IOException
|
||||
{
|
||||
importFromFile("rewire.db");
|
||||
|
||||
assertThat(habitList.size(), equalTo(3));
|
||||
|
||||
Habit habit = habitList.getByPosition(0);
|
||||
assertThat(habit.getName(), equalTo("Wake up early"));
|
||||
assertThat(habit.getFrequency(),
|
||||
equalTo(Frequency.THREE_TIMES_PER_WEEK));
|
||||
assertFalse(habit.hasReminder());
|
||||
assertFalse(containsRepetition(habit, 2015, 12, 31));
|
||||
assertTrue(containsRepetition(habit, 2016, 1, 18));
|
||||
assertTrue(containsRepetition(habit, 2016, 1, 28));
|
||||
assertFalse(containsRepetition(habit, 2016, 3, 10));
|
||||
|
||||
habit = habitList.getByPosition(1);
|
||||
assertThat(habit.getName(), equalTo("brush teeth"));
|
||||
assertThat(habit.getFrequency(),
|
||||
equalTo(Frequency.THREE_TIMES_PER_WEEK));
|
||||
assertThat(habit.hasReminder(), equalTo(true));
|
||||
|
||||
Reminder reminder = habit.getReminder();
|
||||
assertThat(reminder.getHour(), equalTo(8));
|
||||
assertThat(reminder.getMinute(), equalTo(0));
|
||||
boolean[] reminderDays = { false, true, true, true, true, true, false };
|
||||
assertThat(reminder.getDays().toArray(), equalTo(reminderDays));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTickmateDB() throws IOException
|
||||
{
|
||||
importFromFile("tickmate.db");
|
||||
|
||||
assertThat(habitList.size(), equalTo(3));
|
||||
|
||||
Habit h = habitList.getByPosition(0);
|
||||
assertThat(h.getName(), equalTo("Vegan"));
|
||||
assertTrue(containsRepetition(h, 2016, 1, 24));
|
||||
assertTrue(containsRepetition(h, 2016, 2, 5));
|
||||
assertTrue(containsRepetition(h, 2016, 3, 18));
|
||||
assertFalse(containsRepetition(h, 2016, 3, 14));
|
||||
}
|
||||
|
||||
private boolean containsRepetition(Habit h, int year, int month, int day)
|
||||
{
|
||||
GregorianCalendar date = DateUtils.getStartOfTodayCalendar();
|
||||
date.set(year, month - 1, day);
|
||||
return h.getRepetitions().containsTimestamp(date.getTimeInMillis());
|
||||
}
|
||||
|
||||
private void copyAssetToFile(String assetPath, File dst) throws IOException
|
||||
{
|
||||
InputStream in = context.getAssets().open(assetPath);
|
||||
FileUtils.copy(in, dst);
|
||||
}
|
||||
|
||||
private void importFromFile(String assetFilename) throws IOException
|
||||
{
|
||||
File file =
|
||||
new File(String.format("%s/%s", baseDir.getPath(), assetFilename));
|
||||
copyAssetToFile(assetFilename, file);
|
||||
assertTrue(file.exists());
|
||||
assertTrue(file.canRead());
|
||||
|
||||
GenericImporter importer = component.getGenericImporter();
|
||||
assertThat(importer.canHandle(file), is(true));
|
||||
|
||||
importer.importHabitsFromFile(file);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models.sqlite;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.sqlite.records.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class HabitRecordTest extends BaseAndroidTest
|
||||
{
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
Habit h = component.getModelFactory().buildHabit();
|
||||
h.setName("Hello world");
|
||||
h.setId(1000L);
|
||||
|
||||
HabitRecord record = new HabitRecord();
|
||||
record.copyFrom(h);
|
||||
record.position = 0;
|
||||
record.save(1000L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyFrom()
|
||||
{
|
||||
Habit habit = component.getModelFactory().buildHabit();
|
||||
habit.setName("Hello world");
|
||||
habit.setDescription("Did you greet the world today?");
|
||||
habit.setColor(1);
|
||||
habit.setArchived(true);
|
||||
habit.setFrequency(Frequency.THREE_TIMES_PER_WEEK);
|
||||
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
|
||||
habit.setId(1000L);
|
||||
|
||||
HabitRecord rec = new HabitRecord();
|
||||
rec.copyFrom(habit);
|
||||
|
||||
assertThat(rec.name, equalTo(habit.getName()));
|
||||
assertThat(rec.description, equalTo(habit.getDescription()));
|
||||
assertThat(rec.color, equalTo(habit.getColor()));
|
||||
assertThat(rec.archived, equalTo(1));
|
||||
assertThat(rec.freqDen, equalTo(7));
|
||||
assertThat(rec.freqNum, equalTo(3));
|
||||
|
||||
Reminder reminder = habit.getReminder();
|
||||
assertThat(rec.reminderDays, equalTo(reminder.getDays().toInteger()));
|
||||
assertThat(rec.reminderHour, equalTo(reminder.getHour()));
|
||||
assertThat(rec.reminderMin, equalTo(reminder.getMinute()));
|
||||
|
||||
habit.setReminder(null);
|
||||
rec.copyFrom(habit);
|
||||
|
||||
assertThat(rec.reminderMin, equalTo(null));
|
||||
assertThat(rec.reminderHour, equalTo(null));
|
||||
assertThat(rec.reminderDays, equalTo(0));
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models.sqlite;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import com.activeandroid.query.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.sqlite.records.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class SQLiteCheckmarkListTest extends BaseAndroidTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
private CheckmarkList checkmarks;
|
||||
|
||||
private long today;
|
||||
|
||||
private long day;
|
||||
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
habit = fixtures.createLongHabit();
|
||||
checkmarks = habit.getCheckmarks();
|
||||
checkmarks.getToday(); // compute checkmarks
|
||||
|
||||
today = DateUtils.getStartOfToday();
|
||||
day = DateUtils.millisecondsInOneDay;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd()
|
||||
{
|
||||
checkmarks.invalidateNewerThan(0);
|
||||
|
||||
List<Checkmark> list = new LinkedList<>();
|
||||
list.add(new Checkmark(0, 0));
|
||||
list.add(new Checkmark(1, 1));
|
||||
list.add(new Checkmark(2, 2));
|
||||
|
||||
checkmarks.add(list);
|
||||
|
||||
List<CheckmarkRecord> records = getAllRecords();
|
||||
assertThat(records.size(), equalTo(3));
|
||||
assertThat(records.get(0).timestamp, equalTo(2L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByInterval()
|
||||
{
|
||||
long from = today - 10 * day;
|
||||
long to = today - 3 * day;
|
||||
|
||||
List<Checkmark> list = checkmarks.getByInterval(from, to);
|
||||
assertThat(list.size(), equalTo(8));
|
||||
|
||||
assertThat(list.get(0).getTimestamp(), equalTo(today - 3 * day));
|
||||
assertThat(list.get(3).getTimestamp(), equalTo(today - 6 * day));
|
||||
assertThat(list.get(7).getTimestamp(), equalTo(today - 10 * day));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByInterval_withLongInterval()
|
||||
{
|
||||
long from = today - 200 * day;
|
||||
long to = today;
|
||||
|
||||
List<Checkmark> list = checkmarks.getByInterval(from, to);
|
||||
assertThat(list.size(), equalTo(201));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidateNewerThan()
|
||||
{
|
||||
List<CheckmarkRecord> records = getAllRecords();
|
||||
assertThat(records.size(), equalTo(121));
|
||||
|
||||
checkmarks.invalidateNewerThan(today - 20 * day);
|
||||
|
||||
records = getAllRecords();
|
||||
assertThat(records.size(), equalTo(100));
|
||||
assertThat(records.get(0).timestamp, equalTo(today - 21 * day));
|
||||
}
|
||||
|
||||
private List<CheckmarkRecord> getAllRecords()
|
||||
{
|
||||
return new Select()
|
||||
.from(CheckmarkRecord.class)
|
||||
.where("habit = ?", habit.getId())
|
||||
.orderBy("timestamp desc")
|
||||
.execute();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models.sqlite;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import com.activeandroid.query.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.sqlite.records.*;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
|
||||
@SuppressWarnings("JavaDoc")
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class SQLiteHabitListTest extends BaseAndroidTest
|
||||
{
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
private SQLiteHabitList habitList;
|
||||
|
||||
private ModelFactory modelFactory;
|
||||
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
this.habitList = (SQLiteHabitList) super.habitList;
|
||||
fixtures.purgeHabits(habitList);
|
||||
|
||||
modelFactory = component.getModelFactory();
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Habit h = modelFactory.buildHabit();
|
||||
h.setName("habit " + i);
|
||||
h.setId((long) i);
|
||||
if (i % 2 == 0) h.setArchived(true);
|
||||
|
||||
HabitRecord record = new HabitRecord();
|
||||
record.copyFrom(h);
|
||||
record.position = i;
|
||||
record.save(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd_withDuplicate()
|
||||
{
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
habitList.add(habit);
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
habitList.add(habit);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd_withId()
|
||||
{
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
habit.setName("Hello world with id");
|
||||
habit.setId(12300L);
|
||||
|
||||
habitList.add(habit);
|
||||
assertThat(habit.getId(), equalTo(12300L));
|
||||
|
||||
HabitRecord record = getRecord(12300L);
|
||||
assertNotNull(record);
|
||||
assertThat(record.name, equalTo(habit.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd_withoutId()
|
||||
{
|
||||
Habit habit = modelFactory.buildHabit();
|
||||
habit.setName("Hello world");
|
||||
assertNull(habit.getId());
|
||||
|
||||
habitList.add(habit);
|
||||
assertNotNull(habit.getId());
|
||||
|
||||
HabitRecord record = getRecord(habit.getId());
|
||||
assertNotNull(record);
|
||||
assertThat(record.name, equalTo(habit.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSize()
|
||||
{
|
||||
assertThat(habitList.size(), equalTo(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAll_withArchived()
|
||||
{
|
||||
List<Habit> habits = habitList.toList();
|
||||
assertThat(habits.size(), equalTo(10));
|
||||
assertThat(habits.get(3).getName(), equalTo("habit 3"));
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testGetAll_withoutArchived()
|
||||
// {
|
||||
// List<Habit> habits = habitList.toList();
|
||||
// assertThat(habits.size(), equalTo(5));
|
||||
// assertThat(habits.get(3).getName(), equalTo("habit 7"));
|
||||
//
|
||||
// List<Habit> another = habitList.toList();
|
||||
// assertThat(habits, equalTo(another));
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testGetById()
|
||||
{
|
||||
Habit h1 = habitList.getById(0);
|
||||
assertNotNull(h1);
|
||||
assertThat(h1.getName(), equalTo("habit 0"));
|
||||
|
||||
Habit h2 = habitList.getById(0);
|
||||
assertNotNull(h2);
|
||||
assertThat(h1, equalTo(h2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetById_withInvalid()
|
||||
{
|
||||
long invalidId = 9183792001L;
|
||||
Habit h1 = habitList.getById(invalidId);
|
||||
assertNull(h1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByPosition()
|
||||
{
|
||||
Habit h = habitList.getByPosition(5);
|
||||
assertNotNull(h);
|
||||
assertThat(h.getName(), equalTo("habit 5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexOf()
|
||||
{
|
||||
Habit h1 = habitList.getByPosition(5);
|
||||
assertNotNull(h1);
|
||||
assertThat(habitList.indexOf(h1), equalTo(5));
|
||||
|
||||
Habit h2 = modelFactory.buildHabit();
|
||||
assertThat(habitList.indexOf(h2), equalTo(-1));
|
||||
|
||||
h2.setId(1000L);
|
||||
assertThat(habitList.indexOf(h2), equalTo(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_reorder()
|
||||
{
|
||||
// Same as HabitListTest.java
|
||||
// TODO: remove duplication
|
||||
|
||||
int operations[][] = {
|
||||
{5, 2}, {3, 7}, {4, 4}, {3, 2}
|
||||
};
|
||||
|
||||
int expectedPosition[][] = {
|
||||
{0, 1, 3, 4, 5, 2, 6, 7, 8, 9},
|
||||
{0, 1, 7, 3, 4, 2, 5, 6, 8, 9},
|
||||
{0, 1, 7, 3, 4, 2, 5, 6, 8, 9},
|
||||
{0, 1, 7, 2, 4, 3, 5, 6, 8, 9},
|
||||
};
|
||||
|
||||
for (int i = 0; i < operations.length; i++)
|
||||
{
|
||||
int from = operations[i][0];
|
||||
int to = operations[i][1];
|
||||
|
||||
Habit fromHabit = habitList.getByPosition(from);
|
||||
Habit toHabit = habitList.getByPosition(to);
|
||||
habitList.reorder(fromHabit, toHabit);
|
||||
|
||||
int actualPositions[] = new int[10];
|
||||
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
Habit h = habitList.getById(j);
|
||||
assertNotNull(h);
|
||||
actualPositions[j] = habitList.indexOf(h);
|
||||
}
|
||||
|
||||
assertThat(actualPositions, equalTo(expectedPosition[i]));
|
||||
}
|
||||
}
|
||||
|
||||
private HabitRecord getRecord(long id)
|
||||
{
|
||||
return new Select()
|
||||
.from(HabitRecord.class)
|
||||
.where("id = ?", id)
|
||||
.executeSingle();
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models.sqlite;
|
||||
|
||||
import android.support.annotation.*;
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import com.activeandroid.query.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.sqlite.records.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class SQLiteRepetitionListTest extends BaseAndroidTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
private long today;
|
||||
|
||||
private RepetitionList repetitions;
|
||||
|
||||
private long day;
|
||||
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
habit = fixtures.createLongHabit();
|
||||
repetitions = habit.getRepetitions();
|
||||
today = DateUtils.getStartOfToday();
|
||||
day = DateUtils.millisecondsInOneDay;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd()
|
||||
{
|
||||
RepetitionRecord record = getByTimestamp(today + day);
|
||||
assertThat(record, is(nullValue()));
|
||||
|
||||
Repetition rep = new Repetition(today + day);
|
||||
habit.getRepetitions().add(rep);
|
||||
|
||||
record = getByTimestamp(today + day);
|
||||
assertThat(record, is(not(nullValue())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByInterval()
|
||||
{
|
||||
List<Repetition> reps =
|
||||
repetitions.getByInterval(today - 10 * day, today);
|
||||
|
||||
assertThat(reps.size(), equalTo(8));
|
||||
assertThat(reps.get(0).getTimestamp(), equalTo(today - 10 * day));
|
||||
assertThat(reps.get(4).getTimestamp(), equalTo(today - 5 * day));
|
||||
assertThat(reps.get(5).getTimestamp(), equalTo(today - 3 * day));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByTimestamp()
|
||||
{
|
||||
Repetition rep = repetitions.getByTimestamp(today);
|
||||
assertThat(rep, is(not(nullValue())));
|
||||
assertThat(rep.getTimestamp(), equalTo(today));
|
||||
|
||||
rep = repetitions.getByTimestamp(today - 2 * day);
|
||||
assertThat(rep, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOldest()
|
||||
{
|
||||
Repetition rep = repetitions.getOldest();
|
||||
assertThat(rep, is(not(nullValue())));
|
||||
assertThat(rep.getTimestamp(), equalTo(today - 120 * day));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOldest_withEmptyHabit()
|
||||
{
|
||||
Habit empty = fixtures.createEmptyHabit();
|
||||
Repetition rep = empty.getRepetitions().getOldest();
|
||||
assertThat(rep, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove()
|
||||
{
|
||||
RepetitionRecord record = getByTimestamp(today);
|
||||
assertThat(record, is(not(nullValue())));
|
||||
|
||||
Repetition rep = record.toRepetition();
|
||||
repetitions.remove(rep);
|
||||
|
||||
record = getByTimestamp(today);
|
||||
assertThat(record, is(nullValue()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RepetitionRecord getByTimestamp(long timestamp)
|
||||
{
|
||||
return selectByTimestamp(timestamp).executeSingle();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private From selectByTimestamp(long timestamp)
|
||||
{
|
||||
return new Select()
|
||||
.from(RepetitionRecord.class)
|
||||
.where("habit = ?", habit.getId())
|
||||
.and("timestamp = ?", timestamp);
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.models.sqlite;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import com.activeandroid.query.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.models.sqlite.records.*;
|
||||
import org.isoron.uhabits.utils.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
@SuppressWarnings("JavaDoc")
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class SQLiteScoreListTest extends BaseAndroidTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
private ScoreList scores;
|
||||
|
||||
private long today;
|
||||
|
||||
private long day;
|
||||
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
habit = fixtures.createLongHabit();
|
||||
scores = habit.getScores();
|
||||
|
||||
today = DateUtils.getStartOfToday();
|
||||
day = DateUtils.millisecondsInOneDay;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAll()
|
||||
{
|
||||
List<Score> list = scores.toList();
|
||||
assertThat(list.size(), equalTo(121));
|
||||
assertThat(list.get(0).getTimestamp(), equalTo(today));
|
||||
assertThat(list.get(10).getTimestamp(), equalTo(today - 10 * day));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidateNewerThan()
|
||||
{
|
||||
scores.getTodayValue(); // force recompute
|
||||
List<ScoreRecord> records = getAllRecords();
|
||||
assertThat(records.size(), equalTo(121));
|
||||
|
||||
scores.invalidateNewerThan(today - 10 * day);
|
||||
|
||||
records = getAllRecords();
|
||||
assertThat(records.size(), equalTo(110));
|
||||
assertThat(records.get(0).timestamp, equalTo(today - 11 * day));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdd()
|
||||
{
|
||||
new Delete().from(ScoreRecord.class).execute();
|
||||
|
||||
List<Score> list = new LinkedList<>();
|
||||
list.add(new Score(today, 0));
|
||||
list.add(new Score(today - day, 0));
|
||||
list.add(new Score(today - 2 * day, 0));
|
||||
|
||||
scores.add(list);
|
||||
|
||||
List<ScoreRecord> records = getAllRecords();
|
||||
assertThat(records.size(), equalTo(3));
|
||||
assertThat(records.get(0).timestamp, equalTo(today));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByInterval()
|
||||
{
|
||||
long from = today - 10 * day;
|
||||
long to = today - 3 * day;
|
||||
|
||||
List<Score> list = scores.getByInterval(from, to);
|
||||
assertThat(list.size(), equalTo(8));
|
||||
|
||||
assertThat(list.get(0).getTimestamp(), equalTo(today - 3 * day));
|
||||
assertThat(list.get(3).getTimestamp(), equalTo(today - 6 * day));
|
||||
assertThat(list.get(7).getTimestamp(), equalTo(today - 10 * day));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetByInterval_withLongInterval()
|
||||
{
|
||||
long from = today - 200 * day;
|
||||
long to = today;
|
||||
|
||||
List<Score> list = scores.getByInterval(from, to);
|
||||
assertThat(list.size(), equalTo(201));
|
||||
}
|
||||
|
||||
private List<ScoreRecord> getAllRecords()
|
||||
{
|
||||
return new Select()
|
||||
.from(ScoreRecord.class)
|
||||
.where("habit = ?", habit.getId())
|
||||
.orderBy("timestamp desc")
|
||||
.execute();
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.pebble;
|
||||
|
||||
import android.content.*;
|
||||
import android.support.annotation.*;
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import com.getpebble.android.kit.*;
|
||||
import com.getpebble.android.kit.util.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.isoron.uhabits.receivers.*;
|
||||
import org.json.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import static com.getpebble.android.kit.Constants.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.core.IsEqual.*;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class PebbleReceiverTest extends BaseAndroidTest
|
||||
{
|
||||
|
||||
private Habit habit1;
|
||||
|
||||
private Habit habit2;
|
||||
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
|
||||
fixtures.purgeHabits(habitList);
|
||||
|
||||
habit1 = fixtures.createEmptyHabit();
|
||||
habit1.setName("Exercise");
|
||||
|
||||
habit2 = fixtures.createEmptyHabit();
|
||||
habit2.setName("Meditate");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCount() throws Exception
|
||||
{
|
||||
onPebbleReceived((dict) -> {
|
||||
assertThat(dict.getString(0), equalTo("COUNT"));
|
||||
assertThat(dict.getInteger(1), equalTo(2L));
|
||||
});
|
||||
|
||||
PebbleDictionary dict = buildCountRequest();
|
||||
sendFromPebbleToAndroid(dict);
|
||||
awaitLatch();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetch() throws Exception
|
||||
{
|
||||
onPebbleReceived((dict) -> {
|
||||
assertThat(dict.getString(0), equalTo("HABIT"));
|
||||
assertThat(dict.getInteger(1), equalTo(habit2.getId()));
|
||||
assertThat(dict.getString(2), equalTo(habit2.getName()));
|
||||
assertThat(dict.getInteger(3), equalTo(0L));
|
||||
});
|
||||
|
||||
PebbleDictionary dict = buildFetchRequest(1);
|
||||
sendFromPebbleToAndroid(dict);
|
||||
awaitLatch();
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testToggle() throws Exception
|
||||
// {
|
||||
// int v = habit1.getCheckmarks().getTodayValue();
|
||||
// assertThat(v, equalTo(Checkmark.UNCHECKED));
|
||||
//
|
||||
// onPebbleReceived((dict) -> {
|
||||
// assertThat(dict.getString(0), equalTo("OK"));
|
||||
// int value = habit1.getCheckmarks().getTodayValue();
|
||||
// assertThat(value, equalTo(200)); //Checkmark.CHECKED_EXPLICITLY));
|
||||
// });
|
||||
//
|
||||
// PebbleDictionary dict = buildToggleRequest(habit1.getId());
|
||||
// sendFromPebbleToAndroid(dict);
|
||||
// awaitLatch();
|
||||
// }
|
||||
|
||||
@NonNull
|
||||
protected PebbleDictionary buildCountRequest()
|
||||
{
|
||||
PebbleDictionary dict = new PebbleDictionary();
|
||||
dict.addString(0, "COUNT");
|
||||
return dict;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected PebbleDictionary buildFetchRequest(int position)
|
||||
{
|
||||
PebbleDictionary dict = new PebbleDictionary();
|
||||
dict.addString(0, "FETCH");
|
||||
dict.addInt32(1, position);
|
||||
return dict;
|
||||
}
|
||||
|
||||
protected void onPebbleReceived(PebbleProcessor processor)
|
||||
{
|
||||
BroadcastReceiver pebbleReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
try
|
||||
{
|
||||
String jsonData = intent.getStringExtra(MSG_DATA);
|
||||
PebbleDictionary dict = PebbleDictionary.fromJson(jsonData);
|
||||
processor.process(dict);
|
||||
latch.countDown();
|
||||
targetContext.unregisterReceiver(this);
|
||||
}
|
||||
catch (JSONException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter filter = new IntentFilter(Constants.INTENT_APP_SEND);
|
||||
targetContext.registerReceiver(pebbleReceiver, filter);
|
||||
}
|
||||
|
||||
protected void sendFromPebbleToAndroid(PebbleDictionary dict)
|
||||
{
|
||||
Intent intent = new Intent(Constants.INTENT_APP_RECEIVE);
|
||||
intent.putExtra(Constants.APP_UUID, PebbleReceiver.WATCHAPP_UUID);
|
||||
intent.putExtra(Constants.TRANSACTION_ID, 0);
|
||||
intent.putExtra(Constants.MSG_DATA, dict.toJsonString());
|
||||
targetContext.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private PebbleDictionary buildToggleRequest(long habitId)
|
||||
{
|
||||
PebbleDictionary dict = new PebbleDictionary();
|
||||
dict.addString(0, "TOGGLE");
|
||||
dict.addInt32(1, (int) habitId);
|
||||
return dict;
|
||||
}
|
||||
|
||||
interface PebbleProcessor
|
||||
{
|
||||
void process(PebbleDictionary dict);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.tasks;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.isoron.uhabits.models.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class ExportCSVTaskTest extends BaseAndroidTest
|
||||
{
|
||||
@Before
|
||||
@Override
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExportCSV() throws Throwable
|
||||
{
|
||||
fixtures.purgeHabits(habitList);
|
||||
fixtures.createShortHabit();
|
||||
|
||||
List<Habit> selected = new LinkedList<>();
|
||||
for (Habit h : habitList) selected.add(h);
|
||||
|
||||
taskRunner.execute(
|
||||
new ExportCSVTask(habitList, selected, archiveFilename -> {
|
||||
assertThat(archiveFilename, is(not(nullValue())));
|
||||
File f = new File(archiveFilename);
|
||||
assertTrue(f.exists());
|
||||
assertTrue(f.canRead());
|
||||
}));
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.tasks;
|
||||
|
||||
import android.support.test.runner.*;
|
||||
import android.test.suitebuilder.annotation.*;
|
||||
|
||||
import org.isoron.uhabits.*;
|
||||
import org.junit.*;
|
||||
import org.junit.runner.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static junit.framework.Assert.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class ExportDBTaskTest extends BaseAndroidTest
|
||||
{
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExportCSV() throws Throwable
|
||||
{
|
||||
ExportDBTask task = new ExportDBTask(filename -> {
|
||||
assertThat(filename, is(not(nullValue())));
|
||||
|
||||
File f = new File(filename);
|
||||
assertTrue(f.exists());
|
||||
assertTrue(f.canRead());
|
||||
});
|
||||
|
||||
taskRunner.execute(task);
|
||||
}
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui;
|
||||
|
||||
import android.support.test.espresso.NoMatchingViewException;
|
||||
import android.support.test.espresso.contrib.RecyclerViewActions;
|
||||
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onData;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.Espresso.pressBack;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.action.ViewActions.longClick;
|
||||
import static android.support.test.espresso.action.ViewActions.replaceText;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.matcher.RootMatchers.isPlatformPopup;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.isoron.uhabits.ui.HabitMatchers.containsHabit;
|
||||
import static org.isoron.uhabits.ui.HabitMatchers.withName;
|
||||
|
||||
public class MainActivityActions
|
||||
{
|
||||
public static String addHabit()
|
||||
{
|
||||
return addHabit(false);
|
||||
}
|
||||
|
||||
public static String addHabit(boolean openDialogs)
|
||||
{
|
||||
String name = "New Habit " + new Random().nextInt(1000000);
|
||||
String description = "Did you perform your new habit today?";
|
||||
String num = "4";
|
||||
String den = "8";
|
||||
|
||||
onView(withId(R.id.action_add))
|
||||
.perform(click());
|
||||
|
||||
typeHabitData(name, description, num, den);
|
||||
|
||||
if(openDialogs)
|
||||
{
|
||||
onView(withId(R.id.buttonPickColor))
|
||||
.perform(click());
|
||||
pressBack();
|
||||
onView(withId(R.id.inputReminderTime))
|
||||
.perform(click());
|
||||
onView(withText("Done"))
|
||||
.perform(click());
|
||||
onView(withId(R.id.inputReminderDays))
|
||||
.perform(click());
|
||||
onView(withText("OK"))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
onView(withId(R.id.buttonSave))
|
||||
.perform(click());
|
||||
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.onChildView(withId(R.id.label));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static void typeHabitData(String name, String description, String num, String den)
|
||||
{
|
||||
onView(withId(R.id.input_name))
|
||||
.perform(replaceText(name));
|
||||
onView(withId(R.id.input_description))
|
||||
.perform(replaceText(description));
|
||||
|
||||
try
|
||||
{
|
||||
onView(allOf(withId(R.id.sFrequency), withEffectiveVisibility(VISIBLE)))
|
||||
.perform(click());
|
||||
onData(allOf(instanceOf(String.class), startsWith("Custom")))
|
||||
.inRoot(isPlatformPopup())
|
||||
.perform(click());
|
||||
}
|
||||
catch(NoMatchingViewException e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
onView(withId(R.id.input_freq_num))
|
||||
.perform(replaceText(num));
|
||||
onView(withId(R.id.input_freq_den))
|
||||
.perform(replaceText(den));
|
||||
}
|
||||
|
||||
public static void selectHabit(String name)
|
||||
{
|
||||
selectHabits(Collections.singletonList(name));
|
||||
}
|
||||
|
||||
public static void selectHabits(List<String> names)
|
||||
{
|
||||
boolean first = true;
|
||||
for(String name : names)
|
||||
{
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(first ? longClick() : click());
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertHabitsDontExist(List<String> names)
|
||||
{
|
||||
for(String name : names)
|
||||
onView(withId(R.id.listView))
|
||||
.check(matches(not(containsHabit(withName(name)))));
|
||||
}
|
||||
|
||||
public static void assertHabitExists(String name)
|
||||
{
|
||||
List<String> names = new LinkedList<>();
|
||||
names.add(name);
|
||||
assertHabitsExist(names);
|
||||
}
|
||||
|
||||
public static void assertHabitsExist(List<String> names)
|
||||
{
|
||||
for(String name : names)
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
public static void deleteHabit(String name)
|
||||
{
|
||||
deleteHabits(Collections.singletonList(name));
|
||||
}
|
||||
|
||||
public static void deleteHabits(List<String> names)
|
||||
{
|
||||
selectHabits(names);
|
||||
clickMenuItem(R.string.delete);
|
||||
onView(withText("OK"))
|
||||
.perform(click());
|
||||
assertHabitsDontExist(names);
|
||||
}
|
||||
|
||||
public static void clickMenuItem(int stringId)
|
||||
{
|
||||
try
|
||||
{
|
||||
onView(withText(stringId)).perform(click());
|
||||
}
|
||||
catch (Exception e1)
|
||||
{
|
||||
try
|
||||
{
|
||||
onView(withContentDescription(stringId)).perform(click());
|
||||
}
|
||||
catch(Exception e2)
|
||||
{
|
||||
clickHiddenMenuItem(stringId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void clickHiddenMenuItem(int stringId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try the ActionMode overflow menu first
|
||||
onView(allOf(withContentDescription("More options"), withParent(withParent(
|
||||
withClassName(containsString("Action")))))).perform(click());
|
||||
}
|
||||
catch (Exception e1)
|
||||
{
|
||||
// Try the toolbar overflow menu
|
||||
onView(allOf(withContentDescription("More options"), withParent(withParent(
|
||||
withClassName(containsString("Toolbar")))))).perform(click());
|
||||
}
|
||||
|
||||
onView(withText(stringId)).perform(click());
|
||||
}
|
||||
|
||||
public static void clickSettingsItem(String text)
|
||||
{
|
||||
onView(withClassName(containsString("RecyclerView")))
|
||||
.perform(RecyclerViewActions.actionOnItem(
|
||||
hasDescendant(withText(containsString(text))),
|
||||
click()));
|
||||
}
|
||||
}
|
@ -1,346 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.espresso.NoMatchingViewException;
|
||||
import android.support.test.espresso.intent.rule.IntentsTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
|
||||
import org.isoron.uhabits.MainActivity;
|
||||
import org.isoron.uhabits.R;
|
||||
import org.isoron.uhabits.helpers.DateHelper;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onData;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.Espresso.pressBack;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.action.ViewActions.longClick;
|
||||
import static android.support.test.espresso.action.ViewActions.scrollTo;
|
||||
import static android.support.test.espresso.action.ViewActions.swipeLeft;
|
||||
import static android.support.test.espresso.action.ViewActions.swipeRight;
|
||||
import static android.support.test.espresso.action.ViewActions.swipeUp;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.intent.Intents.intended;
|
||||
import static android.support.test.espresso.intent.Intents.intending;
|
||||
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.isoron.uhabits.ui.HabitMatchers.withName;
|
||||
import static org.isoron.uhabits.ui.HabitViewActions.clickAtRandomLocations;
|
||||
import static org.isoron.uhabits.ui.HabitViewActions.toggleAllCheckmarks;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.addHabit;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.assertHabitExists;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.assertHabitsDontExist;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.assertHabitsExist;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.clickMenuItem;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.clickSettingsItem;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.deleteHabit;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.deleteHabits;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.selectHabit;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.selectHabits;
|
||||
import static org.isoron.uhabits.ui.MainActivityActions.typeHabitData;
|
||||
import static org.isoron.uhabits.ui.ShowHabitActivityActions.openHistoryEditor;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class MainTest
|
||||
{
|
||||
private SystemHelper sys;
|
||||
|
||||
@Rule
|
||||
public IntentsTestRule<MainActivity> activityRule = new IntentsTestRule<>(
|
||||
MainActivity.class);
|
||||
|
||||
private Context targetContext;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
sys = new SystemHelper(context);
|
||||
sys.disableAllAnimations();
|
||||
sys.acquireWakeLock();
|
||||
sys.unlockScreen();
|
||||
|
||||
targetContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
Instrumentation.ActivityResult okResult = new Instrumentation.ActivityResult(
|
||||
Activity.RESULT_OK, new Intent());
|
||||
|
||||
intending(hasAction(equalTo(Intent.ACTION_SEND))).respondWith(okResult);
|
||||
intending(hasAction(equalTo(Intent.ACTION_SENDTO))).respondWith(okResult);
|
||||
intending(hasAction(equalTo(Intent.ACTION_VIEW))).respondWith(okResult);
|
||||
|
||||
skipTutorial();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown()
|
||||
{
|
||||
sys.releaseWakeLock();
|
||||
}
|
||||
|
||||
public void skipTutorial()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
onView(allOf(withClassName(endsWith("AppCompatImageButton")),
|
||||
isDisplayed())).perform(click());
|
||||
}
|
||||
catch (NoMatchingViewException e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens the app, creates some habits, selects them, archives them, select 'show archived'
|
||||
* on the menu, selects the previously archived habits and then deletes them.
|
||||
*/
|
||||
@Test
|
||||
public void testArchiveHabits()
|
||||
{
|
||||
List<String> names = new LinkedList<>();
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
names.add(addHabit());
|
||||
|
||||
selectHabits(names);
|
||||
|
||||
clickMenuItem(R.string.archive);
|
||||
assertHabitsDontExist(names);
|
||||
|
||||
clickMenuItem(R.string.show_archived);
|
||||
|
||||
assertHabitsExist(names);
|
||||
selectHabits(names);
|
||||
clickMenuItem(R.string.unarchive);
|
||||
|
||||
clickMenuItem(R.string.show_archived);
|
||||
|
||||
assertHabitsExist(names);
|
||||
deleteHabits(names);
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens the app, clicks the add button, types some bogus information, tries to save,
|
||||
* dialog displays an error.
|
||||
*/
|
||||
@Test
|
||||
public void testAddInvalidHabit()
|
||||
{
|
||||
onView(withId(R.id.action_add))
|
||||
.perform(click());
|
||||
|
||||
typeHabitData("", "", "15", "7");
|
||||
|
||||
onView(withId(R.id.buttonSave)).perform(click());
|
||||
onView(withId(R.id.input_name)).check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, toggles a bunch of checkmarks, clicks the habit to open the statistics
|
||||
* screen, scrolls down to some views, then scrolls the views backwards and forwards in time.
|
||||
*/
|
||||
@Test
|
||||
public void testAddHabitAndViewStats() throws InterruptedException
|
||||
{
|
||||
String name = addHabit(true);
|
||||
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.onChildView(withId(R.id.llButtons))
|
||||
.perform(toggleAllCheckmarks());
|
||||
|
||||
Thread.sleep(1200);
|
||||
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(click());
|
||||
|
||||
onView(withId(R.id.scoreView))
|
||||
.perform(scrollTo(), swipeRight());
|
||||
|
||||
onView(withId(R.id.punchcardView))
|
||||
.perform(scrollTo(), swipeRight());
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, selects the habit, clicks edit button, changes some information about
|
||||
* the habit, click save button, sees changes on the main window, selects habit again,
|
||||
* changes color, then deletes the habit.
|
||||
*/
|
||||
@Test
|
||||
public void testEditHabit()
|
||||
{
|
||||
String name = addHabit();
|
||||
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(longClick());
|
||||
|
||||
clickMenuItem(R.string.edit);
|
||||
|
||||
String modifiedName = "Modified " + new Random().nextInt(10000);
|
||||
typeHabitData(modifiedName, "", "1", "1");
|
||||
|
||||
onView(withId(R.id.buttonSave))
|
||||
.perform(click());
|
||||
|
||||
assertHabitExists(modifiedName);
|
||||
|
||||
selectHabit(modifiedName);
|
||||
clickMenuItem(R.string.color_picker_default_title);
|
||||
pressBack();
|
||||
|
||||
deleteHabit(modifiedName);
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, opens statistics page, clicks button to edit history, adds some
|
||||
* checkmarks, closes dialog, sees the modified history calendar.
|
||||
*/
|
||||
@Test
|
||||
public void testEditHistory()
|
||||
{
|
||||
String name = addHabit();
|
||||
|
||||
onData(allOf(is(instanceOf(Habit.class)), withName(name)))
|
||||
.onChildView(withId(R.id.label))
|
||||
.perform(click());
|
||||
|
||||
openHistoryEditor();
|
||||
onView(withClassName(endsWith("HabitHistoryView")))
|
||||
.perform(clickAtRandomLocations(20));
|
||||
|
||||
pressBack();
|
||||
onView(withId(R.id.historyView))
|
||||
.perform(scrollTo(), swipeRight(), swipeLeft());
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens menu, clicks settings, sees settings screen.
|
||||
*/
|
||||
@Test
|
||||
public void testSettings()
|
||||
{
|
||||
clickMenuItem(R.string.settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens menu, clicks about, sees about screen.
|
||||
*/
|
||||
@Test
|
||||
public void testAbout()
|
||||
{
|
||||
clickMenuItem(R.string.about);
|
||||
onView(isRoot()).perform(swipeUp());
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens menu, clicks Help, sees website.
|
||||
*/
|
||||
@Test
|
||||
public void testHelp()
|
||||
{
|
||||
clickMenuItem(R.string.help);
|
||||
intended(hasAction(Intent.ACTION_VIEW));
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, exports full backup, deletes the habit, restores backup, sees that the
|
||||
* previously created habit has appeared back.
|
||||
*/
|
||||
@Test
|
||||
public void testExportImportDB()
|
||||
{
|
||||
String name = addHabit();
|
||||
|
||||
clickMenuItem(R.string.settings);
|
||||
|
||||
String date = DateHelper.getBackupDateFormat().format(DateHelper.getLocalTime());
|
||||
date = date.substring(0, date.length() - 2);
|
||||
|
||||
clickSettingsItem("Export full backup");
|
||||
intended(hasAction(Intent.ACTION_SEND));
|
||||
|
||||
deleteHabit(name);
|
||||
|
||||
clickMenuItem(R.string.settings);
|
||||
clickSettingsItem("Import data");
|
||||
|
||||
onData(allOf(is(instanceOf(String.class)), startsWith("Backups")))
|
||||
.perform(click());
|
||||
|
||||
onData(allOf(is(instanceOf(String.class)), containsString(date)))
|
||||
.perform(click());
|
||||
|
||||
selectHabit(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* User creates a habit, opens settings, clicks export as CSV, is asked what activity should
|
||||
* handle the file.
|
||||
*/
|
||||
@Test
|
||||
public void testExportCSV()
|
||||
{
|
||||
addHabit();
|
||||
clickMenuItem(R.string.settings);
|
||||
clickSettingsItem("Export as CSV");
|
||||
intended(hasAction(Intent.ACTION_SEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* User opens the settings and generates a bug report.
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateBugReport()
|
||||
{
|
||||
clickMenuItem(R.string.settings);
|
||||
clickSettingsItem("Generate bug report");
|
||||
intended(hasAction(Intent.ACTION_SENDTO));
|
||||
}
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.unit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.isoron.uhabits.helpers.DatabaseHelper;
|
||||
import org.isoron.uhabits.helpers.DateHelper;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.tasks.BaseTask;
|
||||
import org.isoron.uhabits.tasks.ExportDBTask;
|
||||
import org.isoron.uhabits.tasks.ImportDataTask;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class HabitFixtures
|
||||
{
|
||||
public static boolean NON_DAILY_HABIT_CHECKS[] = { true, false, false, true, true, true, false,
|
||||
false, true, true };
|
||||
|
||||
public static Habit createShortHabit()
|
||||
{
|
||||
Habit habit = new Habit();
|
||||
habit.name = "Wake up early";
|
||||
habit.description = "Did you wake up before 6am?";
|
||||
habit.freqNum = 2;
|
||||
habit.freqDen = 3;
|
||||
habit.save();
|
||||
|
||||
long timestamp = DateHelper.getStartOfToday();
|
||||
for(boolean c : NON_DAILY_HABIT_CHECKS)
|
||||
{
|
||||
if(c) habit.repetitions.toggle(timestamp);
|
||||
timestamp -= DateHelper.millisecondsInOneDay;
|
||||
}
|
||||
|
||||
return habit;
|
||||
}
|
||||
|
||||
public static Habit createEmptyHabit()
|
||||
{
|
||||
Habit habit = new Habit();
|
||||
habit.name = "Meditate";
|
||||
habit.description = "Did you meditate this morning?";
|
||||
habit.color = 3;
|
||||
habit.freqNum = 1;
|
||||
habit.freqDen = 1;
|
||||
habit.save();
|
||||
return habit;
|
||||
}
|
||||
|
||||
public static Habit createLongHabit()
|
||||
{
|
||||
Habit habit = createEmptyHabit();
|
||||
habit.freqNum = 3;
|
||||
habit.freqDen = 7;
|
||||
habit.color = 4;
|
||||
habit.save();
|
||||
|
||||
long day = DateHelper.millisecondsInOneDay;
|
||||
long today = DateHelper.getStartOfToday();
|
||||
int marks[] = { 0, 1, 3, 5, 7, 8, 9, 10, 12, 14, 15, 17, 19, 20, 26, 27, 28, 50, 51, 52,
|
||||
53, 54, 58, 60, 63, 65, 70, 71, 72, 73, 74, 75, 80, 81, 83, 89, 90, 91, 95,
|
||||
102, 103, 108, 109, 120};
|
||||
|
||||
for(int mark : marks)
|
||||
habit.repetitions.toggle(today - mark * day);
|
||||
|
||||
return habit;
|
||||
}
|
||||
|
||||
public static void generateHugeDataSet() throws Throwable
|
||||
{
|
||||
final int nHabits = 30;
|
||||
final int nYears = 5;
|
||||
|
||||
DatabaseHelper.executeAsTransaction(new DatabaseHelper.Command()
|
||||
{
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
Random rand = new Random();
|
||||
|
||||
for(int i = 0; i < nHabits; i++)
|
||||
{
|
||||
Log.i("HabitFixture", String.format("Creating habit %d / %d", i, nHabits));
|
||||
|
||||
Habit habit = new Habit();
|
||||
habit.name = String.format("Habit %d", i);
|
||||
habit.save();
|
||||
|
||||
long today = DateHelper.getStartOfToday();
|
||||
long day = DateHelper.millisecondsInOneDay;
|
||||
|
||||
|
||||
for(int j = 0; j < 365 * nYears; j++)
|
||||
{
|
||||
if(rand.nextBoolean())
|
||||
habit.repetitions.toggle(today - j * day);
|
||||
}
|
||||
|
||||
habit.scores.getTodayValue();
|
||||
habit.streaks.getAll(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ExportDBTask task = new ExportDBTask(null);
|
||||
task.setListener(new ExportDBTask.Listener()
|
||||
{
|
||||
@Override
|
||||
public void onExportDBFinished(@Nullable String filename)
|
||||
{
|
||||
if(filename != null)
|
||||
Log.i("HabitFixture", String.format("Huge data set exported to %s", filename));
|
||||
else
|
||||
Log.i("HabitFixture", "Failed to save database");
|
||||
}
|
||||
});
|
||||
task.execute();
|
||||
|
||||
BaseTask.waitForTasks(30000);
|
||||
}
|
||||
|
||||
public static void loadHugeDataSet(Context testContext) throws Throwable
|
||||
{
|
||||
File baseDir = DatabaseHelper.getFilesDir("Backups");
|
||||
if(baseDir == null) fail("baseDir should not be null");
|
||||
|
||||
File dst = new File(String.format("%s/%s", baseDir.getPath(), "loopHuge.db"));
|
||||
InputStream in = testContext.getAssets().open("fixtures/loopHuge.db");
|
||||
DatabaseHelper.copy(in, dst);
|
||||
|
||||
ImportDataTask task = new ImportDataTask(dst, null);
|
||||
task.execute();
|
||||
|
||||
BaseTask.waitForTasks(30000);
|
||||
}
|
||||
|
||||
public static void purgeHabits()
|
||||
{
|
||||
for(Habit h : Habit.getAll(true))
|
||||
h.cascadeDelete();
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.unit.commands;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import org.isoron.uhabits.BaseTest;
|
||||
import org.isoron.uhabits.commands.CreateHabitCommand;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.unit.HabitFixtures;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class CreateHabitCommandTest extends BaseTest
|
||||
{
|
||||
|
||||
private CreateHabitCommand command;
|
||||
private Habit model;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
super.setup();
|
||||
|
||||
model = new Habit();
|
||||
model.name = "New habit";
|
||||
command = new CreateHabitCommand(model);
|
||||
|
||||
HabitFixtures.purgeHabits();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteUndoRedo()
|
||||
{
|
||||
assertTrue(Habit.getAll(true).isEmpty());
|
||||
|
||||
command.execute();
|
||||
|
||||
List<Habit> allHabits = Habit.getAll(true);
|
||||
assertThat(allHabits.size(), equalTo(1));
|
||||
|
||||
Habit habit = allHabits.get(0);
|
||||
Long id = habit.getId();
|
||||
assertThat(habit.name, equalTo(model.name));
|
||||
|
||||
command.undo();
|
||||
assertTrue(Habit.getAll(true).isEmpty());
|
||||
|
||||
command.execute();
|
||||
allHabits = Habit.getAll(true);
|
||||
assertThat(allHabits.size(), equalTo(1));
|
||||
|
||||
habit = allHabits.get(0);
|
||||
Long newId = habit.getId();
|
||||
assertThat(id, equalTo(newId));
|
||||
assertThat(habit.name, equalTo(model.name));
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.unit.commands;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import org.isoron.uhabits.BaseTest;
|
||||
import org.isoron.uhabits.commands.DeleteHabitsCommand;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.unit.HabitFixtures;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class DeleteHabitsCommandTest extends BaseTest
|
||||
{
|
||||
private DeleteHabitsCommand command;
|
||||
private LinkedList<Habit> habits;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
super.setup();
|
||||
|
||||
HabitFixtures.purgeHabits();
|
||||
habits = new LinkedList<>();
|
||||
|
||||
// Habits that shuold be deleted
|
||||
for(int i = 0; i < 3; i ++)
|
||||
{
|
||||
Habit habit = HabitFixtures.createShortHabit();
|
||||
habits.add(habit);
|
||||
}
|
||||
|
||||
// Extra habit that should not be deleted
|
||||
Habit extraHabit = HabitFixtures.createShortHabit();
|
||||
extraHabit.name = "extra";
|
||||
extraHabit.save();
|
||||
|
||||
command = new DeleteHabitsCommand(habits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteUndoRedo()
|
||||
{
|
||||
assertThat(Habit.getAll(true).size(), equalTo(4));
|
||||
|
||||
command.execute();
|
||||
assertThat(Habit.getAll(true).size(), equalTo(1));
|
||||
assertThat(Habit.getAll(true).get(0).name, equalTo("extra"));
|
||||
|
||||
thrown.expect(UnsupportedOperationException.class);
|
||||
command.undo();
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.isoron.uhabits.unit.commands;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import org.isoron.uhabits.BaseTest;
|
||||
import org.isoron.uhabits.commands.EditHabitCommand;
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.unit.HabitFixtures;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class EditHabitCommandTest extends BaseTest
|
||||
{
|
||||
|
||||
private EditHabitCommand command;
|
||||
private Habit habit;
|
||||
private Habit modified;
|
||||
private Long id;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
super.setup();
|
||||
|
||||
habit = HabitFixtures.createShortHabit();
|
||||
habit.name = "original";
|
||||
habit.freqDen = 1;
|
||||
habit.freqNum = 1;
|
||||
habit.save();
|
||||
|
||||
id = habit.getId();
|
||||
|
||||
modified = new Habit(habit);
|
||||
modified.name = "modified";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteUndoRedo()
|
||||
{
|
||||
command = new EditHabitCommand(habit, modified);
|
||||
|
||||
int originalScore = habit.scores.getTodayValue();
|
||||
assertThat(habit.name, equalTo("original"));
|
||||
|
||||
command.execute();
|
||||
refreshHabit();
|
||||
assertThat(habit.name, equalTo("modified"));
|
||||
assertThat(habit.scores.getTodayValue(), equalTo(originalScore));
|
||||
|
||||
command.undo();
|
||||
refreshHabit();
|
||||
assertThat(habit.name, equalTo("original"));
|
||||
assertThat(habit.scores.getTodayValue(), equalTo(originalScore));
|
||||
|
||||
command.execute();
|
||||
refreshHabit();
|
||||
assertThat(habit.name, equalTo("modified"));
|
||||
assertThat(habit.scores.getTodayValue(), equalTo(originalScore));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteUndoRedo_withModifiedInterval()
|
||||
{
|
||||
modified.freqNum = 1;
|
||||
modified.freqDen = 7;
|
||||
command = new EditHabitCommand(habit, modified);
|
||||
|
||||
int originalScore = habit.scores.getTodayValue();
|
||||
assertThat(habit.name, equalTo("original"));
|
||||
|
||||
command.execute();
|
||||
refreshHabit();
|
||||
assertThat(habit.name, equalTo("modified"));
|
||||
assertThat(habit.scores.getTodayValue(), greaterThan(originalScore));
|
||||
|
||||
command.undo();
|
||||
refreshHabit();
|
||||
assertThat(habit.name, equalTo("original"));
|
||||
assertThat(habit.scores.getTodayValue(), equalTo(originalScore));
|
||||
|
||||
command.execute();
|
||||
refreshHabit();
|
||||
assertThat(habit.name, equalTo("modified"));
|
||||
assertThat(habit.scores.getTodayValue(), greaterThan(originalScore));
|
||||
}
|
||||
|
||||
private void refreshHabit()
|
||||
{
|
||||
habit = Habit.get(id);
|
||||
assertTrue(habit != null);
|
||||
}
|
||||
}
|