@ -1,36 +1,22 @@
|
|||||||
#built application files
|
|
||||||
*.apk
|
|
||||||
*.ap_
|
*.ap_
|
||||||
|
*.apk
|
||||||
# files for the dex VM
|
|
||||||
*.dex
|
|
||||||
|
|
||||||
# Java class files
|
|
||||||
*.class
|
*.class
|
||||||
|
*.dex
|
||||||
# generated files
|
*.iml
|
||||||
bin/
|
*.local.*
|
||||||
gen/
|
*.swp
|
||||||
|
*.trace
|
||||||
# Local configuration file (sdk path, etc)
|
*~
|
||||||
local.properties
|
|
||||||
|
|
||||||
# Windows thumbnail db
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# OSX files
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Eclipse project files
|
|
||||||
.classpath
|
.classpath
|
||||||
.project
|
|
||||||
|
|
||||||
# Android Studio
|
|
||||||
.idea
|
|
||||||
#.idea/workspace.xml - remove # and delete .idea if it better suit your needs.
|
|
||||||
.gradle
|
.gradle
|
||||||
build/
|
.idea
|
||||||
*.iml
|
.project
|
||||||
|
Thumbs.db
|
||||||
art/
|
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.app.KeyguardManager;
|
||||||
import android.content.Context;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|