/**
* Copyright (c) 2012 Todoroo Inc
*
* See the file "LICENSE" for the full license governing this code.
*/
package com.todoroo.astrid.repeats;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
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.test.TodorooTestCase;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Task;
public class RepeatAfterCompleteTests extends TodorooTestCase {
private Task task;
private long nextDueDate;
private RRule rrule;
@Override
protected void setUp() throws Exception {
super.setUp();
task = new Task();
task.setValue(Task.COMPLETION_DATE, DateUtilities.now());
rrule = new RRule();
}
// --- date with time tests
public void testSubDailyFreqs() throws ParseException {
task.setValue(Task.DUE_DATE, DateUtilities.now() - DateUtilities.ONE_WEEK);
for(Frequency freq : Frequency.values()) {
long interval = -1;
switch(freq) {
case MINUTELY:
interval = DateUtilities.ONE_MINUTE; break;
case HOURLY:
interval = DateUtilities.ONE_HOUR; break;
default:
continue;
}
buildRRule(1, freq);
nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal(), true);
buildRRule(6, freq);
nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal(), true);
assertDateTimeEquals(freq.toString() + "x6", DateUtilities.now() + 6 * interval, nextDueDate);
task.setValue(Task.DUE_DATE, nextDueDate);
assertTrue(task.hasDueTime());
}
}
public void testDailyAndGreaterFreqs() throws ParseException {
task.setValue(Task.DUE_DATE,
Task.createDueDate(Task.URGENCY_SPECIFIC_DAY,
DateUtilities.now() - DateUtilities.ONE_WEEK));
for(int interval = 1; interval < 7; interval++) {
for(Frequency freq : Frequency.values()) {
long next = DateUtilities.now();
switch(freq) {
case DAILY:
next += interval * DateUtilities.ONE_DAY; break;
case WEEKLY:
next += interval * DateUtilities.ONE_WEEK; break;
case MONTHLY:
next = DateUtilities.addCalendarMonthsToUnixtime(next, interval); break;
case YEARLY:
next = DateUtilities.addCalendarMonthsToUnixtime(next, interval * 12); break;
default:
continue;
}
buildRRule(interval, freq);
nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal(), true);
assertDateEquals(freq.toString() + "x" + interval, next, nextDueDate);
task.setValue(Task.DUE_DATE, nextDueDate);
assertFalse(task.hasDueTime());
}
}
}
public void testTimeZoneLate() throws ParseException {
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
task.setValue(Task.DUE_DATE, DateUtilities.now() + DateUtilities.ONE_WEEK);
nextDueDate = RepeatTaskCompleteListener.computeNextDueDate(task, rrule.toIcal(), true);
long expected = Task.createDueDate(Task.URGENCY_TOMORROW, 0);
assertDateEquals("tomorrow", expected, nextDueDate);
}
// --- helpers
private void buildRRule(int interval, Frequency freq, Weekday... weekdays) {
rrule.setInterval(interval);
rrule.setFreq(freq);
setRRuleDays(rrule, weekdays);
}
public static void assertDateTimeEquals(String message, long expected, long actual) {
expected = expected / 60000L * 60000;
actual = actual / 60000L * 60000;
assertEquals(message + ": Expected: " + new Date(expected) + ", Actual: " + new Date(actual),
expected, actual);
}
private void assertDateEquals(String message, long expected, long actual) {
expected = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, expected);
actual = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, actual);
assertEquals(message + ": Due Date is '" + DateUtilities.getDateStringWithWeekday(getContext(), new Date(actual))
+ "', expected '" + DateUtilities.getDateStringWithWeekday(getContext(), new Date(expected)) + "'",
expected, actual);
}
private void setRRuleDays(RRule rrule, Weekday... weekdays) {
ArrayList<WeekdayNum> days = new ArrayList<WeekdayNum>();
for(Weekday wd : weekdays)
days.add(new WeekdayNum(0, wd));
rrule.setByDay(days);
}
}