|
|
|
@ -1,255 +1,25 @@
|
|
|
|
|
/**
|
|
|
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
|
|
|
*
|
|
|
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
|
|
|
*/
|
|
|
|
|
package com.todoroo.astrid.repeats;
|
|
|
|
|
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.support.test.runner.AndroidJUnit4;
|
|
|
|
|
|
|
|
|
|
import com.google.ical.values.Frequency;
|
|
|
|
|
import com.google.ical.values.RRule;
|
|
|
|
|
import com.google.ical.values.Weekday;
|
|
|
|
|
import com.google.ical.values.WeekdayNum;
|
|
|
|
|
import com.todoroo.andlib.sql.Query;
|
|
|
|
|
import com.todoroo.andlib.utility.AndroidUtilities;
|
|
|
|
|
import com.todoroo.andlib.utility.DateUtilities;
|
|
|
|
|
import com.todoroo.astrid.api.AstridApiConstants;
|
|
|
|
|
import com.todoroo.astrid.dao.TaskDao;
|
|
|
|
|
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
|
|
|
|
|
import com.todoroo.astrid.data.SyncFlags;
|
|
|
|
|
import com.todoroo.astrid.data.Task;
|
|
|
|
|
import com.todoroo.astrid.test.DatabaseTestCase;
|
|
|
|
|
|
|
|
|
|
import org.junit.Ignore;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
import org.junit.runner.RunWith;
|
|
|
|
|
import org.tasks.R;
|
|
|
|
|
import org.tasks.injection.TestComponent;
|
|
|
|
|
import org.tasks.preferences.Preferences;
|
|
|
|
|
import org.tasks.time.DateTime;
|
|
|
|
|
|
|
|
|
|
import java.text.ParseException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
import javax.inject.Inject;
|
|
|
|
|
|
|
|
|
|
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
|
|
|
|
import static com.todoroo.astrid.repeats.RepeatTaskCompleteListener.computeNextDueDate;
|
|
|
|
|
import static java.util.Arrays.asList;
|
|
|
|
|
import static junit.framework.Assert.assertEquals;
|
|
|
|
|
import static junit.framework.Assert.assertFalse;
|
|
|
|
|
import static junit.framework.Assert.assertTrue;
|
|
|
|
|
import static org.tasks.date.DateTimeUtils.newDateTime;
|
|
|
|
|
|
|
|
|
|
@RunWith(AndroidJUnit4.class)
|
|
|
|
|
public class NewRepeatTests extends DatabaseTestCase {
|
|
|
|
|
|
|
|
|
|
@Inject TaskDao taskDao;
|
|
|
|
|
@Inject Preferences preferences;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void setUp() {
|
|
|
|
|
super.setUp();
|
|
|
|
|
preferences.setStringFromInteger(R.string.p_default_urgency_key, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void inject(TestComponent component) {
|
|
|
|
|
component.inject(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void saveAndTriggerRepeatListener(Task task) {
|
|
|
|
|
task.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true);
|
|
|
|
|
if(task.isSaved())
|
|
|
|
|
taskDao.saveExisting(task);
|
|
|
|
|
else
|
|
|
|
|
taskDao.createNew(task);
|
|
|
|
|
|
|
|
|
|
Intent intent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_COMPLETED);
|
|
|
|
|
intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId());
|
|
|
|
|
new RepeatTaskCompleteListener().onReceive(getTargetContext(), intent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void waitAndSync() {
|
|
|
|
|
// Subclasses can override this to insert sync functionality
|
|
|
|
|
AndroidUtilities.sleepDeep(200L); // Delay to make sure changes persist
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void assertTimesMatch(long expectedTime, long newDueDate) {
|
|
|
|
|
assertTrue(String.format("Expected %s, was %s", newDateTime(expectedTime), newDateTime(newDueDate)),
|
|
|
|
|
Math.abs(expectedTime - newDueDate) < 5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void assertTimesWithinOneHour(long expectedTime, long newDueDate) {
|
|
|
|
|
assertTrue(String.format("Expected %s, was %s", newDateTime(expectedTime), newDateTime(newDueDate)),
|
|
|
|
|
Math.abs(expectedTime - newDueDate) <= DateUtilities.ONE_HOUR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Tests for no sync
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testNoRepeat() {
|
|
|
|
|
Task t = new Task();
|
|
|
|
|
t.setTitle("no repeat");
|
|
|
|
|
taskDao.save(t);
|
|
|
|
|
|
|
|
|
|
t.setCompletionDate(DateUtilities.now());
|
|
|
|
|
saveAndTriggerRepeatListener(t);
|
|
|
|
|
|
|
|
|
|
assertEquals(1, taskDao.toList(Query.select(Task.ID)).size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void testRepeating(boolean completeBefore, boolean fromCompletion,
|
|
|
|
|
RRule rrule, Frequency frequency, String title) {
|
|
|
|
|
Task t = new Task();
|
|
|
|
|
t.setTitle(title);
|
|
|
|
|
long dueDate = DateUtilities.now() + DateUtilities.ONE_DAY * 3;
|
|
|
|
|
DateTime adjustDate = newDateTime(dueDate).withSecondOfMinute(1);
|
|
|
|
|
dueDate = adjustDate.getMillis();
|
|
|
|
|
dueDate = (dueDate / 1000L) * 1000L; // Strip milliseconds
|
|
|
|
|
|
|
|
|
|
t.setDueDate(dueDate);
|
|
|
|
|
|
|
|
|
|
if (rrule == null) {
|
|
|
|
|
rrule = new RRule();
|
|
|
|
|
rrule.setFreq(frequency);
|
|
|
|
|
int interval = 2;
|
|
|
|
|
rrule.setInterval(interval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String result = rrule.toIcal();
|
|
|
|
|
if (fromCompletion)
|
|
|
|
|
result = result + ";FROM=COMPLETION";
|
|
|
|
|
t.setRecurrence(result);
|
|
|
|
|
taskDao.save(t);
|
|
|
|
|
|
|
|
|
|
waitAndSync();
|
|
|
|
|
t = taskDao.fetch(t.getId(), Task.PROPERTIES); // Refetch
|
|
|
|
|
|
|
|
|
|
long completionDate;
|
|
|
|
|
if (completeBefore)
|
|
|
|
|
completionDate = dueDate - DateUtilities.ONE_DAY;
|
|
|
|
|
else
|
|
|
|
|
completionDate = dueDate + DateUtilities.ONE_DAY;
|
|
|
|
|
t.setCompletionDate(completionDate);
|
|
|
|
|
saveAndTriggerRepeatListener(t);
|
|
|
|
|
System.err.println("Completion date: " + newDateTime(completionDate));
|
|
|
|
|
|
|
|
|
|
waitAndSync();
|
|
|
|
|
|
|
|
|
|
List<Task> tasks = taskDao.toList(Query.select(Task.PROPERTIES).where(TaskCriteria.notDeleted()));
|
|
|
|
|
assertEquals(1, tasks.size());
|
|
|
|
|
t = tasks.get(0);
|
|
|
|
|
assertEquals(title, t.getTitle());
|
|
|
|
|
assertFalse(t.isCompleted());
|
|
|
|
|
long newDueDate = t.getDueDate();
|
|
|
|
|
assertTrue(t.hasDueTime());
|
|
|
|
|
|
|
|
|
|
long fromDate = (fromCompletion? completionDate : dueDate);
|
|
|
|
|
long expectedTime = computeNextDueDateFromDate(fromDate, rrule, fromCompletion);
|
|
|
|
|
|
|
|
|
|
if (frequency == Frequency.WEEKLY) // We do this because DST was making the results be off by an hour
|
|
|
|
|
assertTimesWithinOneHour(expectedTime, newDueDate);
|
|
|
|
|
else
|
|
|
|
|
assertTimesMatch(expectedTime, newDueDate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private long computeWeeklyCaseDueDate(long fromDate, RRule rrule, boolean fromCompletion) {
|
|
|
|
|
long result = fromDate;
|
|
|
|
|
Frequency frequency = rrule.getFreq();
|
|
|
|
|
assertTrue(frequency.equals(Frequency.WEEKLY));
|
|
|
|
|
List<WeekdayNum> weekdayNums = rrule.getByDay();
|
|
|
|
|
|
|
|
|
|
if (weekdayNums.size() == 0) {
|
|
|
|
|
result += DateUtilities.ONE_WEEK * rrule.getInterval();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
HashSet<Weekday> weekdays = new HashSet<>();
|
|
|
|
|
for (WeekdayNum curr : weekdayNums) {
|
|
|
|
|
weekdays.add(curr.wday);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Weekday[] allWeekdays = Weekday.values();
|
|
|
|
|
DateTime date = newDateTime(result);
|
|
|
|
|
Weekday start = allWeekdays[date.getDayOfWeek()];
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < allWeekdays.length; i++) {
|
|
|
|
|
if (start == allWeekdays[i]) break;
|
|
|
|
|
}
|
|
|
|
|
int index = i;
|
|
|
|
|
int daysToAdd = 0;
|
|
|
|
|
Weekday next = null;
|
|
|
|
|
for (i = index + 1; i < allWeekdays.length; i++) {
|
|
|
|
|
Weekday curr = allWeekdays[i];
|
|
|
|
|
daysToAdd++;
|
|
|
|
|
if (weekdays.contains(curr)) {
|
|
|
|
|
next = curr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (next == null) {
|
|
|
|
|
for (i = 0; i < index + 1; i++) {
|
|
|
|
|
Weekday curr = allWeekdays[i];
|
|
|
|
|
daysToAdd++;
|
|
|
|
|
if (weekdays.contains(curr)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fromCompletion) {
|
|
|
|
|
result += DateUtilities.ONE_WEEK * (rrule.getInterval() - 1);
|
|
|
|
|
}
|
|
|
|
|
result += DateUtilities.ONE_DAY * daysToAdd;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Advanced weekly repeating tests */
|
|
|
|
|
private long computeNextDueDateFromDate(long fromDate, RRule rrule, boolean fromCompletion) {
|
|
|
|
|
long expectedTime = fromDate;
|
|
|
|
|
Frequency frequency = rrule.getFreq();
|
|
|
|
|
int interval = rrule.getInterval();
|
|
|
|
|
if (frequency.equals(Frequency.MINUTELY)) {
|
|
|
|
|
expectedTime += DateUtilities.ONE_MINUTE * interval;
|
|
|
|
|
} else if (frequency.equals(Frequency.HOURLY)) {
|
|
|
|
|
expectedTime += DateUtilities.ONE_HOUR * interval;
|
|
|
|
|
} else if (frequency.equals(Frequency.DAILY)) {
|
|
|
|
|
expectedTime += DateUtilities.ONE_DAY * interval;
|
|
|
|
|
} else if (frequency.equals(Frequency.WEEKLY)) {
|
|
|
|
|
expectedTime = computeWeeklyCaseDueDate(fromDate, rrule, fromCompletion);
|
|
|
|
|
} else if (frequency.equals(Frequency.MONTHLY)) {
|
|
|
|
|
DateTime originalDate = newDateTime(expectedTime);
|
|
|
|
|
for (int i = 0; i < interval; i++) {
|
|
|
|
|
int month = originalDate.getMonthOfYear();
|
|
|
|
|
if (month == 11) { // Roll over the year and set the month to January
|
|
|
|
|
originalDate = originalDate
|
|
|
|
|
.withYear(originalDate.getYear() + 1)
|
|
|
|
|
.withMonthOfYear(1);
|
|
|
|
|
} else {
|
|
|
|
|
originalDate = originalDate.withMonthOfYear(originalDate.getMonthOfYear() + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
expectedTime = originalDate.getMillis();
|
|
|
|
|
} else if (frequency.equals(Frequency.YEARLY)) {
|
|
|
|
|
DateTime originalCompleteDate = newDateTime(expectedTime);
|
|
|
|
|
originalCompleteDate = originalCompleteDate.withYear(originalCompleteDate.getYear() + interval);
|
|
|
|
|
expectedTime = originalCompleteDate.getMillis();
|
|
|
|
|
}
|
|
|
|
|
return expectedTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void testFromCompletionDate(boolean completeBefore, Frequency frequency, String title) {
|
|
|
|
|
testRepeating(completeBefore, true, null, frequency, title);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Tests for repeating from due date */
|
|
|
|
|
public class NewRepeatTests {
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMinutelyFromDueDate() throws ParseException {
|
|
|
|
@ -301,129 +71,138 @@ public class NewRepeatTests extends DatabaseTestCase {
|
|
|
|
|
|
|
|
|
|
/** Tests for repeating from completionDate */
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMinutelyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testFromCompletionDate(true, Frequency.MINUTELY, "minutely-before");
|
|
|
|
|
}
|
|
|
|
|
public void testRepeatMinutelyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 30, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.MINUTELY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMinutelyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testFromCompletionDate(false, Frequency.MINUTELY, "minutely-after");
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 29, 0, 15), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatHourlyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testFromCompletionDate(true, Frequency.HOURLY, "hourly-before");
|
|
|
|
|
}
|
|
|
|
|
public void testRepeatMinutelyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 28, 0, 4);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.MINUTELY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatHourlyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testFromCompletionDate(false, Frequency.HOURLY, "hourly-after");
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 29, 0, 15), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatDailyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testFromCompletionDate(true, Frequency.DAILY, "daily-before");
|
|
|
|
|
}
|
|
|
|
|
public void testRepeatHourlyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 30, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.HOURLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatDailyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testFromCompletionDate(false, Frequency.DAILY, "daily-after");
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 29, 1, 14), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatWeeklyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testFromCompletionDate(true, Frequency.WEEKLY, "weekly-before");
|
|
|
|
|
}
|
|
|
|
|
public void testRepeatHourlyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 28, 0, 4);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.HOURLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatWeeklyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testFromCompletionDate(false, Frequency.WEEKLY, "weekly-after");
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 29, 1, 14), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMonthlyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testFromCompletionDate(true, Frequency.MONTHLY, "monthly-before");
|
|
|
|
|
public void testRepeatDailyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 30, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.DAILY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 30, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMonthlyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testFromCompletionDate(false, Frequency.MONTHLY, "monthly-after");
|
|
|
|
|
public void testRepeatDailyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 28, 0, 4);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.DAILY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 30, 0, 4), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatYearlyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testFromCompletionDate(true, Frequency.YEARLY, "yearly-before");
|
|
|
|
|
public void testRepeatWeeklyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 30, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.WEEKLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 9, 5, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatYearlyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testFromCompletionDate(false, Frequency.YEARLY, "yearly-after");
|
|
|
|
|
public void testRepeatWeeklyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 28, 0, 4);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.WEEKLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 9, 5, 0, 4), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void testAdvancedWeeklyFromDueDate(boolean completeBefore, String title) {
|
|
|
|
|
RRule rrule = new RRule();
|
|
|
|
|
rrule.setFreq(Frequency.WEEKLY);
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMonthlyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 30, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.MONTHLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
int interval = 1;
|
|
|
|
|
rrule.setInterval(interval);
|
|
|
|
|
List<WeekdayNum> weekdays = new ArrayList<>();
|
|
|
|
|
weekdays.add(new WeekdayNum(0, Weekday.MO));
|
|
|
|
|
weekdays.add(new WeekdayNum(0, Weekday.WE));
|
|
|
|
|
rrule.setByDay(weekdays);
|
|
|
|
|
testRepeating(completeBefore, false, rrule, Frequency.WEEKLY, title);
|
|
|
|
|
assertEquals(newDayTime(2016, 9, 29, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void testAdvancedWeeklyFromCompleteDate(boolean completeBefore, String title) {
|
|
|
|
|
RRule rrule = new RRule();
|
|
|
|
|
rrule.setFreq(Frequency.WEEKLY);
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatMonthlyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 28, 0, 4);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.MONTHLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
int interval = 1;
|
|
|
|
|
rrule.setInterval(interval);
|
|
|
|
|
List<WeekdayNum> weekdays = new ArrayList<>();
|
|
|
|
|
weekdays.add(new WeekdayNum(0, Weekday.MO));
|
|
|
|
|
weekdays.add(new WeekdayNum(0, Weekday.WE));
|
|
|
|
|
rrule.setByDay(weekdays);
|
|
|
|
|
testRepeating(completeBefore, true, rrule, Frequency.WEEKLY, title);
|
|
|
|
|
assertEquals(newDayTime(2016, 9, 29, 0, 4), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testRepeatYearlyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 30, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.YEARLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2017, 8, 29, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// disabled until test can be fixed
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromDueDateCompleteBefore() {
|
|
|
|
|
testAdvancedWeeklyFromDueDate(true, "advanced-weekly-before");
|
|
|
|
|
public void testRepeatYearlyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 28, 0, 4);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 29, 0, 14);
|
|
|
|
|
Task task = newFromCompleted(Frequency.YEARLY, 1, dueDateTime, completionDateTime);
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2017, 8, 29, 0, 4), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromDueDateCompleteAfter() {
|
|
|
|
|
testAdvancedWeeklyFromDueDate(false, "advanced-weekly-after");
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromDueDate() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 29, 0, 25);
|
|
|
|
|
Task task = newWeeklyFromDue(1, dueDateTime, new WeekdayNum(0, Weekday.MO), new WeekdayNum(0, Weekday.WE));
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 31, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromCompleteDateCompleteBefore() {
|
|
|
|
|
testAdvancedWeeklyFromCompleteDate(true, "advanced-weekly-before");
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromCompleteDateCompleteBefore() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 29, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 8, 28, 1, 9);
|
|
|
|
|
Task task = newWeeklyFromCompleted(1, dueDateTime, completionDateTime, new WeekdayNum(0, Weekday.MO), new WeekdayNum(0, Weekday.WE));
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 8, 29, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Ignore
|
|
|
|
|
@Test
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromCompleteDateCompleteAfter() {
|
|
|
|
|
testAdvancedWeeklyFromCompleteDate(false, "advanced-weekly-after");
|
|
|
|
|
public void testAdvancedRepeatWeeklyFromCompleteDateCompleteAfter() throws ParseException {
|
|
|
|
|
DateTime dueDateTime = newDayTime(2016, 8, 29, 0, 25);
|
|
|
|
|
DateTime completionDateTime = newDayTime(2016, 9, 1, 1, 9);
|
|
|
|
|
Task task = newWeeklyFromCompleted(1, dueDateTime, completionDateTime, new WeekdayNum(0, Weekday.MO), new WeekdayNum(0, Weekday.WE));
|
|
|
|
|
|
|
|
|
|
assertEquals(newDayTime(2016, 9, 5, 0, 25), calculateNextDueDate(task));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DateTime newDayTime(int year, int month, int day, int hour, int minute) {
|
|
|
|
@ -441,10 +220,36 @@ public class NewRepeatTests extends DatabaseTestCase {
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getRecurrenceRule(Frequency frequency, int interval, boolean fromCompletion) {
|
|
|
|
|
private Task newWeeklyFromDue(int interval, DateTime dueDate, WeekdayNum... weekdays) {
|
|
|
|
|
return new Task() {{
|
|
|
|
|
setRecurrence(getRecurrenceRule(Frequency.WEEKLY, interval, false, weekdays));
|
|
|
|
|
setDueDate(dueDate.getMillis());
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Task newFromCompleted(Frequency frequency, int interval, DateTime dueDate, DateTime completionDate) {
|
|
|
|
|
return new Task() {{
|
|
|
|
|
setRecurrence(getRecurrenceRule(frequency, interval, true));
|
|
|
|
|
setDueDate(dueDate.getMillis());
|
|
|
|
|
setCompletionDate(completionDate.getMillis());
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Task newWeeklyFromCompleted(int interval, DateTime dueDate, DateTime completionDate, WeekdayNum... weekdays) {
|
|
|
|
|
return new Task() {{
|
|
|
|
|
setRecurrence(getRecurrenceRule(Frequency.WEEKLY, interval, true, weekdays));
|
|
|
|
|
setDueDate(dueDate.getMillis());
|
|
|
|
|
setCompletionDate(completionDate.getMillis());
|
|
|
|
|
}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getRecurrenceRule(Frequency frequency, int interval, boolean fromCompletion, WeekdayNum... weekdays) {
|
|
|
|
|
RRule rrule = new RRule();
|
|
|
|
|
rrule.setFreq(frequency);
|
|
|
|
|
rrule.setInterval(interval);
|
|
|
|
|
if (weekdays != null) {
|
|
|
|
|
rrule.setByDay(asList(weekdays));
|
|
|
|
|
}
|
|
|
|
|
String result = rrule.toIcal();
|
|
|
|
|
if (fromCompletion) {
|
|
|
|
|
result += ";FROM=COMPLETION";
|
|
|
|
|