diff --git a/app/src/androidTest/java/com/todoroo/astrid/adapter/CaldavTaskAdapterTest.kt b/app/src/androidTest/java/com/todoroo/astrid/adapter/CaldavTaskAdapterTest.kt new file mode 100644 index 000000000..89484812e --- /dev/null +++ b/app/src/androidTest/java/com/todoroo/astrid/adapter/CaldavTaskAdapterTest.kt @@ -0,0 +1,176 @@ +package com.todoroo.astrid.adapter + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.natpryce.makeiteasy.MakeItEasy.with +import com.todoroo.astrid.dao.TaskDao +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.tasks.data.CaldavDao +import org.tasks.data.CaldavTask +import org.tasks.data.SubsetCaldav +import org.tasks.data.TaskContainer +import org.tasks.injection.InjectingTestCase +import org.tasks.injection.TestComponent +import org.tasks.makers.TaskContainerMaker.PARENT +import org.tasks.makers.TaskContainerMaker.newTaskContainer +import javax.inject.Inject + +@RunWith(AndroidJUnit4::class) +class CaldavTaskAdapterTest : InjectingTestCase() { + + @Inject lateinit var taskDao: TaskDao + @Inject lateinit var caldavDao: CaldavDao + + private lateinit var adapter: CaldavTaskAdapter + private val tasks = ArrayList() + + @Before + override fun setUp() { + super.setUp() + + tasks.clear() + adapter = CaldavTaskAdapter(taskDao, caldavDao) + adapter.setDataSource(object : TaskAdapterDataSource { + override fun getItem(position: Int) = tasks[position] + + override val itemCount get() = tasks.size + }) + } + + @Test + fun canMoveTask() { + add( + newTaskContainer(), + newTaskContainer()) + + assertTrue(adapter.canMove(tasks[0], 0, tasks[1], 1)) + } + + @Test + fun cantMoveTaskToChildPosition() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0])), + newTaskContainer(with(PARENT, tasks[0]))) + + assertFalse(adapter.canMove(tasks[0], 0, tasks[1], 1)) + assertFalse(adapter.canMove(tasks[0], 0, tasks[2], 2)) + } + + @Test + fun canMoveChildAboveParent() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0]))) + + assertTrue(adapter.canMove(tasks[1], 1, tasks[0], 0)) + } + + @Test + fun canMoveChildBetweenSiblings() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0])), + newTaskContainer(with(PARENT, tasks[0]))) + + assertTrue(adapter.canMove(tasks[1], 1, tasks[2], 2)) + assertTrue(adapter.canMove(tasks[2], 2, tasks[1], 1)) + } + + @Test + fun maxIndentNoChildren() { + add(newTaskContainer(), + newTaskContainer()) + + assertEquals(1, adapter.maxIndent(0, tasks[1])) + } + + @Test + fun maxIndentMultiLevelSubtask() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0])), + newTaskContainer()) + + assertEquals(2, adapter.maxIndent(1, tasks[2])) + } + + @Test + fun movingTaskToNewParentSetsId() { + add(newTaskContainer(), + newTaskContainer()) + + adapter.moved(1, 1, 1) + + assertEquals(tasks[0].id, taskDao.fetch(tasks[1].id)!!.parent) + } + + @Test + fun movingTaskToNewParentSetsRemoteId() { + add(newTaskContainer(), + newTaskContainer()) + + adapter.moved(1, 1, 1) + + val parentId = caldavDao.getTask(tasks[0].id)!!.remoteId!! + + assertTrue(parentId.isNotBlank()) + assertEquals(parentId, caldavDao.getTask(tasks[1].id)!!.remoteParent) + } + + @Test + fun unindentingTaskRemovesParent() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0]))) + + adapter.moved(1, 1, 0) + + assertTrue(caldavDao.getTask(tasks[1].id)!!.remoteParent.isNullOrBlank()) + assertEquals(0, taskDao.fetch(tasks[1].id)!!.parent) + } + + @Test + fun moveSubtaskUpToParent() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0]))) + add(newTaskContainer(with(PARENT, tasks[1]))) + + adapter.moved(2, 2, 1) + + assertEquals(tasks[0].id, taskDao.fetch(tasks[2].id)!!.parent) + } + + @Test + fun moveSubtaskUpToGrandparent() { + add(newTaskContainer()) + add(newTaskContainer(with(PARENT, tasks[0]))) + add(newTaskContainer(with(PARENT, tasks[1]))) + add(newTaskContainer(with(PARENT, tasks[2]))) + + adapter.moved(3, 3, 1) + + assertEquals(tasks[0].id, taskDao.fetch(tasks[3].id)!!.parent) + } + + private fun add(vararg tasks: TaskContainer) { + this.tasks.addAll(tasks) + tasks.forEach { + val task = it.task + taskDao.createNew(task) + val caldavTask = CaldavTask(it.id, "calendar") + if (task.parent > 0) { + caldavTask.remoteParent = caldavDao.getRemoteIdForTask(task.parent) + } + caldavTask.id = caldavDao.insert(caldavTask) + it.caldavTask = caldavTask.toSubset() + } + } + + private fun CaldavTask.toSubset(): SubsetCaldav { + val result = SubsetCaldav() + result.cd_id = id + result.cd_calendar = calendar + result.cd_remote_parent = remoteParent + return result + } + + override fun inject(component: TestComponent) = component.inject(this) +} \ No newline at end of file diff --git a/app/src/androidTest/java/org/tasks/injection/TestComponent.kt b/app/src/androidTest/java/org/tasks/injection/TestComponent.kt index fcdb42c4a..e29858b85 100644 --- a/app/src/androidTest/java/org/tasks/injection/TestComponent.kt +++ b/app/src/androidTest/java/org/tasks/injection/TestComponent.kt @@ -1,5 +1,6 @@ package org.tasks.injection +import com.todoroo.astrid.adapter.CaldavTaskAdapterTest import com.todoroo.astrid.alarms.AlarmJobServiceTest import com.todoroo.astrid.dao.TaskDaoTests import com.todoroo.astrid.gtasks.GtasksListServiceTest @@ -40,4 +41,5 @@ interface TestComponent : ApplicationComponent { fun inject(taskMoverTest: TaskMoverTest) fun inject(locationDaoTest: LocationDaoTest) fun inject(googleTaskListDaoTest: GoogleTaskListDaoTest) + fun inject(caldavTaskAdapterTest: CaldavTaskAdapterTest) } \ No newline at end of file diff --git a/app/src/commonTest/java/org/tasks/makers/TaskContainerMaker.kt b/app/src/commonTest/java/org/tasks/makers/TaskContainerMaker.kt index c078f0665..6708c8e45 100644 --- a/app/src/commonTest/java/org/tasks/makers/TaskContainerMaker.kt +++ b/app/src/commonTest/java/org/tasks/makers/TaskContainerMaker.kt @@ -6,6 +6,7 @@ import com.natpryce.makeiteasy.Property import com.natpryce.makeiteasy.Property.newProperty import com.natpryce.makeiteasy.PropertyLookup import com.natpryce.makeiteasy.PropertyValue +import com.todoroo.astrid.data.Task.Companion.NO_ID import org.tasks.data.TaskContainer import org.tasks.makers.Maker.make import org.tasks.makers.TaskMaker.newTask @@ -17,8 +18,9 @@ object TaskContainerMaker { private val instantiator = Instantiator { lookup: PropertyLookup -> val container = TaskContainer() val parent = lookup.valueOf(PARENT, null as TaskContainer?) + val taskId = lookup.valueOf(ID, NO_ID) container.task = newTask( - with(TaskMaker.ID, lookup.valueOf(ID, 1L)), + with(TaskMaker.ID, taskId), with(TaskMaker.PARENT, parent?.id ?: 0L)) container.indent = parent?.indent?.plus(1) ?: 0 container diff --git a/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt b/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt index 288ba5e76..4563d861f 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt +++ b/app/src/main/java/com/todoroo/astrid/adapter/CaldavTaskAdapter.kt @@ -24,8 +24,12 @@ class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, priva newParent = 0 } else if (previous != null) { when { - indent == previous.getIndent() -> newParent = previous.parent - indent > previous.getIndent() -> newParent = previous.id + indent == previous.getIndent() -> { + newParent = previous.parent + } + indent > previous.getIndent() -> { + newParent = previous.id + } indent < previous.getIndent() -> { newParent = previous.parent var currentIndex = to @@ -45,21 +49,21 @@ class CaldavTaskAdapter internal constructor(private val taskDao: TaskDao, priva return } changeParent(task, newParent) - taskDao.touch(task.id) } private fun changeParent(task: TaskContainer, newParent: Long) { val caldavTask = task.getCaldavTask() if (newParent == 0L) { - caldavTask.remoteParent = "" + caldavTask.cd_remote_parent = "" task.parent = 0 } else { val parentTask = caldavDao.getTask(newParent) ?: return - caldavTask.remoteParent = parentTask.remoteId + caldavTask.cd_remote_parent = parentTask.remoteId task.parent = newParent } caldavDao.update(caldavTask) - taskDao.save(task.getTask()) + taskDao.save(task.getTask(), null) + taskDao.touch(task.id) } private fun taskIsChild(source: TaskContainer, destinationIndex: Int): Boolean { diff --git a/app/src/main/java/org/tasks/data/CaldavDao.kt b/app/src/main/java/org/tasks/data/CaldavDao.kt index 28794a090..041e9f56d 100644 --- a/app/src/main/java/org/tasks/data/CaldavDao.kt +++ b/app/src/main/java/org/tasks/data/CaldavDao.kt @@ -52,11 +52,11 @@ abstract class CaldavDao { abstract fun update(caldavTask: CaldavTask) fun update(caldavTask: SubsetCaldav) { - update(caldavTask.id, caldavTask.remoteParent) + update(caldavTask.cd_id, caldavTask.cd_remote_parent) } @Query("UPDATE caldav_tasks SET cd_remote_parent = :remoteParent WHERE cd_id = :id") - abstract fun update(id: Long, remoteParent: String) + abstract fun update(id: Long, remoteParent: String?) @Update abstract fun update(tasks: Iterable) diff --git a/app/src/main/java/org/tasks/data/SubsetCaldav.java b/app/src/main/java/org/tasks/data/SubsetCaldav.java deleted file mode 100644 index a6fcfcdfe..000000000 --- a/app/src/main/java/org/tasks/data/SubsetCaldav.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.tasks.data; - -import java.util.Objects; - -public class SubsetCaldav { - public long cd_id; - public String cd_calendar; - public long cd_parent; - public String cd_remote_parent; - - public long getId() { - return cd_id; - } - - public String getCalendar() { - return cd_calendar; - } - - public String getRemoteParent() { - return cd_remote_parent; - } - - public void setRemoteParent(String remoteId) { - cd_remote_parent = remoteId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof SubsetCaldav)) { - return false; - } - SubsetCaldav that = (SubsetCaldav) o; - return cd_id == that.cd_id - && cd_parent == that.cd_parent - && Objects.equals(cd_calendar, that.cd_calendar) - && Objects.equals(cd_remote_parent, that.cd_remote_parent); - } - - @Override - public int hashCode() { - return Objects.hash(cd_id, cd_calendar, cd_parent, cd_remote_parent); - } - - @Override - public String toString() { - return "SubsetCaldav{" - + "cd_id=" - + cd_id - + ", cd_calendar='" - + cd_calendar - + '\'' - + ", cd_parent=" - + cd_parent - + ", cd_remote_parent='" - + cd_remote_parent - + '\'' - + '}'; - } -} diff --git a/app/src/main/java/org/tasks/data/SubsetCaldav.kt b/app/src/main/java/org/tasks/data/SubsetCaldav.kt new file mode 100644 index 000000000..710194d7b --- /dev/null +++ b/app/src/main/java/org/tasks/data/SubsetCaldav.kt @@ -0,0 +1,29 @@ +package org.tasks.data + +class SubsetCaldav { + var cd_id: Long = 0 + var cd_calendar: String? = null + var cd_remote_parent: String? = null + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is SubsetCaldav) return false + + if (cd_id != other.cd_id) return false + if (cd_calendar != other.cd_calendar) return false + if (cd_remote_parent != other.cd_remote_parent) return false + + return true + } + + override fun hashCode(): Int { + var result = cd_id.hashCode() + result = 31 * result + (cd_calendar?.hashCode() ?: 0) + result = 31 * result + (cd_remote_parent?.hashCode() ?: 0) + return result + } + + override fun toString(): String { + return "SubsetCaldav(id=$cd_id, calendar=$cd_calendar, remoteParent=$cd_remote_parent)" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/TaskContainer.java b/app/src/main/java/org/tasks/data/TaskContainer.java index 98e2edde2..53499cae3 100644 --- a/app/src/main/java/org/tasks/data/TaskContainer.java +++ b/app/src/main/java/org/tasks/data/TaskContainer.java @@ -26,7 +26,7 @@ public class TaskContainer { } public String getCaldav() { - return caldavTask == null ? null : caldavTask.getCalendar(); + return caldavTask == null ? null : caldavTask.getCd_calendar(); } public String getNotes() { diff --git a/app/src/test/java/com/todoroo/astrid/adapter/CaldavTaskAdapterTest.kt b/app/src/test/java/com/todoroo/astrid/adapter/CaldavTaskAdapterTest.kt deleted file mode 100644 index d2bbb1218..000000000 --- a/app/src/test/java/com/todoroo/astrid/adapter/CaldavTaskAdapterTest.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.todoroo.astrid.adapter - -import com.natpryce.makeiteasy.MakeItEasy.with -import com.todoroo.astrid.dao.TaskDao -import org.junit.After -import org.junit.Assert.* -import org.junit.Before -import org.junit.Test -import org.mockito.Mockito.mock -import org.mockito.Mockito.verifyNoMoreInteractions -import org.tasks.data.CaldavDao -import org.tasks.data.TaskContainer -import org.tasks.makers.TaskContainerMaker.ID -import org.tasks.makers.TaskContainerMaker.PARENT -import org.tasks.makers.TaskContainerMaker.newTaskContainer - -class CaldavTaskAdapterTest { - - private lateinit var taskDao: TaskDao - private lateinit var caldavDao: CaldavDao - private lateinit var adapter: CaldavTaskAdapter - private val tasks = ArrayList() - - @Before - fun setup() { - taskDao = mock(TaskDao::class.java) - caldavDao = mock(CaldavDao::class.java) - tasks.clear() - adapter = CaldavTaskAdapter(taskDao, caldavDao) - adapter.setDataSource(object : TaskAdapterDataSource { - override fun getItem(position: Int) = tasks[position] - - override val itemCount get() = tasks.size - }) - } - - @After - fun teardown() = verifyNoMoreInteractions(taskDao, caldavDao) - - @Test - fun canMoveTask() { - add( - newTaskContainer(), - newTaskContainer()) - - assertTrue(adapter.canMove(tasks[0], 0, tasks[1], 1)) - } - - @Test - fun cantMoveTaskToChildPosition() { - add(newTaskContainer(with(ID, 1L))) - add(newTaskContainer(with(PARENT, tasks[0])), - newTaskContainer(with(PARENT, tasks[0]))) - - assertFalse(adapter.canMove(tasks[0], 0, tasks[1], 1)) - assertFalse(adapter.canMove(tasks[0], 0, tasks[2], 2)) - } - - @Test - fun canMoveChildAboveParent() { - add(newTaskContainer(with(ID, 1L))) - add(newTaskContainer(with(PARENT, tasks[0]))) - - assertTrue(adapter.canMove(tasks[1], 1, tasks[0], 0)) - } - - @Test - fun canMoveChildBetweenSiblings() { - add(newTaskContainer(with(ID, 1L))) - add(newTaskContainer(with(PARENT, tasks[0])), - newTaskContainer(with(PARENT, tasks[0]))) - - assertTrue(adapter.canMove(tasks[1], 1, tasks[2], 2)) - assertTrue(adapter.canMove(tasks[2], 2, tasks[1], 1)) - } - - @Test - fun maxIndentNoChildren() { - add(newTaskContainer(), - newTaskContainer()) - - assertEquals(1, adapter.maxIndent(0, tasks[1])) - } - - @Test - fun maxIndentMultiLevelSubtask() { - add(newTaskContainer(with(ID, 1L))) - add(newTaskContainer(with(PARENT, tasks[0])), - newTaskContainer()) - - assertEquals(2, adapter.maxIndent(1, tasks[2])) - } - - private fun add(vararg tasks: TaskContainer) = this.tasks.addAll(tasks.toList()) -} \ No newline at end of file diff --git a/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 000000000..ca6ee9cea --- /dev/null +++ b/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file