diff --git a/app/src/commonTest/java/org/tasks/Freeze.kt b/app/src/commonTest/java/org/tasks/Freeze.kt index 53662a65a..e20801de9 100644 --- a/app/src/commonTest/java/org/tasks/Freeze.kt +++ b/app/src/commonTest/java/org/tasks/Freeze.kt @@ -4,9 +4,9 @@ import org.tasks.time.DateTime import org.tasks.time.DateTimeUtils class Freeze { - fun thawAfter(run: () -> Unit) { + fun thawAfter(run: () -> T): T { try { - run() + return run() } finally { thaw() } @@ -14,16 +14,16 @@ class Freeze { companion object { - fun freezeClock(run: () -> Unit) { - freezeAt(DateTimeUtils.currentTimeMillis()).thawAfter(run) + fun freezeClock(run: () -> Unit): Any { + return freezeAt(DateTimeUtils.currentTimeMillis()).thawAfter(run) } - fun freezeAt(dateTime: DateTime, run: () -> Unit) { - freezeAt(dateTime.millis, run) + fun freezeAt(dateTime: DateTime, run: () -> T): T { + return freezeAt(dateTime.millis, run) } - fun freezeAt(timestamp: Long, run: () -> Unit) { - freezeAt(timestamp).thawAfter(run) + fun freezeAt(timestamp: Long, run: () -> T): T { + return freezeAt(timestamp).thawAfter(run) } fun freezeAt(dateTime: DateTime): Freeze { diff --git a/app/src/test/java/com/todoroo/astrid/repeats/AdvancedRepeatTest.kt b/app/src/test/java/com/todoroo/astrid/repeats/AdvancedRepeatTest.kt deleted file mode 100644 index 7c57020fe..000000000 --- a/app/src/test/java/com/todoroo/astrid/repeats/AdvancedRepeatTest.kt +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2012 Todoroo Inc - * - * See the file "LICENSE" for the full license governing this code. - */ -package com.todoroo.astrid.repeats - -import com.todoroo.andlib.utility.DateUtilities -import com.todoroo.astrid.data.Task -import net.fortuna.ical4j.model.Recur -import net.fortuna.ical4j.model.Recur.Frequency -import net.fortuna.ical4j.model.WeekDay -import net.fortuna.ical4j.model.WeekDay.* -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.tasks.date.DateTimeUtils -import org.tasks.repeats.RecurrenceUtils.newRecur -import org.tasks.time.DateTime -import org.tasks.time.DateTimeUtils.printTimestamp -import java.text.ParseException -import java.util.* -import kotlin.math.abs -import kotlin.math.min - -class AdvancedRepeatTest { - private var task: Task? = null - private var nextDueDate: Long = 0 - private var recur: Recur? = null - - // --- date with time tests - @Before - fun setUp() { - task = Task() - task!!.completionDate = DateUtilities.now() - recur = newRecur() - } - - @Test - @Throws(ParseException::class) - fun testDueDateSpecificTime() { - buildRecur(1, Frequency.DAILY) - - // test specific day & time - val dayWithTime = Task.createDueDate( - Task.URGENCY_SPECIFIC_DAY_TIME, DateTime(2010, 8, 1, 10, 4, 0).millis) - task!!.dueDate = dayWithTime - val nextDayWithTime = dayWithTime + DateUtilities.ONE_DAY - nextDueDate = RepeatTaskHelper.computeNextDueDate(task!!, recur!!.toString(), false) - assertDateTimeEquals(nextDayWithTime, nextDueDate) - } - - // --- due date tests - @Test - @Throws(ParseException::class) - fun testCompletionDateSpecificTime() { - buildRecur(1, Frequency.DAILY) - - // test specific day & time - val dayWithTime = Task.createDueDate( - Task.URGENCY_SPECIFIC_DAY_TIME, DateTime(2010, 8, 1, 10, 4, 0).millis) - task!!.dueDate = dayWithTime - val todayWithTime = DateTimeUtils.newDateTime().withHourOfDay(10).withMinuteOfHour(4).withSecondOfMinute(1) - var nextDayWithTimeLong = todayWithTime.millis - nextDayWithTimeLong += DateUtilities.ONE_DAY - nextDayWithTimeLong = nextDayWithTimeLong / 1000L * 1000 - nextDueDate = RepeatTaskHelper.computeNextDueDate(task!!, recur!!.toString(), true) - assertDateTimeEquals(nextDayWithTimeLong, nextDueDate) - } - - /** test multiple days per week - DUE DATE */ - @Test - @Throws(Exception::class) - fun testDueDateInPastSingleWeekMultiDay() { - buildRecur(1, Frequency.WEEKLY, MO, WE, FR) - setTaskDueDate(THIS, Calendar.SUNDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - setTaskDueDate(THIS, Calendar.MONDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.WEDNESDAY) - setTaskDueDate(THIS, Calendar.FRIDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - } - - /** test single day repeats - DUE DATE */ - @Test - @Throws(Exception::class) - fun testDueDateSingleDay() { - buildRecur(1, Frequency.WEEKLY, MO) - setTaskDueDate(PREV_PREV, Calendar.MONDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, NEXT, Calendar.MONDAY) - setTaskDueDate(PREV_PREV, Calendar.FRIDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - setTaskDueDate(PREV, Calendar.MONDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, NEXT, Calendar.MONDAY) - setTaskDueDate(PREV, Calendar.FRIDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - setTaskDueDate(THIS, Calendar.SUNDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - setTaskDueDate(THIS, Calendar.MONDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, NEXT, Calendar.MONDAY) - } - - /** test multiple days per week - DUE DATE */ - @Test - @Throws(Exception::class) - fun testDueDateSingleWeekMultiDay() { - buildRecur(1, Frequency.WEEKLY, MO, WE, FR) - setTaskDueDate(THIS, Calendar.SUNDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - setTaskDueDate(THIS, Calendar.MONDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.WEDNESDAY) - setTaskDueDate(THIS, Calendar.FRIDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.MONDAY) - } - // --- completion tests - /** test multiple days per week, multiple intervals - DUE DATE */ - @Test - @Throws(Exception::class) - fun testDueDateMultiWeekMultiDay() { - buildRecur(2, Frequency.WEEKLY, MO, WE, FR) - setTaskDueDate(THIS, Calendar.SUNDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, NEXT, Calendar.MONDAY) - setTaskDueDate(THIS, Calendar.MONDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, THIS, Calendar.WEDNESDAY) - setTaskDueDate(THIS, Calendar.FRIDAY) - computeNextDueDate(false) - assertDueDate(nextDueDate, NEXT, Calendar.MONDAY) - } - - /** test multiple days per week - COMPLETE DATE */ - @Test - @Throws(Exception::class) - fun testCompleteDateSingleWeek() { - for (wday in weekdays) { - buildRecur(1, Frequency.WEEKLY, wday) - computeNextDueDate(true) - val expected = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, THIS, getCalendarDay(wday)) - nextDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, nextDueDate) - assertEquals(expected, nextDueDate) - } - for (wday1 in weekdays) { - for (wday2 in weekdays) { - if (wday1 == wday2) { - continue - } - buildRecur(1, Frequency.WEEKLY, wday1, wday2) - val nextOne = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, THIS, getCalendarDay(wday1)) - val nextTwo = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, THIS, getCalendarDay(wday2)) - computeNextDueDate(true) - nextDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, nextDueDate) - assertEquals(min(nextOne, nextTwo), nextDueDate) - } - } - } - // --- helpers - /** test multiple days per week, multiple intervals - COMPLETE DATE */ - @Test - @Throws(Exception::class) - fun testCompleteDateMultiWeek() { - for (wday in weekdays) { - buildRecur(2, Frequency.WEEKLY, wday) - computeNextDueDate(true) - val expected = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, NEXT, getCalendarDay(wday)) - nextDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, nextDueDate) - assertEquals(expected, nextDueDate) - } - for (wday1 in weekdays) { - for (wday2 in weekdays) { - if (wday1 == wday2) { - continue - } - buildRecur(2, Frequency.WEEKLY, wday1, wday2) - val nextOne = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, NEXT, getCalendarDay(wday1)) - val nextTwo = getDate(DateUtilities.now() + DateUtilities.ONE_DAY, NEXT, getCalendarDay(wday2)) - computeNextDueDate(true) - nextDueDate = Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, nextDueDate) - assertEquals(min(nextOne, nextTwo), nextDueDate) - } - } - } - - @Throws(ParseException::class) - private fun computeNextDueDate(fromComplete: Boolean) { - nextDueDate = RepeatTaskHelper.computeNextDueDate(task!!, recur!!.toString(), fromComplete) - } - - private fun buildRecur(interval: Int, freq: Frequency, vararg weekdays: WeekDay) { - recur!!.interval = interval - recur!!.setFrequency(freq.name) - recur!!.dayList.clear() - recur!!.dayList.addAll(weekdays) - } - - private fun assertDueDate(actual: Long, expectedWhich: Int, expectedDayOfWeek: Int) { - val expected = getDate(task!!.dueDate, expectedWhich, expectedDayOfWeek) - assertEquals(expected, actual) - } - - private fun setTaskDueDate(which: Int, day: Int) { - val time = getDate(DateUtilities.now(), which, day) - task!!.dueDate = time - } - - private fun getDate(start: Long, which: Int, dayOfWeek: Int): Long { - val c = Calendar.getInstance() - c.timeInMillis = start - val direction = if (which > 0) 1 else -1 - while (c[Calendar.DAY_OF_WEEK] != dayOfWeek) { - c.add(Calendar.DAY_OF_MONTH, direction) - } - c.add(Calendar.DAY_OF_MONTH, (abs(which) - 1) * direction * 7) - return Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, c.timeInMillis) - } - - companion object { - private const val PREV_PREV = -2 - private const val PREV = -1 - private const val THIS = 1 - private const val NEXT = 2 - - private val weekdays = listOf(SU, MO, TU, WE, TH, FR, SA) - - fun assertDateTimeEquals(date: Long, other: Long) { - assertEquals("Expected: ${printTimestamp(date)}, Actual: ${printTimestamp(other)}", date, other) - } - } -} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/NewRepeatTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/NewRepeatTests.kt deleted file mode 100644 index 16a5130b9..000000000 --- a/app/src/test/java/com/todoroo/astrid/repeats/NewRepeatTests.kt +++ /dev/null @@ -1,268 +0,0 @@ -package com.todoroo.astrid.repeats - -import com.natpryce.makeiteasy.MakeItEasy.with -import com.todoroo.astrid.data.Task -import net.fortuna.ical4j.model.Recur.Frequency -import net.fortuna.ical4j.model.WeekDay -import org.junit.Assert.assertEquals -import org.junit.Test -import org.tasks.makers.TaskMaker.AFTER_COMPLETE -import org.tasks.makers.TaskMaker.COMPLETION_TIME -import org.tasks.makers.TaskMaker.DUE_TIME -import org.tasks.makers.TaskMaker.RECUR -import org.tasks.makers.TaskMaker.newTask -import org.tasks.repeats.RecurrenceUtils.newRecur -import org.tasks.time.DateTime -import java.text.ParseException - -class NewRepeatTests { - @Test - @Throws(ParseException::class) - fun testRepeatMinutelyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 26, 12, 30) - val task = newFromDue(Frequency.MINUTELY, 1, dueDateTime) - assertEquals(newDayTime(2016, 8, 26, 12, 31), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatHourlyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 26, 12, 30) - val task = newFromDue(Frequency.HOURLY, 1, dueDateTime) - assertEquals(newDayTime(2016, 8, 26, 13, 30), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatDailyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 26, 12, 30) - val task = newFromDue(Frequency.DAILY, 1, dueDateTime) - assertEquals(newDayTime(2016, 8, 27, 12, 30), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatWeeklyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 28, 1, 34) - val task = newFromDue(Frequency.WEEKLY, 1, dueDateTime) - assertEquals(newDayTime(2016, 9, 4, 1, 34), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatMonthlyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 28, 1, 44) - val task = newFromDue(Frequency.MONTHLY, 1, dueDateTime) - assertEquals(newDayTime(2016, 9, 28, 1, 44), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatYearlyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 28, 1, 44) - val task = newFromDue(Frequency.YEARLY, 1, dueDateTime) - assertEquals(newDayTime(2017, 8, 28, 1, 44), calculateNextDueDate(task)) - } - - /** Tests for repeating from completionDate */ - @Test - @Throws(ParseException::class) - fun testRepeatMinutelyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 30, 0, 25) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.MINUTELY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 8, 29, 0, 15), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatMinutelyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 28, 0, 4) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.MINUTELY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 8, 29, 0, 15), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatHourlyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 30, 0, 25) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.HOURLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 8, 29, 1, 14), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatHourlyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 28, 0, 4) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.HOURLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 8, 29, 1, 14), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatDailyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 30, 0, 25) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.DAILY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 8, 30, 0, 25), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatDailyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 28, 0, 4) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.DAILY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 8, 30, 0, 4), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatWeeklyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 30, 0, 25) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.WEEKLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 9, 5, 0, 25), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatWeeklyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 28, 0, 4) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.WEEKLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 9, 5, 0, 4), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatMonthlyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 30, 0, 25) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.MONTHLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 9, 29, 0, 25), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatMonthlyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 28, 0, 4) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.MONTHLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2016, 9, 29, 0, 4), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatYearlyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 30, 0, 25) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.YEARLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2017, 8, 29, 0, 25), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatYearlyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 28, 0, 4) - val completionDateTime = newDayTime(2016, 8, 29, 0, 14) - val task = newFromCompleted(Frequency.YEARLY, 1, dueDateTime, completionDateTime) - assertEquals(newDayTime(2017, 8, 29, 0, 4), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testAdvancedRepeatWeeklyFromDueDate() { - val dueDateTime = newDayTime(2016, 8, 29, 0, 25) - val task = newWeeklyFromDue( - 1, dueDateTime, WeekDay(WeekDay.MO, 0), WeekDay(WeekDay.WE, 0)) - assertEquals(newDayTime(2016, 8, 31, 0, 25), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testAdvancedRepeatWeeklyFromCompleteDateCompleteBefore() { - val dueDateTime = newDayTime(2016, 8, 29, 0, 25) - val completionDateTime = newDayTime(2016, 8, 28, 1, 9) - val task = newWeeklyFromCompleted( - 1, - dueDateTime, - completionDateTime, - WeekDay(WeekDay.MO, 0), - WeekDay(WeekDay.WE, 0)) - assertEquals(newDayTime(2016, 8, 29, 0, 25), calculateNextDueDate(task)) - } - - @Test - @Throws(ParseException::class) - fun testAdvancedRepeatWeeklyFromCompleteDateCompleteAfter() { - val dueDateTime = newDayTime(2016, 8, 29, 0, 25) - val completionDateTime = newDayTime(2016, 9, 1, 1, 9) - val task = newWeeklyFromCompleted( - 1, - dueDateTime, - completionDateTime, - WeekDay(WeekDay.MO, 0), - WeekDay(WeekDay.WE, 0)) - assertEquals(newDayTime(2016, 9, 5, 0, 25), calculateNextDueDate(task)) - } - - private fun newDayTime(year: Int, month: Int, day: Int, hour: Int, minute: Int): DateTime { - return DateTime( - Task.createDueDate( - Task.URGENCY_SPECIFIC_DAY_TIME, - DateTime(year, month, day, hour, minute).millis)) - } - - @Throws(ParseException::class) - private fun calculateNextDueDate(task: Task): DateTime { - return DateTime( - RepeatTaskHelper.computeNextDueDate(task, task.recurrence!!, task.repeatAfterCompletion())) - } - - private fun newFromDue(frequency: Frequency, interval: Int, dueDateTime: DateTime): Task { - return newTask( - with(RECUR, getRecurrenceRule(frequency, interval)), - with(AFTER_COMPLETE, false), - with(DUE_TIME, dueDateTime)) - } - - private fun newWeeklyFromDue(interval: Int, dueDateTime: DateTime, vararg weekdays: WeekDay): Task { - return newTask( - with(RECUR, getRecurrenceRule(Frequency.WEEKLY, interval, *weekdays)), - with(AFTER_COMPLETE, false), - with(DUE_TIME, dueDateTime)) - } - - private fun newFromCompleted( - frequency: Frequency, interval: Int, dueDateTime: DateTime, completionDate: DateTime): Task { - return newTask( - with(RECUR, getRecurrenceRule(frequency, interval)), - with(AFTER_COMPLETE, true), - with(DUE_TIME, dueDateTime), - with(COMPLETION_TIME, completionDate)) - } - - private fun newWeeklyFromCompleted( - interval: Int, dueDateTime: DateTime, completionDate: DateTime, vararg weekdays: WeekDay): Task { - return newTask( - with(RECUR, getRecurrenceRule(Frequency.WEEKLY, interval, *weekdays)), - with(AFTER_COMPLETE, true), - with(DUE_TIME, dueDateTime), - with(COMPLETION_TIME, completionDate)) - } - - private fun getRecurrenceRule( - frequency: Frequency, interval: Int, vararg weekdays: WeekDay): String { - val rrule = newRecur() - rrule.setFrequency(frequency.name) - rrule.interval = interval - if (weekdays.isNotEmpty()) { - rrule.dayList.addAll(weekdays) - } - return rrule.toString() - } -} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatDailyTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatDailyTests.kt new file mode 100644 index 000000000..e6eef17fe --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatDailyTests.kt @@ -0,0 +1,46 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.makers.TaskMaker.COMPLETION_TIME +import org.tasks.time.DateTime + +class RepeatDailyTests : RepeatTests() { + @Test + fun testRepeatDailyFromDueDate() { + val task = newFromDue("FREQ=DAILY;INTERVAL=3", newDayTime(2016, 8, 26, 12, 30)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 12, 30), next) + } + + @Test + fun testRepeatDailyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=DAILY;INTERVAL=1", + newDayTime(2016, 8, 30, 0, 25), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 30, 0, 25), next) + } + + @Test + fun testRepeatDailyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=DAILY;INTERVAL=1", + newDayTime(2016, 8, 28, 0, 4), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 30, 0, 4), next) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatHourlyTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatHourlyTests.kt new file mode 100644 index 000000000..07fd1d57d --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatHourlyTests.kt @@ -0,0 +1,49 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.Freeze.Companion.freezeAt +import org.tasks.makers.TaskMaker.COMPLETION_TIME +import org.tasks.time.DateTime + +class RepeatHourlyTests : RepeatTests() { + @Test + fun testRepeatHourlyFromDueDate() { + val task = newFromDue("FREQ=HOURLY;INTERVAL=6", newDayTime(2016, 8, 26, 12, 30)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 26, 18, 30), next) + } + + @Test + fun testRepeatHourlyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=HOURLY;INTERVAL=1", + newDayTime(2016, 8, 30, 0, 25), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 1, 14), next) + } + + @Test + fun testRepeatHourlyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=HOURLY;INTERVAL=1", + newDayTime(2016, 8, 28, 0, 4), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = freezeAt(newDayTime(2016, 8, 29, 0, 14)) { + calculateNextDueDate(task) + } + + assertEquals(newDayTime(2016, 8, 29, 1, 14), next) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatMinutelyTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatMinutelyTests.kt new file mode 100644 index 000000000..7c2128d69 --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatMinutelyTests.kt @@ -0,0 +1,46 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.makers.TaskMaker.COMPLETION_TIME +import org.tasks.time.DateTime + +class RepeatMinutelyTests : RepeatTests() { + @Test + fun testRepeatMinutelyFromDueDate() { + val task = newFromDue("FREQ=MINUTELY;INTERVAL=30", newDayTime(2016, 8, 26, 12, 30)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 26, 13, 0), next) + } + + @Test + fun testRepeatMinutelyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=MINUTELY;INTERVAL=1", + newDayTime(2016, 8, 30, 0, 25), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 0, 15), next) + } + + @Test + fun testRepeatMinutelyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=MINUTELY;INTERVAL=1", + newDayTime(2016, 8, 28, 0, 4), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 0, 15), next) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatMonthlyTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatMonthlyTests.kt new file mode 100644 index 000000000..55912850c --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatMonthlyTests.kt @@ -0,0 +1,58 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.makers.TaskMaker.COMPLETION_TIME +import org.tasks.time.DateTime + +class RepeatMonthlyTests : RepeatTests() { + @Test + fun testRepeatMonthlyFromDueDate() { + val task = newFromDue("FREQ=MONTHLY;INTERVAL=3", newDayTime(2016, 8, 28, 1, 44)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 11, 28, 1, 44), next) + } + + @Test + fun testRepeatMonthlyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=MONTHLY;INTERVAL=1", + newDayTime(2016, 8, 30, 0, 25), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 29, 0, 25), next) + } + + @Test + fun testRepeatMonthlyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=MONTHLY;INTERVAL=1", + newDayTime(2016, 8, 28, 0, 4), + with(COMPLETION_TIME, DateTime(2016, 8, 29, 0, 14, 13, 451)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 29, 0, 4), next) + } + + @Test + fun repeatAtEndOfJanuary() { + val task = newFromDue( + "FREQ=MONTHLY;INTERVAL=1", + newDayTime(2017, 1, 31, 13, 30) + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2017, 2, 28, 13, 30), next) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatTaskHelperTest.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatTaskHelperTest.kt deleted file mode 100644 index 4c05622f9..000000000 --- a/app/src/test/java/com/todoroo/astrid/repeats/RepeatTaskHelperTest.kt +++ /dev/null @@ -1,211 +0,0 @@ -package com.todoroo.astrid.repeats - -import android.annotation.SuppressLint -import com.natpryce.makeiteasy.MakeItEasy.with -import com.todoroo.astrid.alarms.AlarmService -import com.todoroo.astrid.dao.TaskDao -import com.todoroo.astrid.data.Task -import com.todoroo.astrid.gcal.GCalHelper -import com.todoroo.astrid.service.TaskCompleter -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runBlockingTest -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.mockito.InOrder -import org.mockito.Mockito -import org.tasks.Freeze.Companion.freezeClock -import org.tasks.LocalBroadcastManager -import org.tasks.makers.TaskMaker.AFTER_COMPLETE -import org.tasks.makers.TaskMaker.COMPLETION_TIME -import org.tasks.makers.TaskMaker.DUE_TIME -import org.tasks.makers.TaskMaker.ID -import org.tasks.makers.TaskMaker.RECUR -import org.tasks.makers.TaskMaker.newTask -import org.tasks.repeats.RecurrenceUtils.newRecur -import org.tasks.time.DateTime -import java.text.ParseException - -@ExperimentalCoroutinesApi -@SuppressLint("NewApi") -class RepeatTaskHelperTest { - private lateinit var taskDao: TaskDao - private lateinit var localBroadcastManager: LocalBroadcastManager - private lateinit var alarmService: AlarmService - private lateinit var gCalHelper: GCalHelper - private lateinit var helper: RepeatTaskHelper - private lateinit var mocks: InOrder - private lateinit var taskCompleter: TaskCompleter - - @Before - fun setUp() { - taskDao = Mockito.mock(TaskDao::class.java) - alarmService = Mockito.mock(AlarmService::class.java) - gCalHelper = Mockito.mock(GCalHelper::class.java) - localBroadcastManager = Mockito.mock(LocalBroadcastManager::class.java) - taskCompleter = Mockito.mock(TaskCompleter::class.java) - mocks = Mockito.inOrder(alarmService, gCalHelper, localBroadcastManager) - helper = RepeatTaskHelper(gCalHelper, alarmService, taskDao, localBroadcastManager, taskCompleter) - } - - @After - fun after() { - Mockito.verifyNoMoreInteractions(localBroadcastManager, gCalHelper, alarmService) - } - - @Test - fun noRepeat() = runBlockingTest { - helper.handleRepeat(newTask(with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)))) - } - - @Test - @Throws(ParseException::class) - fun testMinutelyRepeat() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=MINUTELY;INTERVAL=30")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 4, 14, 0, 1)) - } - - @Test - @Throws(ParseException::class) - fun testMinutelyRepeatAfterCompletion() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(COMPLETION_TIME, DateTime(2017, 10, 4, 13, 17, 45, 340)), - with(RECUR, "RRULE:FREQ=MINUTELY;INTERVAL=30"), - with(AFTER_COMPLETE, true)) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 4, 13, 47, 1)) - } - - @Test - @Throws(ParseException::class) - fun testMinutelyDecrementCount() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=MINUTELY;COUNT=2;INTERVAL=30")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 4, 14, 0, 1)) - assertEquals(1, newRecur(task.recurrence!!).count) - } - - @Test - @Throws(ParseException::class) - fun testMinutelyLastOccurrence() = runBlockingTest { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=MINUTELY;COUNT=1;INTERVAL=30")) - helper.handleRepeat(task) - } - - @Test - @Throws(ParseException::class) - fun testHourlyRepeat() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=HOURLY;INTERVAL=6")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 4, 19, 30, 1)) - } - - @Test - @Throws(ParseException::class) - fun testHourlyRepeatAfterCompletion() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(COMPLETION_TIME, DateTime(2017, 10, 4, 13, 17, 45, 340)), - with(RECUR, "RRULE:FREQ=HOURLY;INTERVAL=6"), - with(AFTER_COMPLETE, true)) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 4, 19, 17, 1)) - } - - @Test - @Throws(ParseException::class) - fun testDailyRepeat() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=DAILY;INTERVAL=6")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 10, 13, 30, 1)) - } - - @Test - @Throws(ParseException::class) - fun testRepeatWeeklyNoDays() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=WEEKLY;INTERVAL=2")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2017, 10, 18, 13, 30, 1)) - } - - @Test - @Throws(ParseException::class) - fun testYearly() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=YEARLY;INTERVAL=3")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2020, 10, 4, 13, 30, 1)) - } - - @Test - @Throws(ParseException::class) - fun testMonthlyRepeat() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 10, 4, 13, 30)), - with(RECUR, "RRULE:FREQ=MONTHLY;INTERVAL=3")) - repeatAndVerify( - task, DateTime(2017, 10, 4, 13, 30, 1), DateTime(2018, 1, 4, 13, 30, 1)) - } - - @Test - @Throws(ParseException::class) - fun testMonthlyRepeatAtEndOfMonth() { - val task = newTask( - with(ID, 1L), - with(DUE_TIME, DateTime(2017, 1, 31, 13, 30)), - with(RECUR, "RRULE:FREQ=MONTHLY;INTERVAL=1")) - repeatAndVerify( - task, DateTime(2017, 1, 31, 13, 30, 1), DateTime(2017, 2, 28, 13, 30, 1)) - } - - @Test - fun testAlarmShiftWithNoDueDate() { - val task = newTask( - with(ID, 1L), - with(RECUR, "RRULE:FREQ=DAILY") - ) - freezeClock { - repeatAndVerify( - task, - Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, DateTime().millis), - Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, DateTime().plusDays(1).millis) - ) - } - } - - private fun repeatAndVerify(task: Task, oldDueDate: DateTime, newDueDate: DateTime) = - repeatAndVerify(task, oldDueDate.millis, newDueDate.millis) - - private fun repeatAndVerify(task: Task, oldDueDate: Long, newDueDate: Long) = runBlockingTest { - helper.handleRepeat(task) - mocks.verify(gCalHelper).rescheduleRepeatingTask(task) - mocks.verify(alarmService).rescheduleAlarms(1, oldDueDate, newDueDate) - mocks.verify(localBroadcastManager).broadcastRepeat(1, oldDueDate, newDueDate) - } -} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatTaskHelperTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatTaskHelperTests.kt new file mode 100644 index 000000000..9bd0b0e81 --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatTaskHelperTests.kt @@ -0,0 +1,80 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.* +import org.junit.Test +import org.tasks.Freeze.Companion.freezeAt +import org.tasks.makers.TaskMaker.COMPLETION_TIME +import org.tasks.repeats.RecurrenceUtils.newRecur +import org.tasks.time.DateTime + +class RepeatTaskHelperTests : RepeatTests() { + @Test + fun shouldDecrementCount() { + val task = newFromDue( + "RRULE:FREQ=MINUTELY;COUNT=2;INTERVAL=30", + newDayTime(2017, 10, 4, 13, 30) + ) + + calculateNextDueDate(task) + + assertEquals(1, newRecur(task.recurrence!!).count) + } + + @Test + fun shouldUncompleteTask() { + val task = newFromDue( + "FREQ=DAILY;INTERVAL=1", + newDayTime(2017, 10, 4, 13, 30), + with(COMPLETION_TIME, DateTime()) + ) + + calculateNextDueDate(task) + + assertFalse(task.isCompleted) + } + + @Test + fun dontAdjustOnLastInstance() { + val task = newFromDue( + "FREQ=MINUTELY;COUNT=1;INTERVAL=30", + newDayTime(2017, 10, 4, 13, 30), + with(COMPLETION_TIME, DateTime()) + ) + + val next = calculateNextDueDate(task) + + assertEquals(1, newRecur(task.recurrence!!).count) + assertEquals(newDayTime(2017, 10, 4, 13, 30), next) + assertTrue(task.isCompleted) + } + + @Test + fun useCompletionWhenNoDue() { + val task = newFromDue( + "FREQ=DAILY;INTERVAL=1", + DateTime(0) + ) + + val next = freezeAt(DateTime(2021, 2, 1, 16, 54, 32, 451)) { + calculateNextDueDate(task) + } + + assertEquals(newDay(2021, 2, 2), next) + } + + @Test + fun useNowWhenNoCompletion() { + val task = newFromDue( + "FREQ=DAILY;INTERVAL=1", + newDay(2021, 3, 15), + afterComplete = true + ) + + val next = freezeAt(newDayTime(2021, 3, 29, 14, 32)) { + calculateNextDueDate(task) + } + + assertEquals(newDayTime(2021, 3, 30, 12, 0), next) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatTests.kt new file mode 100644 index 000000000..eee3e614c --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatTests.kt @@ -0,0 +1,57 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy +import com.natpryce.makeiteasy.PropertyValue +import com.todoroo.astrid.alarms.AlarmService +import com.todoroo.astrid.dao.TaskDao +import com.todoroo.astrid.data.Task +import com.todoroo.astrid.gcal.GCalHelper +import com.todoroo.astrid.service.TaskCompleter +import kotlinx.coroutines.runBlocking +import org.mockito.Mockito +import org.tasks.LocalBroadcastManager +import org.tasks.makers.TaskMaker +import org.tasks.time.DateTime + +abstract class RepeatTests { + private val helper = RepeatTaskHelper( + Mockito.mock(GCalHelper::class.java), + Mockito.mock(AlarmService::class.java), + Mockito.mock(TaskDao::class.java), + Mockito.mock(LocalBroadcastManager::class.java), + Mockito.mock(TaskCompleter::class.java) + ) + + protected fun newDay(year: Int, month: Int, day: Int) = + DateTime( + Task.createDueDate( + Task.URGENCY_SPECIFIC_DAY, + DateTime(year, month, day).millis + ) + ) + + protected fun newDayTime(year: Int, month: Int, day: Int, hour: Int, minute: Int) = + DateTime( + Task.createDueDate( + Task.URGENCY_SPECIFIC_DAY_TIME, + DateTime(year, month, day, hour, minute).millis + ) + ) + + protected fun calculateNextDueDate(task: Task): DateTime = runBlocking { + helper.handleRepeat(task) + DateTime(task.dueDate) + } + + protected fun newFromDue( + recur: String, + due: DateTime, + vararg properties: PropertyValue, + afterComplete: Boolean = false + ) = TaskMaker.newTask( + MakeItEasy.with(TaskMaker.RECUR, recur), + MakeItEasy.with(TaskMaker.AFTER_COMPLETE, afterComplete), + MakeItEasy.with(TaskMaker.DUE_TIME, due), + *properties + ) +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatWeeklyTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatWeeklyTests.kt new file mode 100644 index 000000000..0cb118225 --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatWeeklyTests.kt @@ -0,0 +1,190 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.makers.TaskMaker.COMPLETION_TIME + +class RepeatWeeklyTests : RepeatTests() { + @Test + fun testRepeatWeeklyFromDueDate() { + val task = newFromDue("FREQ=WEEKLY;INTERVAL=1", newDayTime(2016, 8, 28, 1, 34)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 4, 1, 34), next) + } + + @Test + fun testRepeatBiWeekly() { + val task = newFromDue("FREQ=WEEKLY;INTERVAL=2", newDayTime(2016, 8, 28, 1, 34)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 11, 1, 34), next) + } + + @Test + fun testRepeatWeeklyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1", + newDayTime(2016, 8, 30, 0, 25), + with(COMPLETION_TIME, newDayTime(2016, 8, 29, 0, 14)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 25), next) + } + + @Test + fun testRepeatWeeklyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1", + newDayTime(2016, 8, 28, 0, 4), + with(COMPLETION_TIME, newDayTime(2016, 8, 29, 0, 14)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 4), next) + } + + @Test + fun testWeeklyBySingleDayBefore() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO", + newDayTime(2016, 8, 28, 0, 25) // Sunday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 0, 25), next) + } + + @Test + fun testWeeklyBySingleDayOf() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO", + newDayTime(2016, 8, 29, 0, 25) // Monday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 25), next) + } + + @Test + fun testWeeklyBySingleDayAfter() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO", + newDayTime(2016, 8, 30, 0, 25) // Sunday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 25), next) + } + + @Test + fun testByDayBeforeFirstDate() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE", + newDayTime(2016, 8, 28, 0, 25) // Sunday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 0, 25), next) + } + + @Test + fun testAdvancedRepeatWeeklyOnFirstDate() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE", + newDayTime(2016, 8, 29, 0, 25) // Monday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 31, 0, 25), next) + } + + @Test + fun testAdvancedRepeatWeeklyOnLastDate() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE", + newDayTime(2016, 8, 31, 0, 25) // Wednesday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 25), next) + } + + @Test + fun testAdvancedRepeatWeeklyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE", + newDayTime(2016, 8, 29, 0, 25), + with(COMPLETION_TIME, newDayTime(2016, 8, 28, 1, 9)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 29, 0, 25), next) + } + + @Test + fun testAdvancedRepeatWeeklyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE", + newDayTime(2016, 8, 29, 0, 25), + with(COMPLETION_TIME, newDayTime(2016, 9, 1, 1, 9)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 25), next) + } + + @Test + fun biweeklyOnBeforeFirstDay() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE", + newDayTime(2016, 8, 28, 0, 25), // Sunday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 5, 0, 25), next) + } + + @Test + fun biweeklyOnFirstDay() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE", + newDayTime(2016, 8, 29, 0, 25), // Monday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 8, 31, 0, 25), next) + } + + @Test + fun biweeklyOnLastDay() { + val task = newFromDue( + "FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE", + newDayTime(2016, 8, 31, 0, 25), // Wednesday + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2016, 9, 12, 0, 25), next) + } +} \ No newline at end of file diff --git a/app/src/test/java/com/todoroo/astrid/repeats/RepeatYearlyTests.kt b/app/src/test/java/com/todoroo/astrid/repeats/RepeatYearlyTests.kt new file mode 100644 index 000000000..69aa6e430 --- /dev/null +++ b/app/src/test/java/com/todoroo/astrid/repeats/RepeatYearlyTests.kt @@ -0,0 +1,45 @@ +package com.todoroo.astrid.repeats + +import com.natpryce.makeiteasy.MakeItEasy.with +import org.junit.Assert.assertEquals +import org.junit.Test +import org.tasks.makers.TaskMaker.COMPLETION_TIME + +class RepeatYearlyTests : RepeatTests() { + @Test + fun testRepeatYearlyFromDueDate() { + val task = newFromDue("FREQ=YEARLY;INTERVAL=2", newDayTime(2016, 8, 28, 1, 44)) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2018, 8, 28, 1, 44), next) + } + + @Test + fun testRepeatYearlyFromCompleteDateCompleteBefore() { + val task = newFromDue( + "FREQ=YEARLY;INTERVAL=1", + newDayTime(2016, 8, 30, 0, 25), + with(COMPLETION_TIME, newDayTime(2016, 8, 29, 0, 14)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2017, 8, 29, 0, 25), next) + } + + @Test + fun testRepeatYearlyFromCompleteDateCompleteAfter() { + val task = newFromDue( + "FREQ=YEARLY;INTERVAL=1", + newDayTime(2016, 8, 28, 0, 4), + with(COMPLETION_TIME, newDayTime(2016, 8, 29, 0, 14)), + afterComplete = true + ) + + val next = calculateNextDueDate(task) + + assertEquals(newDayTime(2017, 8, 29, 0, 4), next) + } +} \ No newline at end of file