mirror of https://github.com/tasks/tasks
Compare commits
No commits in common. 'main' and '13.6.1' have entirely different histories.
@ -1 +1 @@
|
||||
3.3.3
|
||||
3.2.2
|
||||
|
@ -1,290 +1,106 @@
|
||||
package com.todoroo.astrid.alarms
|
||||
|
||||
import com.natpryce.makeiteasy.MakeItEasy.with
|
||||
import com.todoroo.andlib.utility.DateUtilities
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import dagger.hilt.android.testing.UninstallModules
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.tasks.SuspendFreeze.Companion.freezeAt
|
||||
import org.tasks.data.createDueDate
|
||||
import org.tasks.data.dao.TaskDao
|
||||
import org.tasks.data.entity.Alarm
|
||||
import org.tasks.data.entity.Notification
|
||||
import org.tasks.data.entity.Task
|
||||
import org.tasks.data.Alarm
|
||||
import org.tasks.data.Alarm.Companion.TYPE_DATE_TIME
|
||||
import org.tasks.data.Alarm.Companion.TYPE_RANDOM
|
||||
import org.tasks.data.Alarm.Companion.TYPE_SNOOZE
|
||||
import org.tasks.data.Alarm.Companion.whenDue
|
||||
import org.tasks.data.Alarm.Companion.whenOverdue
|
||||
import org.tasks.data.AlarmDao
|
||||
import org.tasks.data.TaskDao
|
||||
import org.tasks.date.DateTimeUtils.newDateTime
|
||||
import org.tasks.injection.InjectingTestCase
|
||||
import org.tasks.injection.ProductionModule
|
||||
import org.tasks.jobs.AlarmEntry
|
||||
import org.tasks.jobs.NotificationQueue
|
||||
import org.tasks.makers.TaskMaker.COMPLETION_TIME
|
||||
import org.tasks.makers.TaskMaker.DELETION_TIME
|
||||
import org.tasks.makers.TaskMaker.DUE_DATE
|
||||
import org.tasks.makers.TaskMaker.DUE_TIME
|
||||
import org.tasks.makers.TaskMaker.REMINDER_LAST
|
||||
import org.tasks.makers.TaskMaker.newTask
|
||||
import org.tasks.time.DateTime
|
||||
import org.tasks.time.DateTimeUtils2
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
@UninstallModules(ProductionModule::class)
|
||||
@HiltAndroidTest
|
||||
class AlarmJobServiceTest : InjectingTestCase() {
|
||||
@Inject lateinit var alarmDao: AlarmDao
|
||||
@Inject lateinit var taskDao: TaskDao
|
||||
@Inject lateinit var jobs: NotificationQueue
|
||||
@Inject lateinit var alarmService: AlarmService
|
||||
|
||||
@Test
|
||||
fun testNoAlarms() = runBlocking {
|
||||
testResults(emptyList(), 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun futureAlarmWithNoPastAlarm() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 18).millis
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
|
||||
fun scheduleAlarm() = runBlocking {
|
||||
val task = taskDao.createNew(newTask())
|
||||
val alarm = insertAlarm(Alarm(task, DateTime(2017, 9, 24, 19, 57).millis, TYPE_DATE_TIME))
|
||||
|
||||
testResults(emptyList(), DateTime(2024, 5, 18, 18, 0).millis)
|
||||
}
|
||||
verify(AlarmEntry(alarm, task, DateTime(2017, 9, 24, 19, 57).millis, TYPE_DATE_TIME))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pastAlarmWithNoFutureAlarm() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
|
||||
fun ignoreStaleAlarm() = runBlocking {
|
||||
val alarmTime = DateTime(2017, 9, 24, 19, 57)
|
||||
val task = taskDao.createNew(newTask(with(REMINDER_LAST, alarmTime.endOfMinute())))
|
||||
alarmDao.insert(Alarm(task, alarmTime.millis, TYPE_DATE_TIME))
|
||||
|
||||
testResults(
|
||||
listOf(
|
||||
Notification(
|
||||
taskId = 1L,
|
||||
timestamp = DateTimeUtils2.currentTimeMillis(),
|
||||
type = Alarm.TYPE_REL_END
|
||||
)
|
||||
),
|
||||
0
|
||||
)
|
||||
}
|
||||
verify()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pastRecurringAlarmWithFutureRecurrence() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(
|
||||
1,
|
||||
mutableSetOf(
|
||||
Alarm(
|
||||
type = Alarm.TYPE_REL_END,
|
||||
repeat = 1,
|
||||
interval = TimeUnit.HOURS.toMillis(6)
|
||||
)
|
||||
)
|
||||
fun dontScheduleReminderForCompletedTask() = runBlocking {
|
||||
val task = taskDao.insert(
|
||||
newTask(
|
||||
with(DUE_DATE, newDateTime()),
|
||||
with(COMPLETION_TIME, newDateTime())
|
||||
)
|
||||
)
|
||||
alarmDao.insert(whenDue(task))
|
||||
|
||||
testResults(
|
||||
listOf(
|
||||
Notification(
|
||||
taskId = 1L,
|
||||
timestamp = DateTimeUtils2.currentTimeMillis(),
|
||||
type = Alarm.TYPE_REL_END
|
||||
)
|
||||
),
|
||||
DateTime(2024, 5, 18, 0, 0).millis
|
||||
)
|
||||
}
|
||||
verify()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pastAlarmsRemoveSnoozed() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(
|
||||
1,
|
||||
mutableSetOf(
|
||||
Alarm(type = Alarm.TYPE_REL_END),
|
||||
Alarm(time = DateTimeUtils2.currentTimeMillis(), type = Alarm.TYPE_SNOOZE)
|
||||
)
|
||||
fun dontScheduleReminderForDeletedTask() = runBlocking {
|
||||
val task = taskDao.insert(
|
||||
newTask(
|
||||
with(DUE_DATE, newDateTime()),
|
||||
with(DELETION_TIME, newDateTime())
|
||||
)
|
||||
)
|
||||
alarmDao.insert(whenDue(task))
|
||||
|
||||
testResults(
|
||||
listOf(
|
||||
Notification(
|
||||
taskId = 1L,
|
||||
timestamp = DateTimeUtils2.currentTimeMillis(),
|
||||
type = Alarm.TYPE_REL_END
|
||||
)
|
||||
),
|
||||
0
|
||||
)
|
||||
|
||||
assertEquals(
|
||||
listOf(Alarm(id = 1, task = 1, time = 0, type = Alarm.TYPE_REL_END)),
|
||||
alarmService.getAlarms(1)
|
||||
)
|
||||
}
|
||||
verify()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun alarmsOneMinuteApart() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY_TIME,
|
||||
DateTime(2024, 5, 17, 23, 20).millis
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(1, mutableSetOf(Alarm(type = Alarm.TYPE_REL_END)))
|
||||
taskDao.insert(Task())
|
||||
alarmService.synchronizeAlarms(
|
||||
taskId = 2,
|
||||
alarms = mutableSetOf(
|
||||
Alarm(
|
||||
type = Alarm.TYPE_SNOOZE,
|
||||
time = DateTime(2024, 5, 17, 23, 21).millis)
|
||||
)
|
||||
)
|
||||
|
||||
testResults(
|
||||
listOf(
|
||||
Notification(
|
||||
taskId = 1L,
|
||||
timestamp = DateTimeUtils2.currentTimeMillis(),
|
||||
type = Alarm.TYPE_REL_END
|
||||
)
|
||||
),
|
||||
DateTime(2024, 5, 17, 23, 21).millis
|
||||
)
|
||||
}
|
||||
}
|
||||
fun snoozeOverridesAll() = runBlocking {
|
||||
val now = newDateTime()
|
||||
val task = taskDao.insert(newTask(with(DUE_TIME, now)))
|
||||
|
||||
@Test
|
||||
fun futureSnoozeOverrideOverdue() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(
|
||||
1,
|
||||
mutableSetOf(
|
||||
Alarm(type = Alarm.TYPE_REL_END),
|
||||
Alarm(
|
||||
time = DateTimeUtils2.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5),
|
||||
type = Alarm.TYPE_SNOOZE
|
||||
)
|
||||
)
|
||||
)
|
||||
alarmDao.insert(whenDue(task))
|
||||
alarmDao.insert(whenOverdue(task))
|
||||
alarmDao.insert(Alarm(task, DateUtilities.ONE_HOUR, TYPE_RANDOM))
|
||||
val alarm = alarmDao.insert(Alarm(task, now.plusMonths(12).millis, TYPE_SNOOZE))
|
||||
|
||||
testResults(
|
||||
emptyList(),
|
||||
DateTimeUtils2.currentTimeMillis() + TimeUnit.MINUTES.toMillis(5)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ignoreStaleAlarm() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
),
|
||||
reminderLast = DateTime(2024, 5, 17, 18, 0).millis,
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(
|
||||
1,
|
||||
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
|
||||
)
|
||||
|
||||
testResults(
|
||||
emptyList(),
|
||||
0
|
||||
)
|
||||
}
|
||||
verify(AlarmEntry(alarm, task, now.plusMonths(12).millis, TYPE_SNOOZE))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dontScheduleForCompletedTask() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
),
|
||||
completionDate = DateTime(2024, 5, 17, 14, 0).millis,
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(
|
||||
1,
|
||||
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
|
||||
)
|
||||
|
||||
testResults(
|
||||
emptyList(),
|
||||
0
|
||||
)
|
||||
}
|
||||
private suspend fun insertAlarm(alarm: Alarm): Long {
|
||||
alarm.id = alarmDao.insert(alarm)
|
||||
return alarm.id
|
||||
}
|
||||
|
||||
@Test
|
||||
fun dontScheduleForDeletedTask() = runBlocking {
|
||||
freezeAt(DateTime(2024, 5, 17, 23, 20)) {
|
||||
taskDao.insert(
|
||||
Task(
|
||||
dueDate = createDueDate(
|
||||
Task.URGENCY_SPECIFIC_DAY,
|
||||
DateTime(2024, 5, 17).millis
|
||||
),
|
||||
deletionDate = DateTime(2024, 5, 17, 14, 0).millis,
|
||||
)
|
||||
)
|
||||
alarmService.synchronizeAlarms(
|
||||
1,
|
||||
mutableSetOf(Alarm(type = Alarm.TYPE_REL_END))
|
||||
)
|
||||
|
||||
testResults(
|
||||
emptyList(),
|
||||
0
|
||||
)
|
||||
}
|
||||
}
|
||||
private suspend fun verify(vararg alarms: AlarmEntry) {
|
||||
alarmService.scheduleAllAlarms()
|
||||
|
||||
private suspend fun testResults(notifications: List<Notification>, nextAlarm: Long) {
|
||||
val actualNextAlarm = alarmService.triggerAlarms {
|
||||
assertEquals(notifications, it)
|
||||
it.forEach { taskDao.setLastNotified(it.taskId, DateTimeUtils2.currentTimeMillis()) }
|
||||
}
|
||||
assertEquals(nextAlarm, actualNextAlarm)
|
||||
assertEquals(alarms.toList(), jobs.getJobs())
|
||||
}
|
||||
}
|
@ -1,68 +1,50 @@
|
||||
package com.todoroo.astrid.repeats
|
||||
|
||||
import org.tasks.data.entity.Task
|
||||
import com.todoroo.astrid.service.TaskCompleter
|
||||
import com.natpryce.makeiteasy.MakeItEasy.with
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import dagger.hilt.android.testing.UninstallModules
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.tasks.data.dao.TaskDao
|
||||
import org.tasks.data.TaskDao
|
||||
import org.tasks.injection.InjectingTestCase
|
||||
import org.tasks.injection.ProductionModule
|
||||
import org.tasks.time.DateTimeUtils2.currentTimeMillis
|
||||
import org.tasks.makers.TaskMaker.COMPLETION_TIME
|
||||
import org.tasks.makers.TaskMaker.PARENT
|
||||
import org.tasks.makers.TaskMaker.RECUR
|
||||
import org.tasks.makers.TaskMaker.newTask
|
||||
import org.tasks.time.DateTime
|
||||
import javax.inject.Inject
|
||||
|
||||
@UninstallModules(ProductionModule::class)
|
||||
@HiltAndroidTest
|
||||
class RepeatWithSubtasksTests : InjectingTestCase() {
|
||||
@Inject lateinit var taskDao: TaskDao
|
||||
@Inject lateinit var taskCompleter: TaskCompleter
|
||||
@Inject lateinit var repeat: RepeatTaskHelper
|
||||
|
||||
@Test
|
||||
fun uncompleteGrandchildren() = runBlocking {
|
||||
val grandparent = taskDao.createNew(
|
||||
Task(
|
||||
recurrence = "RRULE:FREQ=DAILY"
|
||||
)
|
||||
)
|
||||
val parent = taskDao.createNew(
|
||||
Task(
|
||||
parent = grandparent
|
||||
)
|
||||
)
|
||||
val child = taskDao.createNew(
|
||||
Task(
|
||||
parent = parent,
|
||||
completionDate = currentTimeMillis(),
|
||||
)
|
||||
)
|
||||
val grandparent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY")))
|
||||
val parent = taskDao.createNew(newTask(with(PARENT, grandparent)))
|
||||
val child = taskDao.createNew(newTask(
|
||||
with(PARENT, parent),
|
||||
with(COMPLETION_TIME, DateTime())
|
||||
))
|
||||
|
||||
assertTrue(taskDao.fetch(child)!!.isCompleted)
|
||||
|
||||
taskCompleter.setComplete(grandparent)
|
||||
repeat.handleRepeat(taskDao.fetch(grandparent)!!)
|
||||
|
||||
assertFalse(taskDao.fetch(child)!!.isCompleted)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun uncompleteGoogleTaskChildren() = runBlocking {
|
||||
val parent = taskDao.createNew(
|
||||
Task(
|
||||
recurrence = "RRULE:FREQ=DAILY"
|
||||
)
|
||||
)
|
||||
val child = taskDao.createNew(
|
||||
Task(
|
||||
parent = parent,
|
||||
completionDate = currentTimeMillis(),
|
||||
)
|
||||
)
|
||||
|
||||
assertTrue(taskDao.fetch(child)!!.isCompleted)
|
||||
val parent = taskDao.createNew(newTask(with(RECUR, "RRULE:FREQ=DAILY")))
|
||||
val child = taskDao.createNew(newTask(
|
||||
with(PARENT, parent),
|
||||
with(COMPLETION_TIME, DateTime())
|
||||
))
|
||||
|
||||
taskCompleter.setComplete(parent)
|
||||
repeat.handleRepeat(taskDao.fetch(parent)!!)
|
||||
|
||||
assertFalse(taskDao.fetch(child)!!.isCompleted)
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue