mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
659 lines
19 KiB
Kotlin
659 lines
19 KiB
Kotlin
@file:Suppress("ClassName")
|
|
|
|
package org.tasks.caldav
|
|
|
|
import com.natpryce.makeiteasy.MakeItEasy.with
|
|
import com.todoroo.astrid.data.Task.Companion.URGENCY_SPECIFIC_DAY
|
|
import com.todoroo.astrid.data.Task.Companion.createDueDate
|
|
import com.todoroo.astrid.data.Task.Priority.Companion.HIGH
|
|
import com.todoroo.astrid.data.Task.Priority.Companion.LOW
|
|
import com.todoroo.astrid.data.Task.Priority.Companion.MEDIUM
|
|
import net.fortuna.ical4j.model.property.Status
|
|
import org.junit.Assert.*
|
|
import org.junit.Test
|
|
import org.tasks.date.DateTimeUtils.newDateTime
|
|
import org.tasks.makers.CaldavTaskMaker.REMOTE_PARENT
|
|
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
|
|
import org.tasks.makers.TaskMaker
|
|
import org.tasks.makers.TaskMaker.COMPLETION_TIME
|
|
import org.tasks.makers.TaskMaker.CREATION_TIME
|
|
import org.tasks.makers.TaskMaker.newTask
|
|
import org.tasks.makers.iCalMaker
|
|
import org.tasks.makers.iCalMaker.COLLAPSED
|
|
import org.tasks.makers.iCalMaker.COMPLETED_AT
|
|
import org.tasks.makers.iCalMaker.CREATED_AT
|
|
import org.tasks.makers.iCalMaker.DESCRIPTION
|
|
import org.tasks.makers.iCalMaker.DUE_DATE
|
|
import org.tasks.makers.iCalMaker.PARENT
|
|
import org.tasks.makers.iCalMaker.PRIORITY
|
|
import org.tasks.makers.iCalMaker.RRULE
|
|
import org.tasks.makers.iCalMaker.START_DATE
|
|
import org.tasks.makers.iCalMaker.STATUS
|
|
import org.tasks.makers.iCalMaker.TITLE
|
|
import org.tasks.makers.iCalMaker.newIcal
|
|
import org.tasks.time.DateTime
|
|
|
|
class iCalendarMergeTest {
|
|
@Test
|
|
fun applyTitleNewTask() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(TITLE, "Title")),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals("Title", it.title)
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatedTitle() =
|
|
newTask(with(TaskMaker.TITLE, "Title"))
|
|
.applyRemote(
|
|
remote = newIcal(with(TITLE, "Title2")),
|
|
local = newIcal(with(TITLE, "Title")),
|
|
)
|
|
.let {
|
|
assertEquals("Title2", it.title)
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteTitle() =
|
|
newTask(with(TaskMaker.TITLE, "Title3"))
|
|
.applyRemote(
|
|
remote = newIcal(with(TITLE, "Title2")),
|
|
local = newIcal(with(TITLE, "Title")),
|
|
)
|
|
.let {
|
|
assertEquals("Title3", it.title)
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesTitle() =
|
|
newTask(with(TaskMaker.TITLE, "Title"))
|
|
.applyRemote(
|
|
remote = newIcal(with(TITLE, null as String?)),
|
|
local = newIcal(with(TITLE, "Title")),
|
|
)
|
|
.let {
|
|
assertNull(it.title)
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesTitle() =
|
|
newTask(with(TaskMaker.TITLE, null as String?))
|
|
.applyRemote(
|
|
remote = newIcal(with(TITLE, "Title")),
|
|
local = newIcal(with(TITLE, "Title"))
|
|
)
|
|
.let {
|
|
assertNull(it.title)
|
|
}
|
|
|
|
@Test
|
|
fun applyNewDescription() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(DESCRIPTION, "Description")),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals("Description", it.notes)
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteDescription() =
|
|
newTask(with(TaskMaker.DESCRIPTION, "Description3"))
|
|
.applyRemote(
|
|
remote = newIcal(with(DESCRIPTION, "Description2")),
|
|
local = newIcal(with(DESCRIPTION, "Description"))
|
|
)
|
|
.let {
|
|
assertEquals("Description3", it.notes)
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatesDescription() {
|
|
newTask(with(TaskMaker.DESCRIPTION, "Description"))
|
|
.applyRemote(
|
|
remote = newIcal(with(DESCRIPTION, "Description2")),
|
|
local = newIcal(with(DESCRIPTION, "Description"))
|
|
)
|
|
.let {
|
|
assertEquals("Description2", it.notes)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localRemovedDescription() =
|
|
newTask(with(TaskMaker.DESCRIPTION, null as String?))
|
|
.applyRemote(
|
|
remote = newIcal(with(DESCRIPTION, "Description")),
|
|
local = newIcal(with(DESCRIPTION, "Description"))
|
|
)
|
|
.let {
|
|
assertNull(it.notes)
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovedDescription() =
|
|
newTask(with(TaskMaker.DESCRIPTION, "Description"))
|
|
.applyRemote(
|
|
remote = newIcal(with(DESCRIPTION, null as String?)),
|
|
local = newIcal(with(DESCRIPTION, "Description"))
|
|
)
|
|
.let {
|
|
assertNull(it.notes)
|
|
}
|
|
|
|
@Test
|
|
fun applyPriorityNewTask() =
|
|
newTask(with(TaskMaker.PRIORITY, HIGH))
|
|
.applyRemote(
|
|
remote = newIcal(with(PRIORITY, 5)),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals(MEDIUM, it.priority)
|
|
}
|
|
|
|
@Test
|
|
fun localUpdatedPriority() =
|
|
newTask(with(TaskMaker.PRIORITY, LOW))
|
|
.applyRemote(
|
|
remote = newIcal(with(PRIORITY, 5)),
|
|
local = newIcal(with(PRIORITY, 5))
|
|
)
|
|
.let {
|
|
assertEquals(LOW, it.priority)
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatedPriority() =
|
|
newTask(with(TaskMaker.PRIORITY, MEDIUM))
|
|
.applyRemote(
|
|
remote = newIcal(with(PRIORITY, 1)),
|
|
local = newIcal(with(PRIORITY, 5))
|
|
)
|
|
.let {
|
|
assertEquals(HIGH, it.priority)
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemotePriority() =
|
|
newTask(with(TaskMaker.PRIORITY, HIGH))
|
|
.applyRemote(
|
|
remote = newIcal(with(PRIORITY, 1)),
|
|
local = newIcal(with(PRIORITY, 5))
|
|
)
|
|
.let {
|
|
assertEquals(HIGH, it.priority)
|
|
}
|
|
|
|
@Test
|
|
fun dueDateNewTask() {
|
|
val due = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(DUE_DATE, due)),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals(due.allDay(), it.dueDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteAddsDueDate() {
|
|
val due = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(DUE_DATE, due)),
|
|
local = newIcal()
|
|
)
|
|
.let {
|
|
assertEquals(due.allDay(), it.dueDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatesDueDate() {
|
|
val due = newDateTime()
|
|
newTask(with(TaskMaker.DUE_DATE, due))
|
|
.applyRemote(
|
|
remote = newIcal(with(DUE_DATE, due.plusDays(1))),
|
|
local = newIcal(with(DUE_DATE, due))
|
|
)
|
|
.let {
|
|
assertEquals(due.plusDays(1).allDay(), it.dueDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesDueDate() {
|
|
val due = newDateTime()
|
|
newTask(with(TaskMaker.DUE_DATE, due))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(with(DUE_DATE, due))
|
|
)
|
|
.let {
|
|
assertEquals(0, it.dueDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesDueDate() {
|
|
val due = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(DUE_DATE, due)),
|
|
local = newIcal(with(DUE_DATE, due))
|
|
)
|
|
.let {
|
|
assertEquals(0, it.dueDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteDueDate() {
|
|
val due = newDateTime()
|
|
newTask(with(TaskMaker.DUE_DATE, due.plusDays(2)))
|
|
.applyRemote(
|
|
remote = newIcal(with(DUE_DATE, due.plusDays(1))),
|
|
local = newIcal(with(DUE_DATE, due))
|
|
)
|
|
.let {
|
|
assertEquals(due.plusDays(2).allDay(), it.dueDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun startDateNewTask() {
|
|
val start = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(START_DATE, start)),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals(start.startOfDay().millis, it.hideUntil)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteAddsStartDate() {
|
|
val start = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(START_DATE, start)),
|
|
local = newIcal()
|
|
)
|
|
.let {
|
|
assertEquals(start.startOfDay().millis, it.hideUntil)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatesStartDate() {
|
|
val start = newDateTime()
|
|
newTask(with(TaskMaker.START_DATE, start))
|
|
.applyRemote(
|
|
remote = newIcal(with(START_DATE, start.plusDays(1))),
|
|
local = newIcal(with(START_DATE, start))
|
|
)
|
|
.let {
|
|
assertEquals(start.plusDays(1).startOfDay().millis, it.hideUntil)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesStartDate() {
|
|
val start = newDateTime()
|
|
newTask(with(TaskMaker.START_DATE, start))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(with(START_DATE, start))
|
|
)
|
|
.let {
|
|
assertEquals(0, it.hideUntil)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesStartDate() {
|
|
val start = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(START_DATE, start)),
|
|
local = newIcal(with(START_DATE, start))
|
|
)
|
|
.let {
|
|
assertEquals(0, it.hideUntil)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteStartDate() {
|
|
val start = newDateTime()
|
|
newTask(with(TaskMaker.START_DATE, start.plusDays(2)))
|
|
.applyRemote(
|
|
remote = newIcal(with(START_DATE, start.plusDays(1))),
|
|
local = newIcal(with(START_DATE, start))
|
|
)
|
|
.let {
|
|
assertEquals(start.plusDays(2).startOfDay().millis, it.hideUntil)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteAddsCreationDate() {
|
|
val created = newDateTime()
|
|
newTask(with(CREATION_TIME, created.minusMinutes(1)))
|
|
.applyRemote(
|
|
remote = newIcal(with(CREATED_AT, created.toUTC())),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals(created.millis, it.creationDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteSetsRecurrence() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(RRULE, "FREQ=DAILY")),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals("FREQ=DAILY", it.recurrence)
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatesRecurrence() =
|
|
newTask(with(TaskMaker.RECUR, "FREQ=DAILY"))
|
|
.applyRemote(
|
|
remote = newIcal(with(RRULE, "FREQ=MONTHLY")),
|
|
local = newIcal(with(RRULE, "FREQ=DAILY"))
|
|
)
|
|
.let {
|
|
assertEquals("FREQ=MONTHLY", it.recurrence)
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesRecurrence() =
|
|
newTask(with(TaskMaker.RECUR, "FREQ=DAILY"))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(with(RRULE, "FREQ=DAILY"))
|
|
)
|
|
.let {
|
|
assertNull(it.recurrence)
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesRecurrence() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(RRULE, "FREQ=DAILY")),
|
|
local = newIcal(with(RRULE, "FREQ=DAILY"))
|
|
)
|
|
.let {
|
|
assertNull(it.recurrence)
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteRecurrence() =
|
|
newTask(with(TaskMaker.RECUR, "FREQ=WEEKLY"))
|
|
.applyRemote(
|
|
remote = newIcal(with(RRULE, "FREQ=MONTHLY")),
|
|
local = newIcal(with(RRULE, "FREQ=DAILY"))
|
|
)
|
|
.let {
|
|
assertEquals("FREQ=WEEKLY", it.recurrence)
|
|
}
|
|
|
|
@Test
|
|
fun remoteSetsCompletedStatus() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(STATUS, Status.VTODO_COMPLETED)),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertTrue(it.isCompleted)
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatesCompletedStatus() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(STATUS, Status.VTODO_COMPLETED)),
|
|
local = newIcal(with(STATUS, Status.VTODO_IN_PROCESS))
|
|
)
|
|
.let {
|
|
assertTrue(it.isCompleted)
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesCompletedStatus() {
|
|
val now = newDateTime()
|
|
newTask(with(COMPLETION_TIME, now))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(
|
|
with(STATUS, Status.VTODO_COMPLETED),
|
|
with(COMPLETED_AT, now)
|
|
)
|
|
)
|
|
.let {
|
|
assertFalse(it.isCompleted)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteSetsCompletedAt() {
|
|
val now = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(COMPLETED_AT, now.toUTC())),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals(now.startOfSecond().millis, it.completionDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteUpdatesCompletedAt() {
|
|
val now = newDateTime()
|
|
newTask(with(COMPLETION_TIME, now))
|
|
.applyRemote(
|
|
remote = newIcal(with(COMPLETED_AT, now.plusMinutes(5).toUTC())),
|
|
local = newIcal(
|
|
with(COMPLETED_AT, now.toUTC()),
|
|
with(STATUS, Status.VTODO_COMPLETED)
|
|
)
|
|
)
|
|
.let {
|
|
assertEquals(now.plusMinutes(5).startOfSecond().millis, it.completionDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesCompletedAt() {
|
|
val now = newDateTime()
|
|
newTask(with(COMPLETION_TIME, now))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(
|
|
with(COMPLETED_AT, now.toUTC()),
|
|
with(STATUS, Status.VTODO_COMPLETED)
|
|
)
|
|
)
|
|
.let {
|
|
assertFalse(it.isCompleted)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesCompletedAt() {
|
|
val now = newDateTime()
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(COMPLETED_AT, now.toUTC())),
|
|
local = newIcal(
|
|
with(COMPLETED_AT, now.toUTC()),
|
|
with(STATUS, Status.VTODO_COMPLETED)
|
|
)
|
|
)
|
|
.let {
|
|
assertFalse(it.isCompleted)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteCompletedAt() {
|
|
val now = newDateTime()
|
|
newTask(with(COMPLETION_TIME, now.plusMinutes(2)))
|
|
.applyRemote(
|
|
remote = newIcal(with(COMPLETED_AT, now.plusMinutes(1).toUTC())),
|
|
local = newIcal(
|
|
with(COMPLETED_AT, now.toUTC()),
|
|
with(STATUS, Status.VTODO_COMPLETED)
|
|
)
|
|
)
|
|
.let {
|
|
assertEquals(now.plusMinutes(2).millis, it.completionDate)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteSetsCollapsed() {
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(COLLAPSED, true)),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertTrue(it.isCollapsed)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesCollapsed() {
|
|
newTask(with(TaskMaker.COLLAPSED, true))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(with(COLLAPSED, true))
|
|
)
|
|
.let {
|
|
assertFalse(it.isCollapsed)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteCollapsed() {
|
|
newTask(with(TaskMaker.COLLAPSED, true))
|
|
.applyRemote(
|
|
remote = newIcal(with(COLLAPSED, false)),
|
|
local = newIcal(with(COLLAPSED, false))
|
|
)
|
|
.let {
|
|
assertTrue(it.isCollapsed)
|
|
}
|
|
}
|
|
|
|
@Test
|
|
fun remoteSetsOrder() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(iCalMaker.ORDER, 1234)),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals(1234L, it.order)
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesOrder() =
|
|
newTask(with(TaskMaker.ORDER, 1234))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(with(iCalMaker.ORDER, 1234))
|
|
)
|
|
.let {
|
|
assertNull(it.order)
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesOrder() =
|
|
newTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(iCalMaker.ORDER, 1234)),
|
|
local = newIcal(with(iCalMaker.ORDER, 1234))
|
|
)
|
|
.let {
|
|
assertNull(it.order)
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteOrder() =
|
|
newTask(with(TaskMaker.ORDER, 789L))
|
|
.applyRemote(
|
|
remote = newIcal(with(iCalMaker.ORDER, 456L)),
|
|
local = newIcal(with(iCalMaker.ORDER, 123))
|
|
)
|
|
.let {
|
|
assertEquals(789L, it.order)
|
|
}
|
|
|
|
@Test
|
|
fun remoteSetsParent() =
|
|
newCaldavTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(PARENT, "1234")),
|
|
local = null
|
|
)
|
|
.let {
|
|
assertEquals("1234", it.remoteParent)
|
|
}
|
|
|
|
@Test
|
|
fun remoteRemovesParent() =
|
|
newCaldavTask(with(REMOTE_PARENT, "1234"))
|
|
.applyRemote(
|
|
remote = newIcal(),
|
|
local = newIcal(with(PARENT, "1234"))
|
|
)
|
|
.let {
|
|
assertNull(it.remoteParent)
|
|
}
|
|
|
|
@Test
|
|
fun localRemovesParent() =
|
|
newCaldavTask()
|
|
.applyRemote(
|
|
remote = newIcal(with(PARENT, "1234")),
|
|
local = newIcal(with(PARENT, "1234"))
|
|
)
|
|
.let {
|
|
assertNull(it.remoteParent)
|
|
}
|
|
|
|
@Test
|
|
fun localBeatsRemoteParent() =
|
|
newCaldavTask(with(REMOTE_PARENT, "789"))
|
|
.applyRemote(
|
|
remote = newIcal(with(PARENT, "456")),
|
|
local = newIcal(with(PARENT, "123"))
|
|
)
|
|
.let {
|
|
assertEquals("789", it.remoteParent)
|
|
}
|
|
|
|
companion object {
|
|
private fun DateTime.allDay() =
|
|
createDueDate(URGENCY_SPECIFIC_DAY, millis)
|
|
}
|
|
} |