Rename legacy to android

This commit is contained in:
2019-03-30 13:57:00 -05:00
parent 07cf74d400
commit 6a30bb98c6
882 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core;
import android.support.annotation.*;
import org.apache.commons.io.*;
import org.isoron.uhabits.core.commands.*;
import org.isoron.uhabits.core.database.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.models.Timestamp;
import org.isoron.uhabits.core.models.memory.*;
import org.isoron.uhabits.core.tasks.*;
import org.isoron.uhabits.core.test.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import org.junit.runner.*;
import org.mockito.junit.*;
import java.io.*;
import java.sql.*;
import java.util.*;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class BaseUnitTest
{
// 8:00am, January 25th, 2015 (UTC)
protected static final long FIXED_LOCAL_TIME = 1422172800000L;
protected HabitList habitList;
protected HabitFixtures fixtures;
protected ModelFactory modelFactory;
protected SingleThreadTaskRunner taskRunner;
protected CommandRunner commandRunner;
protected DatabaseOpener databaseOpener = new DatabaseOpener()
{
@Override
public Database open(@NonNull File file)
{
try
{
return new JdbcDatabase(DriverManager.getConnection(
String.format("jdbc:sqlite:%s", file.getAbsolutePath())));
}
catch (SQLException e)
{
throw new RuntimeException(e);
}
}
};
@Before
public void setUp() throws Exception
{
DateUtils.setFixedLocalTime(FIXED_LOCAL_TIME);
modelFactory = new MemoryModelFactory();
habitList = spy(modelFactory.buildHabitList());
fixtures = new HabitFixtures(modelFactory, habitList);
taskRunner = new SingleThreadTaskRunner();
commandRunner = new CommandRunner(taskRunner);
}
@After
public void tearDown() throws Exception
{
validateMockitoUsage();
DateUtils.setFixedLocalTime(null);
}
public long unixTime(int year, int month, int day)
{
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
cal.set(year, month, day, 0, 0, 0);
return cal.getTimeInMillis();
}
public long unixTime(int year, int month, int day, int hour, int minute)
{
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
cal.set(year, month, day, hour, minute);
return cal.getTimeInMillis();
}
public Timestamp timestamp(int year, int month, int day) {
return new Timestamp(unixTime(year, month, day));
}
@Test
public void nothing()
{
}
protected Database buildMemoryDatabase()
{
try
{
Database db = new JdbcDatabase(
DriverManager.getConnection("jdbc:sqlite::memory:"));
db.execute("pragma user_version=8;");
MigrationHelper helper = new MigrationHelper(db);
helper.migrateTo(21);
return db;
}
catch (SQLException e)
{
throw new RuntimeException(e);
}
}
protected void copyAssetToFile(String assetPath, File dst)
throws IOException
{
IOUtils.copy(openAsset(assetPath), new FileOutputStream(dst));
}
@NonNull
protected InputStream openAsset(String assetPath) throws IOException
{
InputStream in = getClass().getResourceAsStream(assetPath);
if (in != null) return in;
String basePath = "uhabits-core/src/test/resources/";
File file = new File(basePath + assetPath);
if (file.exists() && file.canRead()) in = new FileInputStream(file);
if (in != null) return in;
basePath = "src/test/resources/";
file = new File(basePath + assetPath);
if (file.exists() && file.canRead()) in = new FileInputStream(file);
if (in != null) return in;
throw new IllegalStateException("asset not found: " + assetPath);
}
protected Database openDatabaseResource(String path) throws IOException
{
InputStream original = openAsset(path);
File tmpDbFile = File.createTempFile("database", ".db");
tmpDbFile.deleteOnExit();
IOUtils.copy(original, new FileOutputStream(tmpDbFile));
return databaseOpener.open(tmpDbFile);
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.util.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
public class ArchiveHabitsCommandTest extends BaseUnitTest
{
private ArchiveHabitsCommand command;
private Habit habit;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createShortHabit();
habitList.add(habit);
command = new ArchiveHabitsCommand(habitList,
Collections.singletonList(habit));
}
@Test
public void testExecuteUndoRedo()
{
assertFalse(habit.isArchived());
command.execute();
assertTrue(habit.isArchived());
command.undo();
assertFalse(habit.isArchived());
command.execute();
assertTrue(habit.isArchived());
}
@Test
public void testRecord()
{
ArchiveHabitsCommand.Record rec = command.toRecord();
ArchiveHabitsCommand other = rec.toCommand(habitList);
assertThat(other.selected, equalTo(command.selected));
assertThat(other.getId(), equalTo(command.getId()));
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.util.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
public class ChangeHabitColorCommandTest extends BaseUnitTest
{
private ChangeHabitColorCommand command;
private LinkedList<Habit> selected;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
selected = new LinkedList<>();
for (int i = 0; i < 3; i++)
{
Habit habit = fixtures.createShortHabit();
habit.setColor(i + 1);
selected.add(habit);
habitList.add(habit);
}
command = new ChangeHabitColorCommand(habitList, selected, 0);
}
@Test
public void testExecuteUndoRedo()
{
checkOriginalColors();
command.execute();
checkNewColors();
command.undo();
checkOriginalColors();
command.execute();
checkNewColors();
}
@Test
public void testRecord()
{
ChangeHabitColorCommand.Record rec = command.toRecord();
ChangeHabitColorCommand other = rec.toCommand(habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.newColor, equalTo(command.newColor));
assertThat(other.selected, equalTo(command.selected));
}
private void checkNewColors()
{
for (Habit h : selected)
assertThat(h.getColor(), equalTo(0));
}
private void checkOriginalColors()
{
int k = 0;
for (Habit h : selected)
assertThat(h.getColor(), equalTo(++k));
}
}

View File

@@ -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.core.commands;
import android.support.annotation.*;
import org.hamcrest.*;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.json.*;
import org.junit.*;
import java.util.*;
import static org.hamcrest.CoreMatchers.*;
public class CommandParserTest extends BaseUnitTest
{
@NonNull
private CommandParser parser;
private Habit habit;
private List<Habit> selected;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
parser = new CommandParser(habitList, modelFactory);
habit = fixtures.createShortHabit();
selected = Collections.singletonList(habit);
habitList.add(habit);
}
@Test
public void testDecodeArchiveCommand() throws JSONException
{
ArchiveHabitsCommand original, decoded;
original = new ArchiveHabitsCommand(habitList, selected);
decoded = (ArchiveHabitsCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.selected, equalTo(original.selected));
}
@Test
public void testDecodeChangeColorCommand() throws JSONException
{
ChangeHabitColorCommand original, decoded;
original = new ChangeHabitColorCommand(habitList, selected, 20);
decoded = (ChangeHabitColorCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.newColor, equalTo(original.newColor));
MatcherAssert.assertThat(decoded.selected, equalTo(original.selected));
}
@Test
public void testDecodeCreateHabitCommand() throws JSONException
{
Habit model = modelFactory.buildHabit();
model.setName("JSON");
CreateHabitCommand original, decoded;
original = new CreateHabitCommand(modelFactory, habitList, model);
original.execute();
decoded = (CreateHabitCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.savedId, equalTo(original.savedId));
MatcherAssert.assertThat(decoded.model.getData(), equalTo(model
.getData()));
}
@Test
public void testDecodeCreateRepCommand() throws JSONException
{
CreateRepetitionCommand original, decoded;
original = new CreateRepetitionCommand(habit, Timestamp.ZERO.plus(100), 5);
decoded = (CreateRepetitionCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.timestamp, equalTo(original
.timestamp));
MatcherAssert.assertThat(decoded.value, equalTo(original.value));
MatcherAssert.assertThat(decoded.habit, equalTo(original.habit));
}
@Test
public void testDecodeDeleteCommand() throws JSONException
{
DeleteHabitsCommand original, decoded;
original = new DeleteHabitsCommand(habitList, selected);
decoded = (DeleteHabitsCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.selected, equalTo(original.selected));
}
@Test
public void testDecodeEditHabitCommand() throws JSONException
{
Habit modified = modelFactory.buildHabit();
modified.setName("Edited JSON");
modified.setColor(2);
EditHabitCommand original, decoded;
original = new EditHabitCommand(modelFactory, habitList, habit, modified);
original.execute();
decoded = (EditHabitCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.savedId, equalTo(original.savedId));
MatcherAssert.assertThat(decoded.modified.getData(), equalTo(modified
.getData()));
}
@Test
public void testDecodeToggleCommand() throws JSONException
{
ToggleRepetitionCommand original, decoded;
original = new ToggleRepetitionCommand(habitList, habit,
Timestamp.ZERO.plus(100));
decoded = (ToggleRepetitionCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.timestamp, equalTo(original
.timestamp));
MatcherAssert.assertThat(decoded.habit, equalTo(original.habit));
}
@Test
public void testDecodeUnarchiveCommand() throws JSONException
{
UnarchiveHabitsCommand original, decoded;
original = new UnarchiveHabitsCommand(habitList, selected);
decoded = (UnarchiveHabitsCommand) parser.parse(original.toJson());
MatcherAssert.assertThat(decoded.getId(), equalTo(original.getId()));
MatcherAssert.assertThat(decoded.selected, equalTo(original.selected));
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import static junit.framework.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
public class CreateHabitCommandTest extends BaseUnitTest
{
private CreateHabitCommand command;
private Habit model;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
model = fixtures.createEmptyHabit();
model.setName("New habit");
model.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
command = new CreateHabitCommand(modelFactory, habitList, model);
}
@Test
public void testExecuteUndoRedo()
{
assertTrue(habitList.isEmpty());
command.execute();
assertThat(habitList.size(), equalTo(1));
Habit habit = habitList.getByPosition(0);
Long id = habit.getId();
assertThat(habit.getName(), equalTo(model.getName()));
command.undo();
assertTrue(habitList.isEmpty());
command.execute();
assertThat(habitList.size(), equalTo(1));
habit = habitList.getByPosition(0);
Long newId = habit.getId();
assertThat(id, equalTo(newId));
assertThat(habit.getName(), equalTo(model.getName()));
}
@Test
public void testRecord()
{
command.execute();
CreateHabitCommand.Record rec = command.toRecord();
CreateHabitCommand other = rec.toCommand(modelFactory, habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.savedId, equalTo(command.savedId));
assertThat(other.model.getData(), equalTo(command.model.getData()));
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.isoron.uhabits.core.models.Checkmark.CHECKED_EXPLICITLY;
public class CreateRepetitionCommandTest extends BaseUnitTest
{
private CreateRepetitionCommand command;
private Habit habit;
private Timestamp today;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createShortHabit();
habitList.add(habit);
today = DateUtils.getToday();
command = new CreateRepetitionCommand(habit, today, 100);
}
@Test
public void testExecuteUndoRedo()
{
RepetitionList reps = habit.getRepetitions();
Repetition rep = reps.getByTimestamp(today);
assertNotNull(rep);
assertEquals(CHECKED_EXPLICITLY, rep.getValue());
command.execute();
rep = reps.getByTimestamp(today);
assertNotNull(rep);
assertEquals(100, rep.getValue());
command.undo();
rep = reps.getByTimestamp(today);
assertNotNull(rep);
assertEquals(CHECKED_EXPLICITLY, rep.getValue());
}
@Test
public void testRecord()
{
CreateRepetitionCommand.Record rec = command.toRecord();
CreateRepetitionCommand other = rec.toCommand(habitList);
assertThat(command.getId(), equalTo(other.getId()));
assertThat(command.timestamp, equalTo(other.timestamp));
assertThat(command.value, equalTo(other.value));
assertThat(command.habit, equalTo(other.habit));
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import org.junit.rules.*;
import java.util.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
public class DeleteHabitsCommandTest extends BaseUnitTest
{
private DeleteHabitsCommand command;
private LinkedList<Habit> selected;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
selected = new LinkedList<>();
// Habits that should be deleted
for (int i = 0; i < 3; i++)
{
Habit habit = fixtures.createShortHabit();
habitList.add(habit);
selected.add(habit);
}
// Extra habit that should not be deleted
Habit extraHabit = fixtures.createShortHabit();
extraHabit.setName("extra");
habitList.add(extraHabit);
command = new DeleteHabitsCommand(habitList, selected);
}
@Test
public void testExecuteUndoRedo()
{
assertThat(habitList.size(), equalTo(4));
command.execute();
assertThat(habitList.size(), equalTo(1));
assertThat(habitList.getByPosition(0).getName(), equalTo("extra"));
thrown.expect(UnsupportedOperationException.class);
command.undo();
}
@Test
public void testRecord()
{
DeleteHabitsCommand.Record rec = command.toRecord();
DeleteHabitsCommand other = rec.toCommand(habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.selected, equalTo(command.selected));
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
public class EditHabitCommandTest extends BaseUnitTest
{
private EditHabitCommand command;
private Habit habit;
private Habit modified;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createShortHabit();
habit.setName("original");
habit.setFrequency(Frequency.DAILY);
habitList.add(habit);
modified = fixtures.createEmptyHabit();
modified.copyFrom(habit);
modified.setName("modified");
habitList.add(modified);
}
@Test
public void testExecuteUndoRedo()
{
command =
new EditHabitCommand(modelFactory, habitList, habit, modified);
double originalScore = habit.getScores().getTodayValue();
assertThat(habit.getName(), equalTo("original"));
command.execute();
assertThat(habit.getName(), equalTo("modified"));
assertThat(habit.getScores().getTodayValue(), equalTo(originalScore));
command.undo();
assertThat(habit.getName(), equalTo("original"));
assertThat(habit.getScores().getTodayValue(), equalTo(originalScore));
command.execute();
assertThat(habit.getName(), equalTo("modified"));
assertThat(habit.getScores().getTodayValue(), equalTo(originalScore));
}
@Test
public void testExecuteUndoRedo_withModifiedInterval()
{
modified.setFrequency(Frequency.TWO_TIMES_PER_WEEK);
command =
new EditHabitCommand(modelFactory, habitList, habit, modified);
double originalScore = habit.getScores().getTodayValue();
assertThat(habit.getName(), equalTo("original"));
command.execute();
assertThat(habit.getName(), equalTo("modified"));
assertThat(habit.getScores().getTodayValue(),
lessThan(originalScore));
command.undo();
assertThat(habit.getName(), equalTo("original"));
assertThat(habit.getScores().getTodayValue(), equalTo(originalScore));
command.execute();
assertThat(habit.getName(), equalTo("modified"));
assertThat(habit.getScores().getTodayValue(),
lessThan(originalScore));
}
@Test
public void testRecord()
{
command =
new EditHabitCommand(modelFactory, habitList, habit, modified);
EditHabitCommand.Record rec = command.toRecord();
EditHabitCommand other = rec.toCommand(modelFactory, habitList);
assertThat(other.getId(), equalTo(command.getId()));
assertThat(other.savedId, equalTo(command.savedId));
assertThat(other.original.getData(), equalTo(command.original.getData()));
assertThat(other.modified.getData(), equalTo(command.modified.getData()));
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class ToggleRepetitionCommandTest extends BaseUnitTest
{
private ToggleRepetitionCommand command;
private Habit habit;
private Timestamp today;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createShortHabit();
habitList.add(habit);
today = DateUtils.getToday();
command = new ToggleRepetitionCommand(habitList, habit, today);
}
@Test
public void testExecuteUndoRedo()
{
assertTrue(habit.getRepetitions().containsTimestamp(today));
command.execute();
assertFalse(habit.getRepetitions().containsTimestamp(today));
command.undo();
assertTrue(habit.getRepetitions().containsTimestamp(today));
command.execute();
assertFalse(habit.getRepetitions().containsTimestamp(today));
}
@Test
public void testRecord()
{
ToggleRepetitionCommand.Record rec = command.toRecord();
ToggleRepetitionCommand other = rec.toCommand(habitList);
assertThat(command.getId(), equalTo(other.getId()));
assertThat(command.timestamp, equalTo(other.timestamp));
assertThat(command.habit, equalTo(other.habit));
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.commands;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.util.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
public class UnarchiveHabitsCommandTest extends BaseUnitTest
{
private UnarchiveHabitsCommand command;
private Habit habit;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createShortHabit();
habit.setArchived(true);
habitList.add(habit);
command = new UnarchiveHabitsCommand(habitList, Collections
.singletonList
(habit));
}
@Test
public void testExecuteUndoRedo()
{
assertTrue(habit.isArchived());
command.execute();
assertFalse(habit.isArchived());
command.undo();
assertTrue(habit.isArchived());
command.execute();
assertFalse(habit.isArchived());
}
@Test
public void testRecord()
{
UnarchiveHabitsCommand.Record rec = command.toRecord();
UnarchiveHabitsCommand other = rec.toCommand(habitList);
assertThat(other.selected, equalTo(command.selected));
assertThat(other.getId(), equalTo(command.getId()));
}
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.database;
import org.apache.commons.lang3.builder.*;
import org.isoron.uhabits.core.*;
import org.junit.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
public class RepositoryTest extends BaseUnitTest
{
private Repository<ThingRecord> repository;
private Database db;
@Before
@Override
public void setUp() throws Exception
{
super.setUp();
this.db = buildMemoryDatabase();
repository = new Repository<>(ThingRecord.class, db);
db.execute("drop table if exists tests");
db.execute("create table tests(" +
"id integer not null primary key autoincrement, " +
"color_number integer not null, score float not null, " +
"name string)");
}
@Test
public void testFind() throws Exception
{
db.execute("insert into tests(id, color_number, name, score) " +
"values (10, 20, 'hello', 8.0)");
ThingRecord record = repository.find(10L);
assertNotNull(record);
assertThat(record.id, equalTo(10L));
assertThat(record.color, equalTo(20));
assertThat(record.name, equalTo("hello"));
assertThat(record.score, equalTo(8.0));
}
@Test
public void testSave_withId() throws Exception
{
ThingRecord record = new ThingRecord();
record.id = 50L;
record.color = 10;
record.name = "hello";
record.score = 5.0;
repository.save(record);
assertThat(record, equalTo(repository.find(50L)));
record.name = "world";
record.score = 128.0;
repository.save(record);
assertThat(record, equalTo(repository.find(50L)));
}
@Test
public void testSave_withNull() throws Exception
{
ThingRecord record = new ThingRecord();
record.color = 50;
record.name = null;
record.score = 12.0;
repository.save(record);
ThingRecord retrieved = repository.find(record.id);
assertNotNull(retrieved);
assertNull(retrieved.name);
assertThat(record, equalTo(retrieved));
}
@Test
public void testSave_withoutId() throws Exception
{
ThingRecord r1 = new ThingRecord();
r1.color = 10;
r1.name = "hello";
r1.score = 16.0;
repository.save(r1);
ThingRecord r2 = new ThingRecord();
r2.color = 20;
r2.name = "world";
r2.score = 2.0;
repository.save(r2);
assertThat(r1.id, equalTo(1L));
assertThat(r2.id, equalTo(2L));
}
@Test
public void testRemove() throws Exception
{
ThingRecord rec1 = new ThingRecord();
rec1.color = 10;
rec1.name = "hello";
rec1.score = 16.0;
repository.save(rec1);
ThingRecord rec2 = new ThingRecord();
rec2.color = 20;
rec2.name = "world";
rec2.score = 32.0;
repository.save(rec2);
long id = rec1.id;
assertThat(rec1, equalTo(repository.find(id)));
assertThat(rec2, equalTo(repository.find(rec2.id)));
repository.remove(rec1);
assertThat(rec1.id, equalTo(null));
assertNull(repository.find(id));
assertThat(rec2, equalTo(repository.find(rec2.id)));
repository.remove(rec1); // should have no effect
assertNull(repository.find(id));
}
}
@Table(name = "tests")
class ThingRecord
{
@Column
public Long id;
@Column
public String name;
@Column(name = "color_number")
public Integer color;
@Column
public Double score;
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ThingRecord record = (ThingRecord) o;
return new EqualsBuilder()
.append(id, record.id)
.append(name, record.name)
.append(color, record.color)
.isEquals();
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(id)
.append(name)
.append(color)
.toHashCode();
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("id", id)
.append("name", name)
.append("color", color)
.toString();
}
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.database.migrations;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.database.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.models.sqlite.*;
import org.isoron.uhabits.core.test.*;
import org.junit.*;
import org.junit.rules.*;
import static junit.framework.TestCase.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
public class Version22Test extends BaseUnitTest
{
@Rule
public ExpectedException exception = ExpectedException.none();
private Database db;
private MigrationHelper helper;
@Override
public void setUp() throws Exception
{
super.setUp();
db = openDatabaseResource("/databases/021.db");
helper = new MigrationHelper(db);
modelFactory = new SQLModelFactory(db);
habitList = modelFactory.buildHabitList();
fixtures = new HabitFixtures(modelFactory, habitList);
}
@Test
public void testKeepValidReps() throws Exception
{
db.query("select count(*) from repetitions",
(c) -> assertThat(c.getInt(0), equalTo(3)));
helper.migrateTo(22);
db.query("select count(*) from repetitions",
(c) -> assertThat(c.getInt(0), equalTo(3)));
}
@Test
public void testRemoveRepsWithInvalidId() throws Exception
{
db.execute("insert into Repetitions(habit, timestamp, value) " +
"values (99999, 100, 2)");
db.query("select count(*) from repetitions where habit = 99999",
(c) -> assertThat(c.getInt(0), equalTo(1)));
helper.migrateTo(22);
db.query("select count(*) from repetitions where habit = 99999",
(c) -> assertThat(c.getInt(0), equalTo(0)));
}
@Test
public void testDisallowNewRepsWithInvalidRef() throws Exception
{
helper.migrateTo(22);
exception.expectMessage(containsString("FOREIGNKEY"));
db.execute("insert into Repetitions(habit, timestamp, value) " +
"values (99999, 100, 2)");
}
@Test
public void testRemoveRepetitionsWithNullTimestamp() throws Exception
{
db.execute("insert into repetitions(habit, value) values (0, 2)");
db.query("select count(*) from repetitions where timestamp is null",
(c) -> assertThat(c.getInt(0), equalTo(1)));
helper.migrateTo(22);
db.query("select count(*) from repetitions where timestamp is null",
(c) -> assertThat(c.getInt(0), equalTo(0)));
}
@Test
public void testDisallowNullTimestamp() throws Exception
{
helper.migrateTo(22);
exception.expectMessage(containsString("SQLITE_CONSTRAINT_NOTNULL"));
db.execute("insert into Repetitions(habit, value) " + "values (0, 2)");
}
@Test
public void testRemoveRepetitionsWithNullHabit() throws Exception
{
db.execute("insert into repetitions(timestamp, value) values (0, 2)");
db.query("select count(*) from repetitions where habit is null",
(c) -> assertThat(c.getInt(0), equalTo(1)));
helper.migrateTo(22);
db.query("select count(*) from repetitions where habit is null",
(c) -> assertThat(c.getInt(0), equalTo(0)));
}
@Test
public void testDisallowNullHabit() throws Exception
{
helper.migrateTo(22);
exception.expectMessage(containsString("SQLITE_CONSTRAINT_NOTNULL"));
db.execute(
"insert into Repetitions(timestamp, value) " + "values (5, 2)");
}
@Test
public void testRemoveDuplicateRepetitions() throws Exception
{
db.execute("insert into repetitions(habit, timestamp, value)" +
"values (0, 100, 2)");
db.execute("insert into repetitions(habit, timestamp, value)" +
"values (0, 100, 5)");
db.execute("insert into repetitions(habit, timestamp, value)" +
"values (0, 100, 10)");
db.query(
"select count(*) from repetitions where timestamp=100 and habit=0",
(c) -> assertThat(c.getInt(0), equalTo(3)));
helper.migrateTo(22);
db.query(
"select count(*) from repetitions where timestamp=100 and habit=0",
(c) -> assertThat(c.getInt(0), equalTo(1)));
}
@Test
public void testDisallowNewDuplicateTimestamps() throws Exception
{
helper.migrateTo(22);
db.execute("insert into repetitions(habit, timestamp, value)" +
"values (0, 100, 2)");
exception.expectMessage(containsString("SQLITE_CONSTRAINT_UNIQUE"));
db.execute("insert into repetitions(habit, timestamp, value)" +
"values (0, 100, 5)");
}
@Test
public void testKeepHabitsUnchanged() throws Exception
{
Habit original = fixtures.createLongHabit();
Reminder reminder = new Reminder(8, 30, new WeekdayList(100));
original.setReminder(reminder);
habitList.update(original);
helper.migrateTo(22);
((SQLiteHabitList) habitList).reload();
Habit modified = habitList.getById(original.getId());
assertNotNull(modified);
assertThat(original.getData(), equalTo(modified.getData()));
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.io;
import org.apache.commons.io.*;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.zip.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class HabitsCSVExporterTest extends BaseUnitTest
{
private File baseDir;
@Before
public void setUp() throws Exception
{
super.setUp();
habitList.add(fixtures.createShortHabit());
habitList.add(fixtures.createEmptyHabit());
baseDir = Files.createTempDirectory("csv").toFile();
assertNotNull(baseDir);
}
@Override
public void tearDown() throws Exception
{
FileUtils.deleteDirectory(baseDir);
super.tearDown();
}
@Test
public void testExportCSV() throws IOException
{
List<Habit> selected = new LinkedList<>();
for (Habit h : habitList) selected.add(h);
HabitsCSVExporter exporter =
new HabitsCSVExporter(habitList, selected, baseDir);
String filename = exporter.writeArchive();
assertAbsolutePathExists(filename);
File archive = new File(filename);
unzip(archive);
assertPathExists("Habits.csv");
assertPathExists("001 Wake up early");
assertPathExists("001 Wake up early/Checkmarks.csv");
assertPathExists("001 Wake up early/Scores.csv");
assertPathExists("002 Meditate/Checkmarks.csv");
assertPathExists("002 Meditate/Scores.csv");
assertPathExists("Checkmarks.csv");
assertPathExists("Scores.csv");
}
private void unzip(File file) throws IOException
{
ZipFile zip = new ZipFile(file);
Enumeration<? extends ZipEntry> e = zip.entries();
while (e.hasMoreElements())
{
ZipEntry entry = e.nextElement();
InputStream stream = zip.getInputStream(entry);
String outputFilename =
String.format("%s/%s", baseDir.getAbsolutePath(),
entry.getName());
File out = new File(outputFilename);
File parent = out.getParentFile();
if (parent != null) parent.mkdirs();
IOUtils.copy(stream, new FileOutputStream(out));
}
zip.close();
}
private void assertPathExists(String s)
{
assertAbsolutePathExists(
String.format("%s/%s", baseDir.getAbsolutePath(), s));
}
private void assertAbsolutePathExists(String s)
{
File file = new File(s);
assertTrue(
String.format("File %s should exist", file.getAbsolutePath()),
file.exists());
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.io;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import java.io.*;
import java.util.*;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.*;
import static org.isoron.uhabits.core.models.Frequency.*;
import static org.junit.Assert.assertTrue;
public class ImportTest extends BaseUnitTest
{
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
DateUtils.setFixedLocalTime(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(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(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(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(new Timestamp(date));
}
private void importFromFile(String assetFilename) throws IOException
{
File file = File.createTempFile("asset", "");
copyAssetToFile(assetFilename, file);
assertTrue(file.exists());
assertTrue(file.canRead());
GenericImporter importer = new GenericImporter(habitList,
new LoopDBImporter(habitList, modelFactory, databaseOpener),
new RewireDBImporter(habitList, modelFactory, databaseOpener),
new TickmateDBImporter(habitList, modelFactory, databaseOpener),
new HabitBullCSVImporter(habitList, modelFactory));
assertTrue(importer.canHandle(file));
importer.importHabitsFromFile(file);
file.delete();
}
}

View File

@@ -0,0 +1,410 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import java.io.*;
import java.util.*;
import nl.jqno.equalsverifier.*;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.JULY;
import static java.util.Calendar.JUNE;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
import static org.isoron.uhabits.core.models.Checkmark.*;
import static org.isoron.uhabits.core.utils.DateUtils.TruncateField.MONTH;
import static org.isoron.uhabits.core.utils.DateUtils.TruncateField.QUARTER;
import static org.isoron.uhabits.core.utils.DateUtils.TruncateField.YEAR;
public class CheckmarkListTest extends BaseUnitTest
{
private long dayLength;
private Timestamp today;
private Habit nonDailyHabit;
private Habit emptyHabit;
private Habit numericalHabit;
@Override
public void setUp() throws Exception
{
super.setUp();
nonDailyHabit = fixtures.createShortHabit();
habitList.add(nonDailyHabit);
emptyHabit = fixtures.createEmptyHabit();
habitList.add(emptyHabit);
numericalHabit = fixtures.createNumericalHabit();
habitList.add(numericalHabit);
today = DateUtils.getToday();
}
@Test
public void test_buildCheckmarksFromIntervals_1() throws Exception
{
Repetition reps[] = new Repetition[]{
new Repetition(day(10), CHECKED_EXPLICITLY),
new Repetition(day(5), CHECKED_EXPLICITLY),
new Repetition(day(2), CHECKED_EXPLICITLY),
new Repetition(day(1), CHECKED_EXPLICITLY),
};
ArrayList<CheckmarkList.Interval> intervals = new ArrayList<>();
intervals.add(new CheckmarkList.Interval(day(10), day(8), day(8)));
intervals.add(new CheckmarkList.Interval(day(6), day(5), day(4)));
intervals.add(new CheckmarkList.Interval(day(2), day(2), day(1)));
List<Checkmark> expected = new ArrayList<>();
expected.add(new Checkmark(day(0), UNCHECKED));
expected.add(new Checkmark(day(1), CHECKED_EXPLICITLY));
expected.add(new Checkmark(day(2), CHECKED_EXPLICITLY));
expected.add(new Checkmark(day(3), UNCHECKED));
expected.add(new Checkmark(day(4), CHECKED_IMPLICITLY));
expected.add(new Checkmark(day(5), CHECKED_EXPLICITLY));
expected.add(new Checkmark(day(6), CHECKED_IMPLICITLY));
expected.add(new Checkmark(day(7), UNCHECKED));
expected.add(new Checkmark(day(8), CHECKED_IMPLICITLY));
expected.add(new Checkmark(day(9), CHECKED_IMPLICITLY));
expected.add(new Checkmark(day(10), CHECKED_EXPLICITLY));
List<Checkmark> actual =
CheckmarkList.buildCheckmarksFromIntervals(reps, intervals);
assertThat(actual, equalTo(expected));
}
@Test
public void test_buildCheckmarksFromIntervals_2() throws Exception
{
Repetition reps[] = new Repetition[]{
new Repetition(day(0), CHECKED_EXPLICITLY),
};
ArrayList<CheckmarkList.Interval> intervals = new ArrayList<>();
intervals.add(new CheckmarkList.Interval(day(0), day(0), day(-10)));
List<Checkmark> expected = new ArrayList<>();
expected.add(new Checkmark(day(0), CHECKED_EXPLICITLY));
List<Checkmark> actual =
CheckmarkList.buildCheckmarksFromIntervals(reps, intervals);
assertThat(actual, equalTo(expected));
}
@Test
public void test_buildIntervals_1() throws Exception
{
Repetition reps[] = new Repetition[]{
new Repetition(day(23), CHECKED_EXPLICITLY),
new Repetition(day(18), CHECKED_EXPLICITLY),
new Repetition(day(8), CHECKED_EXPLICITLY),
};
ArrayList<CheckmarkList.Interval> expected = new ArrayList<>();
expected.add(new CheckmarkList.Interval(day(23), day(23), day(17)));
expected.add(new CheckmarkList.Interval(day(18), day(18), day(12)));
expected.add(new CheckmarkList.Interval(day(8), day(8), day(2)));
ArrayList<CheckmarkList.Interval> actual;
actual = CheckmarkList.buildIntervals(Frequency.WEEKLY, reps);
assertThat(actual, equalTo(expected));
}
@Test
public void test_buildIntervals_2() throws Exception
{
Repetition reps[] = new Repetition[]{
new Repetition(day(23), CHECKED_EXPLICITLY),
new Repetition(day(18), CHECKED_EXPLICITLY),
new Repetition(day(8), CHECKED_EXPLICITLY),
};
ArrayList<CheckmarkList.Interval> expected = new ArrayList<>();
expected.add(new CheckmarkList.Interval(day(23), day(23), day(23)));
expected.add(new CheckmarkList.Interval(day(18), day(18), day(18)));
expected.add(new CheckmarkList.Interval(day(8), day(8), day(8)));
ArrayList<CheckmarkList.Interval> actual;
actual = CheckmarkList.buildIntervals(Frequency.DAILY, reps);
assertThat(actual, equalTo(expected));
}
@Test
public void test_buildIntervals_3() throws Exception
{
Repetition reps[] = new Repetition[]{
new Repetition(day(23), CHECKED_EXPLICITLY),
new Repetition(day(22), CHECKED_EXPLICITLY),
new Repetition(day(18), CHECKED_EXPLICITLY),
new Repetition(day(15), CHECKED_EXPLICITLY),
new Repetition(day(8), CHECKED_EXPLICITLY),
};
ArrayList<CheckmarkList.Interval> expected = new ArrayList<>();
expected.add(new CheckmarkList.Interval(day(23), day(22), day(17)));
expected.add(new CheckmarkList.Interval(day(22), day(18), day(16)));
expected.add(new CheckmarkList.Interval(day(18), day(15), day(12)));
ArrayList<CheckmarkList.Interval> actual;
actual =
CheckmarkList.buildIntervals(Frequency.TWO_TIMES_PER_WEEK, reps);
assertThat(actual, equalTo(expected));
}
@Test
public void test_getAllValues_moveBackwardsInTime()
{
travelInTime(-3);
int[] expectedValues = {
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY
};
int[] actualValues = nonDailyHabit.getCheckmarks().getAllValues();
assertThat(actualValues, equalTo(expectedValues));
}
@Test
public void test_getAllValues_moveForwardInTime()
{
travelInTime(3);
int[] expectedValues = {
UNCHECKED,
UNCHECKED,
UNCHECKED,
CHECKED_EXPLICITLY,
UNCHECKED,
CHECKED_IMPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY
};
int[] actualValues = nonDailyHabit.getCheckmarks().getAllValues();
assertThat(actualValues, equalTo(expectedValues));
}
@Test
public void test_getAllValues_withEmptyHabit()
{
int[] expectedValues = new int[0];
int[] actualValues = emptyHabit.getCheckmarks().getAllValues();
assertThat(actualValues, equalTo(expectedValues));
}
@Test
public void test_getAllValues_withNonDailyHabit()
{
int[] expectedValues = {
CHECKED_EXPLICITLY,
UNCHECKED,
CHECKED_IMPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY
};
int[] actualValues = nonDailyHabit.getCheckmarks().getAllValues();
assertThat(actualValues, equalTo(expectedValues));
}
@Test
public void test_getByInterval_withNumericalHabits() throws Exception
{
CheckmarkList checkmarks = numericalHabit.getCheckmarks();
List<Checkmark> expected =
Arrays.asList(new Checkmark(day(1), 200), new Checkmark(day(2), 0),
new Checkmark(day(3), 300), new Checkmark(day(4), 0),
new Checkmark(day(5), 400));
List<Checkmark> actual = checkmarks.getByInterval(day(5), day(1));
assertThat(actual, equalTo(expected));
}
@Test
public void test_getTodayValue()
{
CheckmarkList checkmarks = nonDailyHabit.getCheckmarks();
travelInTime(-1);
assertThat(checkmarks.getTodayValue(), equalTo(UNCHECKED));
travelInTime(0);
assertThat(checkmarks.getTodayValue(), equalTo(CHECKED_EXPLICITLY));
travelInTime(1);
assertThat(checkmarks.getTodayValue(), equalTo(UNCHECKED));
}
@Test
public void test_getValues_withInvalidInterval()
{
int values[] = nonDailyHabit
.getCheckmarks()
.getValues(new Timestamp(0L).plus(100), new Timestamp(0L));
assertThat(values, equalTo(new int[0]));
}
@Test
public void test_getValues_withValidInterval()
{
Timestamp from = today.minus(15);
Timestamp to = today.minus(5);
int[] expectedValues = {
CHECKED_EXPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_IMPLICITLY,
CHECKED_EXPLICITLY,
CHECKED_EXPLICITLY,
UNCHECKED,
UNCHECKED,
UNCHECKED,
UNCHECKED,
UNCHECKED,
UNCHECKED
};
int[] actualValues = nonDailyHabit.getCheckmarks().getValues(from, to);
assertThat(actualValues, equalTo(expectedValues));
}
@Test
public void test_snapIntervalsTogether_1() throws Exception
{
ArrayList<CheckmarkList.Interval> original = new ArrayList<>();
original.add(new CheckmarkList.Interval(day(40), day(40), day(34)));
original.add(new CheckmarkList.Interval(day(25), day(25), day(19)));
original.add(new CheckmarkList.Interval(day(16), day(16), day(10)));
original.add(new CheckmarkList.Interval(day(8), day(8), day(2)));
ArrayList<CheckmarkList.Interval> expected = new ArrayList<>();
expected.add(new CheckmarkList.Interval(day(40), day(40), day(34)));
expected.add(new CheckmarkList.Interval(day(25), day(25), day(19)));
expected.add(new CheckmarkList.Interval(day(18), day(16), day(12)));
expected.add(new CheckmarkList.Interval(day(11), day(8), day(5)));
CheckmarkList.snapIntervalsTogether(original);
assertThat(original, equalTo(expected));
}
@Test
public void test_writeCSV() throws IOException
{
String expectedCSV = "2015-01-25,2\n2015-01-24,0\n2015-01-23,1\n" +
"2015-01-22,2\n2015-01-21,2\n2015-01-20,2\n" +
"2015-01-19,1\n2015-01-18,1\n2015-01-17,2\n" +
"2015-01-16,2\n";
StringWriter writer = new StringWriter();
nonDailyHabit.getCheckmarks().writeCSV(writer);
assertThat(writer.toString(), equalTo(expectedCSV));
}
private Timestamp day(int offset)
{
return DateUtils.getToday().minus(offset);
}
private void travelInTime(int days)
{
DateUtils.setFixedLocalTime(
FIXED_LOCAL_TIME + days * Timestamp.DAY_LENGTH);
}
@Test
public void testToString() throws Exception
{
Timestamp t = Timestamp.ZERO.plus(100);
Checkmark checkmark = new Checkmark(t, 2);
assertThat(checkmark.toString(),
equalTo("{timestamp: 1970-04-11, value: 2}"));
CheckmarkList.Interval interval =
new CheckmarkList.Interval(t, t.plus(1), t.plus(2));
assertThat(interval.toString(), equalTo(
"{begin: 1970-04-11, center: 1970-04-12, end: 1970-04-13}"));
}
@Test
public void testEquals() throws Exception
{
EqualsVerifier.forClass(Checkmark.class).verify();
EqualsVerifier.forClass(Timestamp.class).verify();
EqualsVerifier.forClass(CheckmarkList.Interval.class).verify();
}
@Test
public void testGroupBy() throws Exception
{
Habit habit = fixtures.createLongNumericalHabit(timestamp(2014, JUNE, 1));
CheckmarkList checkmarks = habit.getCheckmarks();
List<Checkmark> byMonth = checkmarks.groupBy(MONTH);
assertThat(byMonth.size(), equalTo(25)); // from 2013-01-01 to 2015-01-01
assertThat(byMonth.get(0), equalTo(new Checkmark(timestamp(2015, JANUARY, 1), 0)));
assertThat(byMonth.get(6), equalTo(new Checkmark(timestamp(2014, JULY, 1), 0)));
assertThat(byMonth.get(12), equalTo(new Checkmark(timestamp(2014, JANUARY, 1), 1706)));
assertThat(byMonth.get(18), equalTo(new Checkmark(timestamp(2013, JULY, 1), 1379)));
List<Checkmark> byQuarter = checkmarks.groupBy(QUARTER);
assertThat(byQuarter.size(), equalTo(9)); // from 2013-Q1 to 2015-Q1
assertThat(byQuarter.get(0), equalTo(new Checkmark(timestamp(2015, JANUARY, 1), 0)));
assertThat(byQuarter.get(4), equalTo(new Checkmark(timestamp(2014, JANUARY, 1), 4964)));
assertThat(byQuarter.get(8), equalTo(new Checkmark(timestamp(2013, JANUARY, 1), 4975)));
List<Checkmark> byYear = checkmarks.groupBy(YEAR);
assertThat(byYear.size(), equalTo(3)); // from 2013 to 2015
assertThat(byYear.get(0), equalTo(new Checkmark(timestamp(2015, JANUARY, 1), 0)));
assertThat(byYear.get(1), equalTo(new Checkmark(timestamp(2014, JANUARY, 1), 8227)));
assertThat(byYear.get(2), equalTo(new Checkmark(timestamp(2013, JANUARY, 1), 16172)));
}
}

View File

@@ -0,0 +1,291 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.junit.*;
import org.junit.rules.*;
import java.io.*;
import java.util.*;
import static java.lang.Math.*;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.isoron.uhabits.core.models.HabitList.Order.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@SuppressWarnings("JavaDoc")
public class HabitListTest extends BaseUnitTest
{
@Rule
public ExpectedException thrown = ExpectedException.none();
private ArrayList<Habit> habitsArray;
private HabitList activeHabits;
private HabitList reminderHabits;
@Override
public void setUp() throws Exception
{
super.setUp();
habitsArray = new ArrayList<>();
for (int i = 0; i < 10; i++)
{
Habit habit = fixtures.createEmptyHabit();
habitList.add(habit);
habitsArray.add(habit);
if (i % 3 == 0)
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
}
habitsArray.get(0).setArchived(true);
habitsArray.get(1).setArchived(true);
habitsArray.get(4).setArchived(true);
habitsArray.get(7).setArchived(true);
activeHabits = habitList.getFiltered(new HabitMatcherBuilder().build());
reminderHabits = habitList.getFiltered(new HabitMatcherBuilder()
.setArchivedAllowed(true)
.setReminderRequired(true)
.build());
}
@Test
public void testSize()
{
assertThat(habitList.size(), equalTo(10));
assertThat(activeHabits.size(), equalTo(6));
assertThat(reminderHabits.size(), equalTo(4));
}
@Test
public void testGetByPosition()
{
assertThat(habitList.getByPosition(0), equalTo(habitsArray.get(0)));
assertThat(habitList.getByPosition(3), equalTo(habitsArray.get(3)));
assertThat(habitList.getByPosition(9), equalTo(habitsArray.get(9)));
assertThat(activeHabits.getByPosition(0), equalTo(habitsArray.get(2)));
assertThat(reminderHabits.getByPosition(1),
equalTo(habitsArray.get(3)));
}
@Test
public void testGetById()
{
Habit habit1 = habitsArray.get(0);
Habit habit2 = habitList.getById(habit1.getId());
assertThat(habit1, equalTo(habit2));
}
@Test
public void testGetById_withInvalidId()
{
assertNull(habitList.getById(100L));
}
@Test
public void testOrdering()
{
HabitList list = modelFactory.buildHabitList();
Habit h1 = fixtures.createEmptyHabit();
h1.setName("A Habit");
h1.setColor(2);
h1.setPosition(1);
Habit h2 = fixtures.createEmptyHabit();
h2.setName("B Habit");
h2.setColor(2);
h2.setPosition(3);
Habit h3 = fixtures.createEmptyHabit();
h3.setName("C Habit");
h3.setColor(0);
h3.setPosition(0);
Habit h4 = fixtures.createEmptyHabit();
h4.setName("D Habit");
h4.setColor(1);
h4.setPosition(2);
list.add(h3);
list.add(h1);
list.add(h4);
list.add(h2);
list.setOrder(BY_POSITION);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h1));
assertThat(list.getByPosition(2), equalTo(h4));
assertThat(list.getByPosition(3), equalTo(h2));
list.setOrder(BY_NAME);
assertThat(list.getByPosition(0), equalTo(h1));
assertThat(list.getByPosition(1), equalTo(h2));
assertThat(list.getByPosition(2), equalTo(h3));
assertThat(list.getByPosition(3), equalTo(h4));
list.remove(h1);
list.add(h1);
assertThat(list.getByPosition(0), equalTo(h1));
list.setOrder(BY_COLOR);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h4));
assertThat(list.getByPosition(2), equalTo(h1));
assertThat(list.getByPosition(3), equalTo(h2));
list.setOrder(BY_POSITION);
assertThat(list.getByPosition(0), equalTo(h3));
assertThat(list.getByPosition(1), equalTo(h1));
assertThat(list.getByPosition(2), equalTo(h4));
assertThat(list.getByPosition(3), equalTo(h2));
}
@Test
public void testReorder()
{
int operations[][] = {
{ 5, 2 }, { 3, 7 }, { 4, 4 }, { 8, 3 }
};
int expectedSequence[][] = {
{ 0, 1, 5, 2, 3, 4, 6, 7, 8, 9 },
{ 0, 1, 5, 2, 4, 6, 7, 3, 8, 9 },
{ 0, 1, 5, 2, 4, 6, 7, 3, 8, 9 },
{ 0, 1, 5, 2, 4, 6, 7, 8, 3, 9 },
};
for (int i = 0; i < operations.length; i++)
{
Habit fromHabit = habitsArray.get(operations[i][0]);
Habit toHabit = habitsArray.get(operations[i][1]);
habitList.reorder(fromHabit, toHabit);
int actualSequence[] = new int[10];
for (int j = 0; j < 10; j++)
{
Habit h = habitList.getByPosition(j);
assertThat(h.getPosition(), equalTo(j));
actualSequence[j] = toIntExact(h.getId());
}
assertThat(actualSequence, equalTo(expectedSequence[i]));
}
assertThat(activeHabits.indexOf(habitsArray.get(5)), equalTo(0));
assertThat(activeHabits.indexOf(habitsArray.get(2)), equalTo(1));
}
@Test
public void testReorder_withInvalidArguments() throws Exception
{
Habit h1 = habitsArray.get(0);
Habit h2 = fixtures.createEmptyHabit();
thrown.expect(IllegalArgumentException.class);
habitList.reorder(h1, h2);
}
@Test
public void testWriteCSV() throws IOException
{
HabitList list = modelFactory.buildHabitList();
Habit h1 = fixtures.createEmptyHabit();
h1.setName("Meditate");
h1.setDescription("Did you meditate this morning?");
h1.setFrequency(Frequency.DAILY);
h1.setColor(3);
Habit h2 = fixtures.createEmptyHabit();
h2.setName("Wake up early");
h2.setDescription("Did you wake up before 6am?");
h2.setFrequency(new Frequency(2, 3));
h2.setColor(5);
list.add(h1);
list.add(h2);
String expectedCSV =
"Position,Name,Description,NumRepetitions,Interval,Color\n" +
"001,Meditate,Did you meditate this morning?,1,1,#FF8F00\n" +
"002,Wake up early,Did you wake up before 6am?,2,3,#AFB42B\n";
StringWriter writer = new StringWriter();
list.writeCSV(writer);
assertThat(writer.toString(), equalTo(expectedCSV));
}
@Test
public void testAdd() throws Exception
{
Habit h1 = fixtures.createEmptyHabit();
assertFalse(h1.isArchived());
assertNull(h1.getId());
assertThat(habitList.indexOf(h1), equalTo(-1));
habitList.add(h1);
assertNotNull(h1.getId());
assertThat(habitList.indexOf(h1), not(equalTo(-1)));
assertThat(activeHabits.indexOf(h1), not(equalTo(-1)));
}
@Test
public void testAdd_withFilteredList() throws Exception
{
thrown.expect(IllegalStateException.class);
activeHabits.add(fixtures.createEmptyHabit());
}
@Test
public void testRemove_onFilteredList() throws Exception
{
thrown.expect(IllegalStateException.class);
activeHabits.remove(fixtures.createEmptyHabit());
}
@Test
public void testReorder_onFilteredList() throws Exception
{
Habit h1 = fixtures.createEmptyHabit();
Habit h2 = fixtures.createEmptyHabit();
thrown.expect(IllegalStateException.class);
activeHabits.reorder(h1, h2);
}
@Test
public void testReorder_onSortedList() throws Exception
{
habitList.setOrder(BY_SCORE);
Habit h1 = habitsArray.get(1);
Habit h2 = habitsArray.get(2);
thrown.expect(IllegalStateException.class);
habitList.reorder(h1, h2);
}
}

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.junit.*;
import org.junit.rules.*;
import nl.jqno.equalsverifier.*;
import static org.hamcrest.CoreMatchers.*;
import static org.isoron.uhabits.core.utils.DateUtils.*;
import static org.junit.Assert.*;
public class HabitTest extends BaseUnitTest
{
@Rule
public final ExpectedException exception = ExpectedException.none();
@Override
public void setUp() throws Exception
{
super.setUp();
}
@Test
public void testConstructor_default()
{
Habit habit = modelFactory.buildHabit();
assertFalse(habit.isArchived());
assertThat(habit.hasReminder(), is(false));
assertNotNull(habit.getStreaks());
assertNotNull(habit.getScores());
assertNotNull(habit.getRepetitions());
assertNotNull(habit.getCheckmarks());
}
@Test
public void test_copyAttributes()
{
Habit model = modelFactory.buildHabit();
model.setArchived(true);
model.setColor(0);
model.setFrequency(new Frequency(10, 20));
model.setReminder(new Reminder(8, 30, new WeekdayList(1)));
Habit habit = modelFactory.buildHabit();
habit.copyFrom(model);
assertThat(habit.isArchived(), is(model.isArchived()));
assertThat(habit.getColor(), is(model.getColor()));
assertThat(habit.getFrequency(), equalTo(model.getFrequency()));
assertThat(habit.getReminder(), equalTo(model.getReminder()));
}
@Test
public void test_hasReminder_clearReminder()
{
Habit h = modelFactory.buildHabit();
assertThat(h.hasReminder(), is(false));
h.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
assertThat(h.hasReminder(), is(true));
h.clearReminder();
assertThat(h.hasReminder(), is(false));
}
@Test
public void test_isCompleted() throws Exception
{
Habit h = modelFactory.buildHabit();
assertFalse(h.isCompletedToday());
h.getRepetitions().toggle(getToday());
assertTrue(h.isCompletedToday());
}
@Test
public void test_isCompleted_numerical() throws Exception
{
Habit h = modelFactory.buildHabit();
h.setType(Habit.NUMBER_HABIT);
h.setTargetType(Habit.AT_LEAST);
h.setTargetValue(100.0);
assertFalse(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 200);
assertTrue(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 100);
assertTrue(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 50);
assertFalse(h.isCompletedToday());
h.setTargetType(Habit.AT_MOST);
h.getRepetitions().toggle(getToday(), 200);
assertFalse(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 100);
assertTrue(h.isCompletedToday());
h.getRepetitions().toggle(getToday(), 50);
assertTrue(h.isCompletedToday());
}
@Test
public void testURI() throws Exception
{
assertTrue(habitList.isEmpty());
Habit h = modelFactory.buildHabit();
habitList.add(h);
assertThat(h.getId(), equalTo(0L));
assertThat(h.getUriString(),
equalTo("content://org.isoron.uhabits/habit/0"));
}
@Test
public void testEquals() throws Exception
{
EqualsVerifier
.forClass(Habit.HabitData.class)
.suppress(Warning.NONFINAL_FIELDS)
.verify();
EqualsVerifier.forClass(Repetition.class).verify();
EqualsVerifier.forClass(Score.class).verify();
EqualsVerifier.forClass(Streak.class).verify();
EqualsVerifier.forClass(Reminder.class).verify();
EqualsVerifier.forClass(WeekdayList.class).verify();
}
@Test
public void testToString() throws Exception
{
Habit h = modelFactory.buildHabit();
h.setReminder(new Reminder(22, 30, WeekdayList.EVERY_DAY));
String expected = "{id: <null>, data: {name: , description: ," +
" frequency: {numerator: 3, denominator: 7}," +
" color: 8, archived: false, targetType: 0," +
" targetValue: 100.0, type: 0, unit: ," +
" reminder: {hour: 22, minute: 30," +
" days: {weekdays: [true,true,true,true,true,true,true]}}," +
" position: 0}}";
assertThat(h.toString(), equalTo(expected));
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import android.support.annotation.*;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import java.util.*;
import static java.util.Calendar.*;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
public class RepetitionListTest extends BaseUnitTest
{
@NonNull
private RepetitionList reps;
@NonNull
private Habit habit;
private Timestamp today;
private long day;
@NonNull
private ModelObservable.Listener listener;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createEmptyHabit();
reps = habit.getRepetitions();
today = DateUtils.getToday();
reps.toggle(today.minus(3));
reps.toggle(today.minus(2));
reps.toggle(today);
reps.toggle(today.minus(7));
reps.toggle(today.minus(5));
listener = mock(ModelObservable.Listener.class);
reps.getObservable().addListener(listener);
reset(listener);
}
@Override
@After
public void tearDown() throws Exception
{
super.tearDown();
}
@Test
public void test_contains()
{
assertTrue(reps.containsTimestamp(today));
assertTrue(reps.containsTimestamp(today.minus(2)));
assertTrue(reps.containsTimestamp(today.minus(3)));
assertFalse(reps.containsTimestamp(today.minus(1)));
assertFalse(reps.containsTimestamp(today.minus(4)));
}
@Test
public void test_getOldest()
{
Repetition rep = reps.getOldest();
assertThat(rep.getTimestamp(), equalTo(today.minus(7)));
}
@Test
public void test_getWeekDayFrequency()
{
habit = fixtures.createEmptyHabit();
reps = habit.getRepetitions();
Random random = new Random(123L);
Integer weekdayCount[][] = new Integer[12][7];
Integer monthCount[] = new Integer[12];
Arrays.fill(monthCount, 0);
for (Integer row[] : weekdayCount) Arrays.fill(row, 0);
GregorianCalendar day = DateUtils.getStartOfTodayCalendar();
// Sets the current date to the end of November
day.set(2015, NOVEMBER, 30, 12, 0, 0);
DateUtils.setFixedLocalTime(day.getTimeInMillis());
// Add repetitions randomly from January to December
day.set(2015, JANUARY, 1, 0, 0, 0);
for (int i = 0; i < 365; i++)
{
if (random.nextBoolean())
{
int month = day.get(Calendar.MONTH);
int week = day.get(Calendar.DAY_OF_WEEK) % 7;
// Leave the month of March empty, to check that it returns null
if (month == MARCH) continue;
reps.toggle(new Timestamp(day));
// Repetitions in December should not be counted
if (month == DECEMBER) continue;
weekdayCount[month][week]++;
monthCount[month]++;
}
day.add(Calendar.DAY_OF_YEAR, 1);
}
HashMap<Timestamp, Integer[]> freq = reps.getWeekdayFrequency();
// Repetitions until November should be counted correctly
for (int month = 0; month < 11; month++)
{
day.set(2015, month, 1, 0, 0, 0);
Integer actualCount[] = freq.get(new Timestamp(day));
if (monthCount[month] == 0) assertThat(actualCount, equalTo(null));
else assertThat(actualCount, equalTo(weekdayCount[month]));
}
// Repetitions in December should be discarded
day.set(2015, DECEMBER, 1, 0, 0, 0);
assertThat(freq.get(new Timestamp(day)), equalTo(null));
}
@Test
public void test_toggle()
{
assertTrue(reps.containsTimestamp(today));
reps.toggle(today);
assertFalse(reps.containsTimestamp(today));
verify(listener).onModelChange();
reset(listener);
assertFalse(reps.containsTimestamp(today.minus(1)));
reps.toggle(today.minus(1));
assertTrue(reps.containsTimestamp(today.minus(1)));
verify(listener).onModelChange();
reset(listener);
habit.setType(Habit.NUMBER_HABIT);
reps.toggle(today, 100);
Repetition check = reps.getByTimestamp(today);
assertNotNull(check);
assertThat(check.getValue(), equalTo(100));
verify(listener).onModelChange();
reset(listener);
reps.toggle(today, 500);
check = reps.getByTimestamp(today);
assertNotNull(check);
assertThat(check.getValue(), equalTo(500));
verify(listener, times(2)).onModelChange();
reset(listener);
}
@Test
public void testToString() throws Exception
{
Repetition rep = new Repetition(Timestamp.ZERO.plus(100), 20);
assertThat(rep.toString(), equalTo("{timestamp: 1970-04-11, value: 20}"));
}
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import java.io.*;
import java.util.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
import static org.hamcrest.number.IsCloseTo.*;
public class ScoreListTest extends BaseUnitTest
{
private static final double E = 1e-6;
private Habit habit;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createEmptyHabit();
}
@Test
public void test_getAll()
{
toggleRepetitions(0, 20);
double expectedValues[] = {
0.655747,
0.636894,
0.617008,
0.596033,
0.573910,
0.550574,
0.525961,
0.500000,
0.472617,
0.443734,
0.413270,
0.381137,
0.347244,
0.311495,
0.273788,
0.234017,
0.192067,
0.147820,
0.101149,
0.051922,
};
int i = 0;
for (Score s : habit.getScores())
assertThat(s.getValue(), closeTo(expectedValues[i++], E));
}
@Test
public void test_getTodayValue()
{
toggleRepetitions(0, 20);
double actual = habit.getScores().getTodayValue();
assertThat(actual, closeTo(0.655747, E));
}
@Test
public void test_getValue()
{
toggleRepetitions(0, 20);
double expectedValues[] = {
0.655747,
0.636894,
0.617008,
0.596033,
0.573910,
0.550574,
0.525961,
0.500000,
0.472617,
0.443734,
0.413270,
0.381137,
0.347244,
0.311495,
0.273788,
0.234017,
0.192067,
0.147820,
0.101149,
0.051922,
0.000000,
0.000000,
0.000000
};
ScoreList scores = habit.getScores();
Timestamp current = DateUtils.getToday();
for (double expectedValue : expectedValues)
{
assertThat(scores.getValue(current), closeTo(expectedValue, E));
current = current.minus(1);
}
}
@Test
public void test_getValues()
{
toggleRepetitions(0, 20);
Timestamp today = DateUtils.getToday();
Timestamp from = today.minus(4);
Timestamp to = today.minus(2);
double[] expected = {
0.617008, 0.596033, 0.573909,
};
double[] actual = habit.getScores().getValues(from, to);
assertThat(actual.length, equalTo(expected.length));
for (int i = 0; i < actual.length; i++)
assertThat(actual[i], closeTo(expected[i], E));
}
@Test
public void test_groupBy()
{
Habit habit = fixtures.createLongHabit();
List<Score> list =
habit.getScores().groupBy(DateUtils.TruncateField.MONTH);
assertThat(list.size(), equalTo(5));
assertThat(list.get(0).getValue(), closeTo(0.653659, E));
assertThat(list.get(1).getValue(), closeTo(0.622715, E));
assertThat(list.get(2).getValue(), closeTo(0.520997, E));
}
@Test
public void test_invalidateNewerThan()
{
assertThat(habit.getScores().getTodayValue(), closeTo(0.0, E));
toggleRepetitions(0, 2);
assertThat(habit.getScores().getTodayValue(), closeTo(0.101149, E));
habit.setFrequency(new Frequency(1, 2));
habit.getScores().invalidateNewerThan(new Timestamp(0));
assertThat(habit.getScores().getTodayValue(), closeTo(0.051922, E));
}
@Test
public void test_writeCSV() throws IOException
{
Habit habit = fixtures.createShortHabit();
String expectedCSV = "2015-01-25,0.2654\n2015-01-24,0.2389\n" +
"2015-01-23,0.2475\n2015-01-22,0.2203\n" +
"2015-01-21,0.1921\n2015-01-20,0.1628\n" +
"2015-01-19,0.1325\n2015-01-18,0.1011\n" +
"2015-01-17,0.0686\n2015-01-16,0.0349\n";
StringWriter writer = new StringWriter();
habit.getScores().writeCSV(writer);
assertThat(writer.toString(), equalTo(expectedCSV));
}
private void toggleRepetitions(final int from, final int to)
{
RepetitionList reps = habit.getRepetitions();
Timestamp today = DateUtils.getToday();
for (int i = from; i < to; i++)
reps.toggle(today.minus(i));
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.junit.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
import static org.hamcrest.number.IsCloseTo.*;
import static org.isoron.uhabits.core.models.Score.*;
public class ScoreTest extends BaseUnitTest
{
private static final double E = 1e-6;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
}
@Test
public void test_compute_withDailyHabit()
{
int check = 1;
double freq = 1.0;
assertThat(compute(freq, 0, check), closeTo(0.051922, E));
assertThat(compute(freq, 0.5, check), closeTo(0.525961, E));
assertThat(compute(freq, 0.75, check), closeTo(0.762981, E));
check = 0;
assertThat(compute(freq, 0, check), closeTo(0, E));
assertThat(compute(freq, 0.5, check), closeTo(0.474039, E));
assertThat(compute(freq, 0.75, check), closeTo(0.711058, E));
}
@Test
public void test_compute_withNonDailyHabit()
{
int check = 1;
double freq = 1 / 3.0;
assertThat(compute(freq, 0, check), closeTo(0.017616, E));
assertThat(compute(freq, 0.5, check), closeTo(0.508808, E));
assertThat(compute(freq, 0.75, check), closeTo(0.754404, E));
check = 0;
assertThat(compute(freq, 0, check), closeTo(0.0, E));
assertThat(compute(freq, 0.5, check), closeTo(0.491192, E));
assertThat(compute(freq, 0.75, check), closeTo(0.736788, E));
}
@Test
public void testToString() throws Exception
{
Score score = new Score(Timestamp.ZERO.plus(100), 150.0);
assertThat(score.toString(), equalTo( "{timestamp: 1970-04-11, value: 150.0}"));
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import java.util.*;
import static junit.framework.TestCase.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
import static org.mockito.Mockito.*;
public class StreakListTest extends BaseUnitTest
{
private Habit habit;
private StreakList streaks;
private long day;
private Timestamp today;
private ModelObservable.Listener listener;
@Override
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createLongHabit();
habit.setFrequency(Frequency.DAILY);
streaks = habit.getStreaks();
streaks.rebuild();
listener = mock(ModelObservable.Listener.class);
streaks.getObservable().addListener(listener);
today = DateUtils.getToday();
}
@Test
public void testFindBeginning_withEmptyHistory()
{
Habit habit2 = fixtures.createEmptyHabit();
Timestamp beginning = habit2.getStreaks().findBeginning();
assertNull(beginning);
}
@Test
public void testFindBeginning_withLongHistory()
{
streaks.rebuild();
streaks.invalidateNewerThan(new Timestamp(0));
assertThat(streaks.findBeginning(), equalTo(today.minus(120)));
}
@Test
public void testGetAll() throws Exception
{
List<Streak> all = streaks.getAll();
assertThat(all.size(), equalTo(22));
assertThat(all.get(3).getEnd(), equalTo(today.minus(7)));
assertThat(all.get(3).getStart(), equalTo(today.minus(10)));
assertThat(all.get(17).getEnd(), equalTo(today.minus(89)));
assertThat(all.get(17).getStart(), equalTo(today.minus(91)));
}
@Test
public void testGetBest() throws Exception
{
List<Streak> best = streaks.getBest(4);
assertThat(best.size(), equalTo(4));
assertThat(best.get(0).getLength(), equalTo(4));
assertThat(best.get(1).getLength(), equalTo(3));
assertThat(best.get(2).getLength(), equalTo(5));
assertThat(best.get(3).getLength(), equalTo(6));
best = streaks.getBest(2);
assertThat(best.size(), equalTo(2));
assertThat(best.get(0).getLength(), equalTo(5));
assertThat(best.get(1).getLength(), equalTo(6));
}
@Test
public void testInvalidateNewer()
{
Streak s = streaks.getNewestComputed();
assertThat(s.getEnd(), equalTo(today));
streaks.invalidateNewerThan(today.minus(8));
verify(listener).onModelChange();
s = streaks.getNewestComputed();
assertNull(s);
}
@Test
public void testToString() throws Exception
{
Timestamp time = Timestamp.ZERO.plus(100);
Streak streak = new Streak(time, time.plus(10));
assertThat(streak.toString(), equalTo(
"{start: 1970-04-11, end: 1970-04-21}"));
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2015-2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertTrue;
public class TimestampTest extends BaseUnitTest
{
@Test
public void testCompare() throws Exception
{
Timestamp t1 = DateUtils.getToday();
Timestamp t2 = t1.minus(1);
Timestamp t3 = t1.plus(3);
assertThat(t1.compare(t2), greaterThan(0));
assertThat(t1.compare(t1), equalTo(0));
assertThat(t1.compare(t3), lessThan(0));
assertTrue(t1.isNewerThan(t2));
assertFalse(t1.isNewerThan(t1));
assertFalse(t2.isNewerThan(t1));
assertTrue(t2.isOlderThan(t1));
assertFalse(t1.isOlderThan(t2));
}
@Test
public void testDaysUntil() throws Exception
{
Timestamp t = DateUtils.getToday();
assertThat(t.daysUntil(t), equalTo(0));
assertThat(t.daysUntil(t.plus(1)), equalTo(1));
assertThat(t.daysUntil(t.plus(3)), equalTo(3));
assertThat(t.daysUntil(t.plus(300)), equalTo(300));
assertThat(t.daysUntil(t.minus(1)), equalTo(-1));
assertThat(t.daysUntil(t.minus(3)), equalTo(-3));
assertThat(t.daysUntil(t.minus(300)), equalTo(-300));
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models;
import org.isoron.uhabits.core.*;
import org.junit.*;
import static junit.framework.Assert.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
public class WeekdayListTest extends BaseUnitTest
{
@Test
public void test()
{
int daysInt = 124;
boolean[] daysArray = new boolean[]{
false, false, true, true, true, true, true
};
WeekdayList list = new WeekdayList(daysArray);
assertThat(list.toArray(), equalTo(daysArray));
assertThat(list.toInteger(), equalTo(daysInt));
list = new WeekdayList(daysInt);
assertThat(list.toArray(), equalTo(daysArray));
assertThat(list.toInteger(), equalTo(daysInt));
}
@Test
public void testEmpty()
{
WeekdayList list = new WeekdayList(0);
assertTrue(list.isEmpty());
assertFalse(WeekdayList.EVERY_DAY.isEmpty());
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models.sqlite;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.database.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.models.sqlite.records.*;
import org.isoron.uhabits.core.test.*;
import org.junit.*;
import org.junit.rules.*;
import java.util.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class SQLiteHabitListTest extends BaseUnitTest
{
@Rule
public ExpectedException exception = ExpectedException.none();
private SQLiteHabitList habitList;
private Repository<HabitRecord> repository;
private ModelObservable.Listener listener;
private ArrayList<Habit> habitsArray;
private HabitList activeHabits;
private HabitList reminderHabits;
@Override
public void setUp() throws Exception
{
super.setUp();
Database db = buildMemoryDatabase();
modelFactory = new SQLModelFactory(db);
habitList = new SQLiteHabitList(modelFactory);
fixtures = new HabitFixtures(modelFactory, habitList);
repository = new Repository<>(HabitRecord.class, db);
habitsArray = new ArrayList<>();
for (int i = 0; i < 10; i++)
{
Habit habit = fixtures.createEmptyHabit();
habit.setName("habit " + i);
habitList.update(habit);
habitsArray.add(habit);
if (i % 3 == 0)
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
}
habitsArray.get(0).setArchived(true);
habitsArray.get(1).setArchived(true);
habitsArray.get(4).setArchived(true);
habitsArray.get(7).setArchived(true);
habitList.update(habitsArray);
activeHabits = habitList.getFiltered(new HabitMatcherBuilder().build());
reminderHabits = habitList.getFiltered(new HabitMatcherBuilder()
.setArchivedAllowed(true)
.setReminderRequired(true)
.build());
listener = mock(ModelObservable.Listener.class);
habitList.getObservable().addListener(listener);
}
@Override
public void tearDown() throws Exception
{
habitList.getObservable().removeListener(listener);
super.tearDown();
}
@Test
public void testAdd_withDuplicate()
{
Habit habit = modelFactory.buildHabit();
habitList.add(habit);
verify(listener).onModelChange();
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 = repository.find(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 = repository.find(habit.getId());
assertNotNull(record);
assertThat(record.name, equalTo(habit.getName()));
}
@Test
public void testSize()
{
assertThat(habitList.size(), equalTo(10));
}
@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 testRemove() throws Exception
{
Habit h = habitList.getByPosition(2);
habitList.remove(h);
assertThat(habitList.indexOf(h), equalTo(-1));
HabitRecord rec = repository.find(2L);
assertNull(rec);
rec = repository.find(3L);
assertNotNull(rec);
assertThat(rec.position, equalTo(2));
}
@Test
public void testReorder()
{
Habit habit3 = habitList.getById(3);
Habit habit4 = habitList.getById(4);
assertNotNull(habit3);
assertNotNull(habit4);
habitList.reorder(habit4, habit3);
HabitRecord record3 = repository.find(3L);
assertNotNull(record3);
assertThat(record3.position, equalTo(4));
HabitRecord record4 = repository.find(4L);
assertNotNull(record4);
assertThat(record4.position, equalTo(3));
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.models.sqlite;
import android.support.annotation.*;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.database.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.models.sqlite.records.*;
import org.isoron.uhabits.core.test.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import java.util.*;
import static junit.framework.TestCase.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
import static org.isoron.uhabits.core.models.Checkmark.*;
public class SQLiteRepetitionListTest extends BaseUnitTest
{
private Habit habit;
private Timestamp today;
private RepetitionList repetitions;
private long day;
private Repository<RepetitionRecord> repository;
@Override
public void setUp() throws Exception
{
super.setUp();
Database db = buildMemoryDatabase();
modelFactory = new SQLModelFactory(db);
habitList = modelFactory.buildHabitList();
fixtures = new HabitFixtures(modelFactory, habitList);
repository = new Repository<>(RepetitionRecord.class, db);
habit = fixtures.createLongHabit();
repetitions = habit.getRepetitions();
today = DateUtils.getToday();
}
@Test
public void testAdd()
{
RepetitionRecord record = getByTimestamp(today.plus(1));
assertNull(record);
Repetition rep = new Repetition(today.plus(1), CHECKED_EXPLICITLY);
habit.getRepetitions().add(rep);
record = getByTimestamp(today.plus(1));
assertNotNull(record);
assertThat(record.value, equalTo(CHECKED_EXPLICITLY));
}
@Test
public void testGetByInterval()
{
List<Repetition> reps =
repetitions.getByInterval(today.minus(10), today);
assertThat(reps.size(), equalTo(8));
assertThat(reps.get(0).getTimestamp(), equalTo(today.minus(10)));
assertThat(reps.get(4).getTimestamp(), equalTo(today.minus(5)));
assertThat(reps.get(5).getTimestamp(), equalTo(today.minus(3)));
}
@Test
public void testGetByTimestamp()
{
Repetition rep = repetitions.getByTimestamp(today);
assertNotNull(rep);
assertThat(rep.getTimestamp(), equalTo(today));
rep = repetitions.getByTimestamp(today.minus(2));
assertNull(rep);
}
@Test
public void testGetOldest()
{
Repetition rep = repetitions.getOldest();
assertNotNull(rep);
assertThat(rep.getTimestamp(), equalTo(today.minus(120)));
}
@Test
public void testGetOldest_withEmptyHabit()
{
Habit empty = fixtures.createEmptyHabit();
Repetition rep = empty.getRepetitions().getOldest();
assertNull(rep);
}
@Test
public void testRemove()
{
RepetitionRecord record = getByTimestamp(today);
assertNotNull(record);
Repetition rep = record.toRepetition();
repetitions.remove(rep);
record = getByTimestamp(today);
assertNull(record);
}
@Nullable
private RepetitionRecord getByTimestamp(Timestamp timestamp)
{
String query = "where habit = ? and timestamp = ?";
String params[] = {
Long.toString(habit.getId()), Long.toString(timestamp.getUnixTime())
};
return repository.findFirst(query, params);
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package org.isoron.uhabits.core.models.sqlite.records;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
public class HabitRecordTest extends BaseUnitTest
{
@Test
public void testCopyRestore1()
{
Habit original = modelFactory.buildHabit();
original.setName("Hello world");
original.setDescription("Did you greet the world today?");
original.setColor(1);
original.setArchived(true);
original.setFrequency(Frequency.THREE_TIMES_PER_WEEK);
original.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
original.setId(1000L);
original.setPosition(20);
HabitRecord record = new HabitRecord();
record.copyFrom(original);
Habit duplicate = modelFactory.buildHabit();
record.copyTo(duplicate);
assertThat(original.getData(), equalTo(duplicate.getData()));
}
@Test
public void testCopyRestore2()
{
Habit original = modelFactory.buildHabit();
original.setName("Hello world");
original.setDescription("Did you greet the world today?");
original.setColor(5);
original.setArchived(false);
original.setFrequency(Frequency.DAILY);
original.setReminder(null);
original.setId(1L);
original.setPosition(15);
original.setType(Habit.NUMBER_HABIT);
original.setTargetValue(100);
original.setTargetType(Habit.AT_LEAST);
original.setUnit("miles");
HabitRecord record = new HabitRecord();
record.copyFrom(original);
Habit duplicate = modelFactory.buildHabit();
record.copyTo(duplicate);
assertThat(original.getData(), equalTo(duplicate.getData()));
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package org.isoron.uhabits.core.models.sqlite.records;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;
public class RepetitionRecordTest extends BaseUnitTest
{
@Test
public void testRecord() throws Exception
{
Repetition rep = new Repetition(Timestamp.ZERO.plus(100), 50);
RepetitionRecord record = new RepetitionRecord();
record.copyFrom(rep);
assertThat(rep, equalTo(record.toRepetition()));
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (C) 2015-2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences;
import android.support.annotation.*;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.ui.*;
import org.junit.*;
import org.mockito.*;
import java.io.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class PreferencesTest extends BaseUnitTest
{
@NonNull
private Preferences prefs;
@Mock
private Preferences.Listener listener;
private PropertiesStorage storage;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
File file = File.createTempFile("prefs", ".properties");
file.deleteOnExit();
storage = new PropertiesStorage(file);
prefs = new Preferences(storage);
prefs.addListener(listener);
}
@Test
public void testClear() throws Exception
{
prefs.setDefaultHabitColor(99);
prefs.clear();
assertThat(prefs.getDefaultHabitColor(0), equalTo(0));
}
@Test
public void testHabitColor() throws Exception
{
assertThat(prefs.getDefaultHabitColor(999), equalTo(999));
prefs.setDefaultHabitColor(10);
assertThat(prefs.getDefaultHabitColor(999), equalTo(10));
}
@Test
public void testDefaultOrder() throws Exception
{
assertThat(prefs.getDefaultOrder(), equalTo(HabitList.Order.BY_POSITION));
prefs.setDefaultOrder(HabitList.Order.BY_SCORE);
assertThat(prefs.getDefaultOrder(), equalTo(HabitList.Order.BY_SCORE));
storage.putString("pref_default_order", "BOGUS");
assertThat(prefs.getDefaultOrder(), equalTo(HabitList.Order.BY_POSITION));
assertThat(storage.getString("pref_default_order", ""), equalTo("BY_POSITION"));
}
@Test
public void testDefaultSpinnerPosition() throws Exception
{
assertThat(prefs.getDefaultScoreSpinnerPosition(), equalTo(1));
prefs.setDefaultScoreSpinnerPosition(4);
assertThat(prefs.getDefaultScoreSpinnerPosition(), equalTo(4));
storage.putInt("pref_score_view_interval", 9000);
assertThat(prefs.getDefaultScoreSpinnerPosition(), equalTo(1));
assertThat(storage.getInt("pref_score_view_interval", 0), equalTo(1));
}
@Test
public void testLastHint() throws Exception
{
assertThat(prefs.getLastHintNumber(), equalTo(-1));
assertNull(prefs.getLastHintTimestamp());
prefs.updateLastHint(34, Timestamp.ZERO.plus(100));
assertThat(prefs.getLastHintNumber(), equalTo(34));
assertThat(prefs.getLastHintTimestamp(), equalTo(Timestamp.ZERO.plus(100)));
}
@Test
public void testSync() throws Exception
{
assertThat(prefs.getLastSync(), equalTo(0L));
prefs.setLastSync(100);
assertThat(prefs.getLastSync(), equalTo(100L));
assertThat(prefs.getSyncAddress(),
equalTo(Preferences.DEFAULT_SYNC_SERVER));
prefs.setSyncAddress("example");
assertThat(prefs.getSyncAddress(), equalTo("example"));
verify(listener).onSyncFeatureChanged();
reset(listener);
assertThat(prefs.getSyncKey(), equalTo(""));
prefs.setSyncKey("123");
assertThat(prefs.getSyncKey(), equalTo("123"));
verify(listener).onSyncFeatureChanged();
reset(listener);
assertFalse(prefs.isSyncEnabled());
prefs.setSyncEnabled(true);
assertTrue(prefs.isSyncEnabled());
verify(listener).onSyncFeatureChanged();
reset(listener);
String id = prefs.getSyncClientId();
assertFalse(id.isEmpty());
assertThat(prefs.getSyncClientId(), equalTo(id));
}
@Test
public void testTheme() throws Exception
{
assertThat(prefs.getTheme(), equalTo(ThemeSwitcher.THEME_LIGHT));
prefs.setTheme(ThemeSwitcher.THEME_DARK);
assertThat(prefs.getTheme(), equalTo(ThemeSwitcher.THEME_DARK));
assertFalse(prefs.isPureBlackEnabled());
prefs.setPureBlackEnabled(true);
assertTrue(prefs.isPureBlackEnabled());
}
@Test
public void testNotifications() throws Exception
{
assertFalse(prefs.shouldMakeNotificationsSticky());
prefs.setNotificationsSticky(true);
assertTrue(prefs.shouldMakeNotificationsSticky());
assertFalse(prefs.shouldMakeNotificationsLed());
prefs.setNotificationsLed(true);
assertTrue(prefs.shouldMakeNotificationsLed());
assertThat(prefs.getSnoozeInterval(), equalTo(15L));
prefs.setSnoozeInterval(30);
assertThat(prefs.getSnoozeInterval(), equalTo(30L));
}
@Test
public void testAppVersionAndLaunch() throws Exception
{
assertThat(prefs.getLastAppVersion(), equalTo(0));
prefs.setLastAppVersion(23);
assertThat(prefs.getLastAppVersion(), equalTo(23));
assertTrue(prefs.isFirstRun());
prefs.setFirstRun(false);
assertFalse(prefs.isFirstRun());
assertThat(prefs.getLaunchCount(), equalTo(0));
prefs.incrementLaunchCount();
assertThat(prefs.getLaunchCount(), equalTo(1));
}
@Test
public void testCheckmarks() throws Exception
{
assertFalse(prefs.isCheckmarkSequenceReversed());
prefs.setCheckmarkSequenceReversed(true);
assertTrue(prefs.isCheckmarkSequenceReversed());
assertFalse(prefs.isShortToggleEnabled());
prefs.setShortToggleEnabled(true);
assertTrue(prefs.isShortToggleEnabled());
}
@Test
public void testNumericalHabits() throws Exception
{
assertFalse(prefs.isNumericalHabitsFeatureEnabled());
prefs.setNumericalHabitsFeatureEnabled(true);
assertTrue(prefs.isNumericalHabitsFeatureEnabled());
}
@Test
public void testDeveloper() throws Exception
{
assertFalse(prefs.isDeveloper());
prefs.setDeveloper(true);
assertTrue(prefs.isDeveloper());
}
@Test
public void testFiltering() throws Exception
{
assertFalse(prefs.getShowArchived());
assertTrue(prefs.getShowCompleted());
prefs.setShowArchived(true);
prefs.setShowCompleted(false);
assertTrue(prefs.getShowArchived());
assertFalse(prefs.getShowCompleted());
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2015-2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.preferences;
import org.isoron.uhabits.core.*;
import org.junit.*;
import java.io.*;
import java.util.*;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertTrue;
public class PropertiesStorageTest extends BaseUnitTest
{
private PropertiesStorage storage;
private File file;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
file = File.createTempFile("test", ".properties");
file.deleteOnExit();
storage = new PropertiesStorage(file);
}
@Test
public void testPutGetRemove() throws Exception
{
storage.putBoolean("booleanKey", true);
assertTrue(storage.getBoolean("booleanKey", false));
assertFalse(storage.getBoolean("random", false));
storage.putInt("intKey", 64);
assertThat(storage.getInt("intKey", 200), equalTo(64));
assertThat(storage.getInt("random", 200), equalTo(200));
storage.putLong("longKey", 64L);
assertThat(storage.getLong("intKey", 200L), equalTo(64L));
assertThat(storage.getLong("random", 200L), equalTo(200L));
storage.putString("stringKey", "Hello");
assertThat(storage.getString("stringKey", ""), equalTo("Hello"));
assertThat(storage.getString("random", ""), equalTo(""));
storage.remove("stringKey");
assertThat(storage.getString("stringKey", ""), equalTo(""));
storage.clear();
assertThat(storage.getLong("intKey", 200L), equalTo(200L));
assertFalse(storage.getBoolean("booleanKey", false));
}
@Test
public void testPersistence() throws Exception
{
storage.putBoolean("booleanKey", true);
storage.putInt("intKey", 64);
storage.putLong("longKey", 64L);
storage.putString("stringKey", "Hello");
PropertiesStorage storage2 = new PropertiesStorage(file);
assertTrue(storage2.getBoolean("booleanKey", false));
assertThat(storage2.getInt("intKey", 200), equalTo(64));
assertThat(storage2.getLong("intKey", 200L), equalTo(64L));
assertThat(storage2.getString("stringKey", ""), equalTo("Hello"));
}
@Test
public void testLongArray() throws Exception
{
long[] expected1 = new long[]{1L, 2L, 3L, 5L};
long[] expected2 = new long[]{1L};
long[] expected3 = new long[]{};
long[] expected4 = new long[]{};
storage.putLongArray("key1", expected1);
storage.putLongArray("key2", expected2);
storage.putLongArray("key3", expected3);
long[] actual1 = storage.getLongArray("key1");
long[] actual2 = storage.getLongArray("key2");
long[] actual3 = storage.getLongArray("key3");
long[] actual4 = storage.getLongArray("invalidKey");
assertTrue(Arrays.equals(actual1, expected1));
assertTrue(Arrays.equals(actual2, expected2));
assertTrue(Arrays.equals(actual3, expected3));
assertTrue(Arrays.equals(actual4, expected4));
assertEquals("1,2,3,5", storage.getString("key1", ""));
assertEquals(1, storage.getLong("key2", -1));
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.reminders;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import org.junit.runner.*;
import org.mockito.*;
import org.mockito.junit.*;
import java.util.*;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class ReminderSchedulerTest extends BaseUnitTest
{
private Habit habit;
private ReminderScheduler reminderScheduler;
@Mock
private ReminderScheduler.SystemScheduler sys;
@Before
@Override
public void setUp() throws Exception
{
super.setUp();
habit = fixtures.createEmptyHabit();
reminderScheduler =
new ReminderScheduler(commandRunner, habitList, sys);
DateUtils.setFixedTimeZone(TimeZone.getTimeZone("GMT-4"));
}
@Test
public void testScheduleAll()
{
long now = unixTime(2015, 1, 26, 13, 0);
DateUtils.setFixedLocalTime(now);
Habit h1 = fixtures.createEmptyHabit();
Habit h2 = fixtures.createEmptyHabit();
Habit h3 = fixtures.createEmptyHabit();
h1.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
h2.setReminder(new Reminder(18, 30, WeekdayList.EVERY_DAY));
h3.setReminder(null);
habitList.add(h1);
habitList.add(h2);
habitList.add(h3);
reminderScheduler.scheduleAll();
verify(sys).scheduleShowReminder(eq(unixTime(2015, 1, 27, 12, 30)),
eq(h1), anyLong());
verify(sys).scheduleShowReminder(eq(unixTime(2015, 1, 26, 22, 30)),
eq(h2), anyLong());
Mockito.verifyNoMoreInteractions(sys);
}
@Test
public void testSchedule_atSpecificTime()
{
long atTime = unixTime(2015, 1, 30, 11, 30);
long expectedCheckmarkTime = unixTime(2015, 1, 30, 0, 0);
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
scheduleAndVerify(atTime, expectedCheckmarkTime, atTime);
}
@Test
public void testSchedule_laterToday()
{
long now = unixTime(2015, 1, 26, 6, 30);
DateUtils.setFixedLocalTime(now);
long expectedCheckmarkTime = unixTime(2015, 1, 26, 0, 0);
long expectedReminderTime = unixTime(2015, 1, 26, 12, 30);
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
scheduleAndVerify(null, expectedCheckmarkTime, expectedReminderTime);
}
@Test
public void testSchedule_tomorrow()
{
long now = unixTime(2015, 1, 26, 13, 0);
DateUtils.setFixedLocalTime(now);
long expectedCheckmarkTime = unixTime(2015, 1, 27, 0, 0);
long expectedReminderTime = unixTime(2015, 1, 27, 12, 30);
habit.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY));
scheduleAndVerify(null, expectedCheckmarkTime, expectedReminderTime);
}
@Test
public void testSchedule_withoutReminder()
{
reminderScheduler.schedule(habit);
Mockito.verifyZeroInteractions(sys);
}
public long unixTime(int year, int month, int day, int hour, int minute)
{
Calendar cal = DateUtils.getStartOfTodayCalendar();
cal.set(year, month, day, hour, minute);
return cal.getTimeInMillis();
}
private void scheduleAndVerify(Long atTime,
long expectedCheckmarkTime,
long expectedReminderTime)
{
if(atTime == null) reminderScheduler.schedule(habit);
else reminderScheduler.scheduleAtTime(habit, atTime);
verify(sys).scheduleShowReminder(expectedReminderTime, habit,
expectedCheckmarkTime);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.tasks;
import org.isoron.uhabits.core.*;
import org.junit.*;
import org.junit.runner.*;
import org.junit.runners.*;
import org.mockito.*;
import static org.mockito.Mockito.*;
@RunWith(JUnit4.class)
public class SingleThreadTaskRunnerTest extends BaseUnitTest
{
private SingleThreadTaskRunner runner;
private Task task;
@Override
public void setUp() throws Exception
{
super.setUp();
runner = new SingleThreadTaskRunner();
task = mock(Task.class);
}
@Test
public void test()
{
runner.execute(task);
InOrder inOrder = inOrder(task);
inOrder.verify(task).onAttached(runner);
inOrder.verify(task).onPreExecute();
inOrder.verify(task).doInBackground();
inOrder.verify(task).onPostExecute();
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.about;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.preferences.*;
import org.junit.*;
import org.mockito.*;
import static org.isoron.uhabits.core.ui.screens.about.AboutBehavior.Message.YOU_ARE_NOW_A_DEVELOPER;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
public class AboutBehaviorTest extends BaseUnitTest
{
private AboutBehavior behavior;
@Mock
private Preferences prefs;
@Mock
private AboutBehavior.Screen screen;
@Before
public void setUp() throws Exception
{
super.setUp();
behavior = new AboutBehavior(prefs, screen);
}
@Test
public void onPressDeveloperCountdown() throws Exception
{
behavior.onPressDeveloperCountdown();
behavior.onPressDeveloperCountdown();
behavior.onPressDeveloperCountdown();
behavior.onPressDeveloperCountdown();
verifyZeroInteractions(screen);
verifyZeroInteractions(prefs);
behavior.onPressDeveloperCountdown();
verify(screen).showMessage(YOU_ARE_NOW_A_DEVELOPER);
verify(prefs).setDeveloper(true);
behavior.onPressDeveloperCountdown();
verifyZeroInteractions(screen);
verifyZeroInteractions(prefs);
}
@Test
public void onRateApp() throws Exception
{
behavior.onRateApp();
verify(screen).showRateAppWebsite();
}
@Test
public void onSendFeedback() throws Exception
{
behavior.onSendFeedback();
verify(screen).showSendFeedbackScreen();
}
@Test
public void onTranslateApp() throws Exception
{
behavior.onTranslateApp();
verify(screen).showTranslationWebsite();
}
@Test
public void onViewSourceCode() throws Exception
{
behavior.onViewSourceCode();
verify(screen).showSourceCodeWebsite();
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.habits.list;
import junit.framework.Assert;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.commands.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.Test;
import java.util.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.core.IsEqual.*;
import static org.mockito.Mockito.*;
public class HabitCardListCacheTest extends BaseUnitTest
{
private HabitCardListCache cache;
private HabitCardListCache.Listener listener;
@Override
public void setUp() throws Exception
{
super.setUp();
habitList.removeAll();
for (int i = 0; i < 10; i++)
{
if (i == 3) habitList.add(fixtures.createLongHabit());
else habitList.add(fixtures.createShortHabit());
}
cache = new HabitCardListCache(habitList, commandRunner, taskRunner);
cache.setCheckmarkCount(10);
cache.refreshAllHabits();
cache.onAttached();
listener = mock(HabitCardListCache.Listener.class);
cache.setListener(listener);
}
@Override
public void tearDown()
{
cache.onDetached();
}
@Test
public void testCommandListener_all()
{
assertThat(cache.getHabitCount(), equalTo(10));
Habit h = habitList.getByPosition(0);
commandRunner.execute(
new DeleteHabitsCommand(habitList, Collections.singletonList(h)),
null);
verify(listener).onItemRemoved(0);
verify(listener).onRefreshFinished();
assertThat(cache.getHabitCount(), equalTo(9));
}
@Test
public void testCommandListener_single()
{
Habit h2 = habitList.getByPosition(2);
Timestamp today = DateUtils.getToday();
commandRunner.execute(new ToggleRepetitionCommand(habitList, h2, today),
h2.getId());
verify(listener).onItemChanged(2);
verify(listener).onRefreshFinished();
verifyNoMoreInteractions(listener);
}
@Test
public void testGet()
{
assertThat(cache.getHabitCount(), equalTo(10));
Habit h = habitList.getByPosition(3);
junit.framework.Assert.assertNotNull(h.getId());
double score = h.getScores().getTodayValue();
assertThat(cache.getHabitByPosition(3), equalTo(h));
assertThat(cache.getScore(h.getId()), equalTo(score));
Timestamp today = DateUtils.getToday();
int[] actualCheckmarks = cache.getCheckmarks(h.getId());
int[] expectedCheckmarks =
h.getCheckmarks().getValues(today.minus(9), today);
assertThat(actualCheckmarks, equalTo(expectedCheckmarks));
}
@Test
public void testRemoval()
{
removeHabitAt(0);
removeHabitAt(3);
cache.refreshAllHabits();
verify(listener).onItemRemoved(0);
verify(listener).onItemRemoved(3);
verify(listener).onRefreshFinished();
assertThat(cache.getHabitCount(), equalTo(8));
}
@Test
public void testRefreshWithNoChanges()
{
cache.refreshAllHabits();
verify(listener).onRefreshFinished();
verifyNoMoreInteractions(listener);
}
@Test
public void testReorder_onCache()
{
Habit h2 = cache.getHabitByPosition(2);
Habit h3 = cache.getHabitByPosition(3);
Habit h7 = cache.getHabitByPosition(7);
cache.reorder(2, 7);
assertThat(cache.getHabitByPosition(2), equalTo(h3));
assertThat(cache.getHabitByPosition(7), equalTo(h2));
assertThat(cache.getHabitByPosition(6), equalTo(h7));
verify(listener).onItemMoved(2, 7);
verifyNoMoreInteractions(listener);
}
@Test
public void testReorder_onList()
{
Habit h2 = habitList.getByPosition(2);
Habit h3 = habitList.getByPosition(3);
Habit h7 = habitList.getByPosition(7);
assertThat(cache.getHabitByPosition(2), equalTo(h2));
assertThat(cache.getHabitByPosition(7), equalTo(h7));
reset(listener);
habitList.reorder(h2, h7);
cache.refreshAllHabits();
assertThat(cache.getHabitByPosition(2), equalTo(h3));
assertThat(cache.getHabitByPosition(7), equalTo(h2));
assertThat(cache.getHabitByPosition(6), equalTo(h7));
verify(listener).onItemMoved(3, 2);
verify(listener).onItemMoved(4, 3);
verify(listener).onItemMoved(5, 4);
verify(listener).onItemMoved(6, 5);
verify(listener).onItemMoved(7, 6);
verify(listener).onRefreshFinished();
verifyNoMoreInteractions(listener);
}
protected void removeHabitAt(int position)
{
Habit h = habitList.getByPosition(position);
Assert.assertNotNull(h);
habitList.remove(h);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.habits.list;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import org.mockito.*;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
public class HintListTest extends BaseUnitTest
{
private HintList hintList;
private String[] hints;
@Mock
private Preferences prefs;
private Timestamp today;
private Timestamp yesterday;
@Override
public void setUp() throws Exception
{
super.setUp();
today = DateUtils.getToday();
yesterday = today.minus(1);
hints = new String[]{ "hint1", "hint2", "hint3" };
hintList = new HintList(prefs, hints);
}
@Test
public void pop() throws Exception
{
when(prefs.getLastHintNumber()).thenReturn(-1);
assertThat(hintList.pop(), equalTo("hint1"));
verify(prefs).updateLastHint(0, today);
when(prefs.getLastHintNumber()).thenReturn(2);
assertNull(hintList.pop());
}
@Test
public void shouldShow() throws Exception
{
when(prefs.getLastHintTimestamp()).thenReturn(today);
assertFalse(hintList.shouldShow());
when(prefs.getLastHintTimestamp()).thenReturn(yesterday);
assertTrue(hintList.shouldShow());
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.habits.list;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.utils.*;
import org.junit.*;
import org.mockito.*;
import java.io.*;
import static java.nio.file.Files.createTempDirectory;
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.apache.commons.io.FileUtils.listFiles;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.COULD_NOT_EXPORT;
import static org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.COULD_NOT_GENERATE_BUG_REPORT;
import static org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior.Message.DATABASE_REPAIRED;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ListHabitsBehaviorTest extends BaseUnitTest
{
@Mock
private ListHabitsBehavior.DirFinder dirFinder;
@Mock
private Preferences prefs;
private ListHabitsBehavior behavior;
@Mock
private ListHabitsBehavior.Screen screen;
private Habit habit1, habit2;
@Captor
ArgumentCaptor<ListHabitsBehavior.NumberPickerCallback> picker;
@Mock
private ListHabitsBehavior.BugReporter bugReporter;
@Override
@Before
public void setUp() throws Exception
{
super.setUp();
habit1 = fixtures.createShortHabit();
habit2 = fixtures.createNumericalHabit();
habitList.add(habit1);
habitList.add(habit2);
clearInvocations(habitList);
behavior = new ListHabitsBehavior(habitList, dirFinder, taskRunner, screen,
commandRunner, prefs, bugReporter);
}
@Test
public void testOnEdit()
{
behavior.onEdit(habit2, DateUtils.getToday());
verify(screen).showNumberPicker(eq(0.1), eq("miles"), picker.capture());
picker.getValue().onNumberPicked(100);
assertThat(habit2.getCheckmarks().getTodayValue(), equalTo(100000));
}
@Test
public void testOnExportCSV() throws Exception
{
File outputDir = createTempDirectory("CSV").toFile();
when(dirFinder.getCSVOutputDir()).thenReturn(outputDir);
behavior.onExportCSV();
verify(screen).showSendFileScreen(any());
assertThat(listFiles(outputDir, null, false).size(), equalTo(1));
deleteDirectory(outputDir);
}
@Test
public void testOnExportCSV_fail() throws Exception
{
File outputDir = createTempDirectory("CSV").toFile();
outputDir.setWritable(false);
when(dirFinder.getCSVOutputDir()).thenReturn(outputDir);
behavior.onExportCSV();
verify(screen).showMessage(COULD_NOT_EXPORT);
assertTrue(outputDir.delete());
}
@Test
public void testOnHabitClick()
{
behavior.onClickHabit(habit1);
verify(screen).showHabitScreen(habit1);
}
@Test
public void testOnHabitReorder()
{
Habit from = habit1;
Habit to = habit2;
behavior.onReorderHabit(from, to);
verify(habitList).reorder(from, to);
}
@Test
public void testOnRepairDB()
{
behavior.onRepairDB();
verify(habitList).repair();
verify(screen).showMessage(DATABASE_REPAIRED);
}
@Test
public void testOnSendBugReport() throws IOException
{
when(bugReporter.getBugReport()).thenReturn("hello");
behavior.onSendBugReport();
verify(bugReporter).dumpBugReportToFile();
verify(screen).showSendBugReportToDeveloperScreen("hello");
when(bugReporter.getBugReport()).thenThrow(new IOException());
behavior.onSendBugReport();
verify(screen).showMessage(COULD_NOT_GENERATE_BUG_REPORT);
}
@Test
public void testOnStartup_firstLaunch()
{
Timestamp today = DateUtils.getToday();
when(prefs.isFirstRun()).thenReturn(true);
behavior.onStartup();
verify(prefs).setFirstRun(false);
verify(prefs).updateLastHint(-1, today);
verify(screen).showIntroScreen();
}
@Test
public void testOnStartup_notFirstLaunch()
{
when(prefs.isFirstRun()).thenReturn(false);
behavior.onStartup();
verify(prefs).incrementLaunchCount();
}
@Test
public void testOnToggle()
{
assertTrue(habit1.isCompletedToday());
behavior.onToggle(habit1, DateUtils.getToday());
assertFalse(habit1.isCompletedToday());
}
}

View File

@@ -0,0 +1,190 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.habits.list;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.preferences.*;
import org.isoron.uhabits.core.ui.*;
import org.junit.*;
import org.mockito.*;
import static junit.framework.TestCase.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.isoron.uhabits.core.models.HabitList.Order.*;
import static org.mockito.Mockito.*;
public class ListHabitsMenuBehaviorTest extends BaseUnitTest
{
private ListHabitsMenuBehavior behavior;
@Mock
private ListHabitsMenuBehavior.Screen screen;
@Mock
private ListHabitsMenuBehavior.Adapter adapter;
@Mock
private Preferences prefs;
@Mock
private ThemeSwitcher themeSwitcher;
@Captor
private ArgumentCaptor<HabitMatcher> matcherCaptor;
@Captor
private ArgumentCaptor<HabitList.Order> orderCaptor;
@Override
public void setUp() throws Exception
{
super.setUp();
behavior =
new ListHabitsMenuBehavior(screen, adapter, prefs, themeSwitcher);
clearInvocations(adapter);
}
@Test
public void testInitialFilter()
{
when(prefs.getShowArchived()).thenReturn(true);
when(prefs.getShowCompleted()).thenReturn(true);
behavior =
new ListHabitsMenuBehavior(screen, adapter, prefs, themeSwitcher);
verify(adapter).setFilter(matcherCaptor.capture());
verify(adapter).refresh();
verifyNoMoreInteractions(adapter);
clearInvocations(adapter);
assertTrue(matcherCaptor.getValue().isArchivedAllowed());
assertTrue(matcherCaptor.getValue().isCompletedAllowed());
when(prefs.getShowArchived()).thenReturn(false);
when(prefs.getShowCompleted()).thenReturn(false);
behavior =
new ListHabitsMenuBehavior(screen, adapter, prefs, themeSwitcher);
verify(adapter).setFilter(matcherCaptor.capture());
verify(adapter).refresh();
verifyNoMoreInteractions(adapter);
assertFalse(matcherCaptor.getValue().isArchivedAllowed());
assertFalse(matcherCaptor.getValue().isCompletedAllowed());
}
@Test
public void testOnCreateHabit()
{
behavior.onCreateHabit();
verify(screen).showCreateHabitScreen();
}
@Test
public void testOnSortByColor()
{
behavior.onSortByColor();
verify(adapter).setOrder(orderCaptor.capture());
assertThat(orderCaptor.getValue(), equalTo(BY_COLOR));
}
@Test
public void testOnSortManually()
{
behavior.onSortByManually();
verify(adapter).setOrder(orderCaptor.capture());
assertThat(orderCaptor.getValue(), equalTo(BY_POSITION));
}
@Test
public void testOnSortScore()
{
behavior.onSortByScore();
verify(adapter).setOrder(orderCaptor.capture());
assertThat(orderCaptor.getValue(), equalTo(BY_SCORE));
}
@Test
public void testOnSortName()
{
behavior.onSortByName();
verify(adapter).setOrder(orderCaptor.capture());
assertThat(orderCaptor.getValue(), equalTo(BY_NAME));
}
@Test
public void testOnToggleShowArchived()
{
behavior.onToggleShowArchived();
verify(adapter).setFilter(matcherCaptor.capture());
assertTrue(matcherCaptor.getValue().isArchivedAllowed());
clearInvocations(adapter);
behavior.onToggleShowArchived();
verify(adapter).setFilter(matcherCaptor.capture());
assertFalse(matcherCaptor.getValue().isArchivedAllowed());
}
@Test
public void testOnToggleShowCompleted()
{
behavior.onToggleShowCompleted();
verify(adapter).setFilter(matcherCaptor.capture());
assertTrue(matcherCaptor.getValue().isCompletedAllowed());
clearInvocations(adapter);
behavior.onToggleShowCompleted();
verify(adapter).setFilter(matcherCaptor.capture());
assertFalse(matcherCaptor.getValue().isCompletedAllowed());
}
@Test
public void testOnViewAbout()
{
behavior.onViewAbout();
verify(screen).showAboutScreen();
}
@Test
public void testOnViewFAQ()
{
behavior.onViewFAQ();
verify(screen).showFAQScreen();
}
@Test
public void testOnViewSettings()
{
behavior.onViewSettings();
verify(screen).showSettingsScreen();
}
@Test
public void testOnToggleNightMode()
{
behavior.onToggleNightMode();
verify(themeSwitcher).toggleNightMode();
verify(screen).applyTheme();
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.habits.list;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.ui.callbacks.*;
import org.junit.*;
import org.mockito.*;
import java.util.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static junit.framework.TestCase.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;
public class ListHabitsSelectionMenuBehaviorTest extends BaseUnitTest
{
@Mock
private ListHabitsSelectionMenuBehavior.Screen screen;
@Mock
private ListHabitsSelectionMenuBehavior.Adapter adapter;
private ListHabitsSelectionMenuBehavior behavior;
private Habit habit1, habit2, habit3;
@Captor
private ArgumentCaptor<OnColorPickedCallback> colorPickerCallback;
@Captor
private ArgumentCaptor<OnConfirmedCallback> deleteCallback;
@Test
public void canArchive() throws Exception
{
when(adapter.getSelected()).thenReturn(asList(habit1, habit2));
assertFalse(behavior.canArchive());
when(adapter.getSelected()).thenReturn(asList(habit2, habit3));
assertTrue(behavior.canArchive());
}
@Test
public void canEdit() throws Exception
{
when(adapter.getSelected()).thenReturn(singletonList(habit1));
assertTrue(behavior.canEdit());
when(adapter.getSelected()).thenReturn(asList(habit1, habit2));
assertFalse(behavior.canEdit());
}
@Test
public void canUnarchive() throws Exception
{
when(adapter.getSelected()).thenReturn(asList(habit1, habit2));
assertFalse(behavior.canUnarchive());
when(adapter.getSelected()).thenReturn(singletonList(habit1));
assertTrue(behavior.canUnarchive());
}
@Test
public void onArchiveHabits() throws Exception
{
assertFalse(habit2.isArchived());
when(adapter.getSelected()).thenReturn(singletonList(habit2));
behavior.onArchiveHabits();
assertTrue(habit2.isArchived());
}
@Test
public void onChangeColor() throws Exception
{
assertThat(habit1.getColor(), equalTo(8));
assertThat(habit2.getColor(), equalTo(8));
when(adapter.getSelected()).thenReturn(asList(habit1, habit2));
behavior.onChangeColor();
verify(screen).showColorPicker(eq(8), colorPickerCallback.capture());
colorPickerCallback.getValue().onColorPicked(30);
assertThat(habit1.getColor(), equalTo(30));
}
@Test
public void onDeleteHabits() throws Exception
{
Long id = habit1.getId();
assertNotNull(id);
assertNotNull(habitList.getById(id));
when(adapter.getSelected()).thenReturn(singletonList(habit1));
behavior.onDeleteHabits();
verify(screen).showDeleteConfirmationScreen(deleteCallback.capture());
deleteCallback.getValue().onConfirmed();
assertNull(habitList.getById(id));
}
@Test
public void onEditHabits() throws Exception
{
List<Habit> selected = asList(habit1, habit2);
when(adapter.getSelected()).thenReturn(selected);
behavior.onEditHabits();
verify(screen).showEditHabitsScreen(selected);
}
@Test
public void onUnarchiveHabits() throws Exception
{
assertTrue(habit1.isArchived());
when(adapter.getSelected()).thenReturn(singletonList(habit1));
behavior.onUnarchiveHabits();
assertFalse(habit1.isArchived());
}
@Override
public void setUp() throws Exception
{
super.setUp();
habit1 = fixtures.createShortHabit();
habit1.setArchived(true);
habit2 = fixtures.createShortHabit();
habit3 = fixtures.createShortHabit();
habitList.add(habit1);
habitList.add(habit2);
habitList.add(habit3);
behavior =
new ListHabitsSelectionMenuBehavior(habitList, screen, adapter,
commandRunner);
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.ui.screens.habits.show;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.io.*;
import static java.nio.file.Files.*;
import static org.apache.commons.io.FileUtils.*;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
public class ShowHabitMenuBehaviorTest extends BaseUnitTest
{
private ShowHabitMenuBehavior.System system;
private ShowHabitMenuBehavior.Screen screen;
private Habit habit;
private ShowHabitMenuBehavior menu;
@Override
public void setUp() throws Exception
{
super.setUp();
system = mock(ShowHabitMenuBehavior.System.class);
screen = mock(ShowHabitMenuBehavior.Screen.class);
habit = fixtures.createShortHabit();
menu = new ShowHabitMenuBehavior(habitList, habit, taskRunner, screen,
system, commandRunner);
}
@Test
public void testOnEditHabit()
{
menu.onEditHabit();
verify(screen).showEditHabitScreen(habit);
}
@Test
public void testOnExport() throws Exception
{
File outputDir = createTempDirectory("CSV").toFile();
when(system.getCSVOutputDir()).thenReturn(outputDir);
menu.onExportCSV();
assertThat(listFiles(outputDir, null, false).size(), equalTo(1));
deleteDirectory(outputDir);
}
}

View File

@@ -0,0 +1,242 @@
/*
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Loop Habit Tracker is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.isoron.uhabits.core.utils;
import org.isoron.uhabits.core.*;
import org.isoron.uhabits.core.models.*;
import org.junit.*;
import java.util.*;
import static java.util.Calendar.*;
import static junit.framework.Assert.assertEquals;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.isoron.uhabits.core.utils.DateUtils.applyTimezone;
import static org.isoron.uhabits.core.utils.DateUtils.removeTimezone;
public class DateUtilsTest extends BaseUnitTest
{
@Before
@Override
public void setUp() throws Exception
{
super.setUp();
DateUtils.setFixedLocale(Locale.US);
}
@Test
public void testFormatHeaderDate()
{
long timestamp = unixTime(2015, DECEMBER, 31);
GregorianCalendar date = new Timestamp(timestamp).toCalendar();
String formatted = DateUtils.formatHeaderDate(date);
assertThat(formatted, equalTo("Thu\n31"));
}
@Test
public void testTruncate_dayOfWeek()
{
DateUtils.TruncateField field = DateUtils.TruncateField.WEEK_NUMBER;
long expected = unixTime(2015, Calendar.JANUARY, 11);
long t0 = unixTime(2015, Calendar.JANUARY, 11);
long t1 = unixTime(2015, Calendar.JANUARY, 16);
long t2 = unixTime(2015, Calendar.JANUARY, 17);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
expected = unixTime(2015, Calendar.JANUARY, 18);
t0 = unixTime(2015, Calendar.JANUARY, 18);
t1 = unixTime(2015, Calendar.JANUARY, 19);
t2 = unixTime(2015, Calendar.JANUARY, 24);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
}
@Test
public void testTruncate_month()
{
long expected = unixTime(2016, Calendar.JUNE, 1);
long t0 = unixTime(2016, Calendar.JUNE, 1);
long t1 = unixTime(2016, Calendar.JUNE, 15);
long t2 = unixTime(2016, Calendar.JUNE, 20);
DateUtils.TruncateField field = DateUtils.TruncateField.MONTH;
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
expected = unixTime(2016, DECEMBER, 1);
t0 = unixTime(2016, DECEMBER, 1);
t1 = unixTime(2016, DECEMBER, 15);
t2 = unixTime(2016, DECEMBER, 31);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
}
@Test
public void testTruncate_quarter()
{
DateUtils.TruncateField field = DateUtils.TruncateField.QUARTER;
long expected = unixTime(2016, JANUARY, 1);
long t0 = unixTime(2016, JANUARY, 20);
long t1 = unixTime(2016, FEBRUARY, 15);
long t2 = unixTime(2016, MARCH, 30);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
expected = unixTime(2016, APRIL, 1);
t0 = unixTime(2016, APRIL, 1);
t1 = unixTime(2016, MAY, 30);
t2 = unixTime(2016, JUNE, 20);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
}
@Test
public void testTruncate_year()
{
DateUtils.TruncateField field = DateUtils.TruncateField.YEAR;
long expected = unixTime(2016, JANUARY, 1);
long t0 = unixTime(2016, JANUARY, 1);
long t1 = unixTime(2016, FEBRUARY, 25);
long t2 = unixTime(2016, DECEMBER, 31);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
expected = unixTime(2017, JANUARY, 1);
t0 = unixTime(2017, JANUARY, 1);
t1 = unixTime(2017, MAY, 30);
t2 = unixTime(2017, DECEMBER, 31);
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
}
@Test
public void testMillisecondsUntilTomorrow() throws Exception
{
DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 2, 59));
assertThat(DateUtils.millisecondsUntilTomorrow(), equalTo(60000L));
DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 23, 0));
assertThat(DateUtils.millisecondsUntilTomorrow(), equalTo(14400000L));
}
@Test
public void test_applyTimezone()
{
DateUtils.setFixedTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
assertEquals(applyTimezone(unixTime(2017, JULY, 30, 18, 0)), (unixTime(2017, JULY, 30, 8, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 0, 0)), (unixTime(2017, SEPTEMBER, 29, 14, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 10, 0)), (unixTime(2017, SEPTEMBER, 30, 0, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 11, 0)), (unixTime(2017, SEPTEMBER, 30, 1, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 12, 0)), (unixTime(2017, SEPTEMBER, 30, 2, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 13, 0)), (unixTime(2017, SEPTEMBER, 30, 3, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 22, 0)), (unixTime(2017, SEPTEMBER, 30, 12, 0)));
assertEquals(applyTimezone(unixTime(2017, SEPTEMBER, 30, 23, 0)), (unixTime(2017, SEPTEMBER, 30, 13, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 0, 0)), (unixTime(2017, SEPTEMBER, 30, 14, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 1, 0)), (unixTime(2017, SEPTEMBER, 30, 15, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 1, 59)), (unixTime(2017, SEPTEMBER, 30, 15, 59)));
// DST begins
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 3, 0)), (unixTime(2017, SEPTEMBER, 30, 16, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 4, 0)), (unixTime(2017, SEPTEMBER, 30, 17, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 5, 0)), (unixTime(2017, SEPTEMBER, 30, 18, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 11, 0)), (unixTime(2017, OCTOBER, 1, 0, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 12, 0)), (unixTime(2017, OCTOBER, 1, 1, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 13, 0)), (unixTime(2017, OCTOBER, 1, 2, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 14, 0)), (unixTime(2017, OCTOBER, 1, 3, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 15, 0)), (unixTime(2017, OCTOBER, 1, 4, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 1, 19, 0)), (unixTime(2017, OCTOBER, 1, 8, 0)));
assertEquals(applyTimezone(unixTime(2017, OCTOBER, 2, 19, 0)), (unixTime(2017, OCTOBER, 2, 8, 0)));
assertEquals(applyTimezone(unixTime(2017, NOVEMBER, 30, 19, 0)), (unixTime(2017, NOVEMBER, 30, 8, 0)));
assertEquals(applyTimezone(unixTime(2018, MARCH, 31, 0, 0)), (unixTime(2018, MARCH, 30, 13, 0)));
assertEquals(applyTimezone(unixTime(2018, MARCH, 31, 12, 0)), (unixTime(2018, MARCH, 31, 1, 0)));
assertEquals(applyTimezone(unixTime(2018, MARCH, 31, 18, 0)), (unixTime(2018, MARCH, 31, 7, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 0, 0)), (unixTime(2018, MARCH, 31, 13, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 1, 0)), (unixTime(2018, MARCH, 31, 14, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 1, 59)), (unixTime(2018, MARCH, 31, 14, 59)));
// DST ends
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 2, 0)), (unixTime(2018, MARCH, 31, 16, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 3, 0)), (unixTime(2018, MARCH, 31, 17, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 4, 0)), (unixTime(2018, MARCH, 31, 18, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 10, 0)), (unixTime(2018, APRIL, 1, 0, 0)));
assertEquals(applyTimezone(unixTime(2018, APRIL, 1, 18, 0)), (unixTime(2018, APRIL, 1, 8, 0)));
}
@Test
public void test_removeTimezone()
{
DateUtils.setFixedTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
assertEquals(removeTimezone(unixTime(2017, JULY, 30, 8, 0)), (unixTime(2017, JULY, 30, 18, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 29, 14, 0)), (unixTime(2017, SEPTEMBER, 30, 0, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 0, 0)), (unixTime(2017, SEPTEMBER, 30, 10, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 1, 0)), (unixTime(2017, SEPTEMBER, 30, 11, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 2, 0)), (unixTime(2017, SEPTEMBER, 30, 12, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 3, 0)), (unixTime(2017, SEPTEMBER, 30, 13, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 12, 0)), (unixTime(2017, SEPTEMBER, 30, 22, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 13, 0)), (unixTime(2017, SEPTEMBER, 30, 23, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 14, 0)), (unixTime(2017, OCTOBER, 1, 0, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 15, 0)), (unixTime(2017, OCTOBER, 1, 1, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 15, 59)), (unixTime(2017, OCTOBER, 1, 1, 59)));
// DST begins
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 16, 0)), (unixTime(2017, OCTOBER, 1, 3, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 17, 0)), (unixTime(2017, OCTOBER, 1, 4, 0)));
assertEquals(removeTimezone(unixTime(2017, SEPTEMBER, 30, 18, 0)), (unixTime(2017, OCTOBER, 1, 5, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 1, 0, 0)), (unixTime(2017, OCTOBER, 1, 11, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 1, 1, 0)), (unixTime(2017, OCTOBER, 1, 12, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 1, 2, 0)), (unixTime(2017, OCTOBER, 1, 13, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 1, 3, 0)), (unixTime(2017, OCTOBER, 1, 14, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 1, 4, 0)), (unixTime(2017, OCTOBER, 1, 15, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 1, 8, 0)), (unixTime(2017, OCTOBER, 1, 19, 0)));
assertEquals(removeTimezone(unixTime(2017, OCTOBER, 2, 8, 0)), (unixTime(2017, OCTOBER, 2, 19, 0)));
assertEquals(removeTimezone(unixTime(2017, NOVEMBER, 30, 8, 0)), (unixTime(2017, NOVEMBER, 30, 19, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 30, 13, 0)), (unixTime(2018, MARCH, 31, 0, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 1, 0)), (unixTime(2018, MARCH, 31, 12, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 7, 0)), (unixTime(2018, MARCH, 31, 18, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 13, 0)), (unixTime(2018, APRIL, 1, 0, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 14, 0)), (unixTime(2018, APRIL, 1, 1, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 14, 59)), (unixTime(2018, APRIL, 1, 1, 59)));
// DST ends
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 16, 0)), (unixTime(2018, APRIL, 1, 2, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 17, 0)), (unixTime(2018, APRIL, 1, 3, 0)));
assertEquals(removeTimezone(unixTime(2018, MARCH, 31, 18, 0)), (unixTime(2018, APRIL, 1, 4, 0)));
assertEquals(removeTimezone(unixTime(2018, APRIL, 1, 0, 0)), (unixTime(2018, APRIL, 1, 10, 0)));
assertEquals(removeTimezone(unixTime(2018, APRIL, 1, 8, 0)), (unixTime(2018, APRIL, 1, 18, 0)));
}
}

View File

@@ -0,0 +1,19 @@
HabitName,HabitDescription,HabitCategory,CalendarDate,Value,CommentText
Breed dragons,with love and fire,Diet & Food,2016-03-18,1,
Breed dragons,with love and fire,Diet & Food,2016-03-19,1,
Breed dragons,with love and fire,Diet & Food,2016-03-21,1,
Reduce sleep,only 2 hours per day,Time Management,2016-03-15,1,
Reduce sleep,only 2 hours per day,Time Management,2016-03-16,1,
Reduce sleep,only 2 hours per day,Time Management,2016-03-17,1,
Reduce sleep,only 2 hours per day,Time Management,2016-03-21,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-15,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-16,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-18,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-21,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-15,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-16,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-18,1,
No-arms pushup,Become like water my friend!,Fitness,2016-03-21,1,
Grow spiritually,"transcend ego, practice compassion, smile and breath",Meditation,2016-03-15,1,
Grow spiritually,"transcend ego, practice compassion, smile and breath",Meditation,2016-03-17,1,
Grow spiritually,"transcend ego, practice compassion, smile and breath",Meditation,2016-03-21,1,
1 HabitName HabitDescription HabitCategory CalendarDate Value CommentText
2 Breed dragons with love and fire Diet & Food 2016-03-18 1
3 Breed dragons with love and fire Diet & Food 2016-03-19 1
4 Breed dragons with love and fire Diet & Food 2016-03-21 1
5 Reduce sleep only 2 hours per day Time Management 2016-03-15 1
6 Reduce sleep only 2 hours per day Time Management 2016-03-16 1
7 Reduce sleep only 2 hours per day Time Management 2016-03-17 1
8 Reduce sleep only 2 hours per day Time Management 2016-03-21 1
9 No-arms pushup Become like water my friend! Fitness 2016-03-15 1
10 No-arms pushup Become like water my friend! Fitness 2016-03-16 1
11 No-arms pushup Become like water my friend! Fitness 2016-03-18 1
12 No-arms pushup Become like water my friend! Fitness 2016-03-21 1
13 No-arms pushup Become like water my friend! Fitness 2016-03-15 1
14 No-arms pushup Become like water my friend! Fitness 2016-03-16 1
15 No-arms pushup Become like water my friend! Fitness 2016-03-18 1
16 No-arms pushup Become like water my friend! Fitness 2016-03-21 1
17 Grow spiritually transcend ego, practice compassion, smile and breath Meditation 2016-03-15 1
18 Grow spiritually transcend ego, practice compassion, smile and breath Meditation 2016-03-17 1
19 Grow spiritually transcend ego, practice compassion, smile and breath Meditation 2016-03-21 1

Binary file not shown.

Binary file not shown.

Binary file not shown.