diff --git a/app/src/androidTest/java/com/todoroo/astrid/service/Upgrade_11_3_Test.kt b/app/src/androidTest/java/com/todoroo/astrid/service/Upgrade_11_3_Test.kt index 2c5fc9060..77217bb3e 100644 --- a/app/src/androidTest/java/com/todoroo/astrid/service/Upgrade_11_3_Test.kt +++ b/app/src/androidTest/java/com/todoroo/astrid/service/Upgrade_11_3_Test.kt @@ -2,22 +2,16 @@ package com.todoroo.astrid.service -import android.content.ContentProviderResult -import at.bitfire.ical4android.BatchOperation import com.natpryce.makeiteasy.MakeItEasy.with import com.todoroo.astrid.data.Task -import com.todoroo.astrid.helper.UUIDHelper import dagger.hilt.android.testing.HiltAndroidTest import dagger.hilt.android.testing.UninstallModules import kotlinx.coroutines.runBlocking -import org.dmfs.tasks.contract.TaskContract -import org.dmfs.tasks.contract.TaskContract.CALLER_IS_SYNCADAPTER -import org.dmfs.tasks.contract.TaskContract.TaskLists import org.junit.Test import org.tasks.SuspendFreeze.Companion.freezeAt import org.tasks.TestUtilities.assertEquals -import org.tasks.TestUtilities.fromString -import org.tasks.data.* +import org.tasks.data.CaldavDao +import org.tasks.data.TaskDao import org.tasks.injection.InjectingTestCase import org.tasks.injection.ProductionModule import org.tasks.makers.CaldavTaskMaker.CALENDAR @@ -29,6 +23,7 @@ import org.tasks.makers.TaskMaker.DUE_DATE import org.tasks.makers.TaskMaker.HIDE_TYPE import org.tasks.makers.TaskMaker.MODIFICATION_TIME import org.tasks.makers.TaskMaker.newTask +import org.tasks.opentasks.TestOpenTaskDao import org.tasks.time.DateTime import javax.inject.Inject @@ -37,7 +32,7 @@ import javax.inject.Inject class Upgrade_11_3_Test : InjectingTestCase() { @Inject lateinit var taskDao: TaskDao @Inject lateinit var caldavDao: CaldavDao - @Inject lateinit var openTaskDao: OpenTaskDao + @Inject lateinit var openTaskDao: TestOpenTaskDao @Inject lateinit var upgrader: Upgrade_11_3 @Test @@ -91,12 +86,8 @@ class Upgrade_11_3_Test : InjectingTestCase() { @Test fun applyRemoteOpenTaskStartDate() = runBlocking { - val (listId, list) = insertList() - applyOperation( - MyAndroidTask(fromString(VTODO_WITH_START_DATE)) - .toBuilder(openTaskDao.tasks, true) - .withValue(TaskContract.TaskColumns.LIST_ID, listId) - ) + val (listId, list) = openTaskDao.insertList() + openTaskDao.insertTask(listId, VTODO_WITH_START_DATE) val taskId = taskDao.insert(newTask()) caldavDao.insert(newCaldavTask( with(CALENDAR, list.uuid), @@ -111,12 +102,8 @@ class Upgrade_11_3_Test : InjectingTestCase() { @Test fun ignoreRemoteOpenTaskStartDate() = runBlocking { - val (listId, list) = insertList() - applyOperation( - MyAndroidTask(fromString(VTODO_WITH_START_DATE)) - .toBuilder(openTaskDao.tasks, true) - .withValue(TaskContract.TaskColumns.LIST_ID, listId) - ) + val (listId, list) = openTaskDao.insertList() + openTaskDao.insertTask(listId, VTODO_WITH_START_DATE) val taskId = taskDao.insert(newTask( with(DUE_DATE, DateTime(2021, 1, 20)), with(HIDE_TYPE, Task.HIDE_UNTIL_DUE) @@ -135,12 +122,8 @@ class Upgrade_11_3_Test : InjectingTestCase() { @Test fun touchWithOpenTaskStartDate() = runBlocking { val upgradeTime = DateTime(2021, 1, 21, 11, 47, 32, 450) - val (listId, list) = insertList() - applyOperation( - MyAndroidTask(fromString(VTODO_WITH_START_DATE)) - .toBuilder(openTaskDao.tasks, true) - .withValue(TaskContract.TaskColumns.LIST_ID, listId) - ) + val (listId, list) = openTaskDao.insertList() + openTaskDao.insertTask(listId, VTODO_WITH_START_DATE) val taskId = taskDao.insert(newTask( with(DUE_DATE, DateTime(2021, 1, 20)), with(HIDE_TYPE, Task.HIDE_UNTIL_DUE), @@ -162,12 +145,8 @@ class Upgrade_11_3_Test : InjectingTestCase() { @Test fun dontTouchNoOpenTaskStartDate() = runBlocking { val modificationTime = DateTime(2021, 1, 21, 9, 50, 4, 348) - val (listId, list) = insertList() - applyOperation( - MyAndroidTask(fromString(VTODO_NO_START_DATE)) - .toBuilder(openTaskDao.tasks, true) - .withValue(TaskContract.TaskColumns.LIST_ID, listId) - ) + val (listId, list) = openTaskDao.insertList() + openTaskDao.insertTask(listId, VTODO_NO_START_DATE) val taskId = taskDao.insert(newTask(with(MODIFICATION_TIME, modificationTime))) caldavDao.insert(newCaldavTask( with(CALENDAR, list.uuid), @@ -180,32 +159,6 @@ class Upgrade_11_3_Test : InjectingTestCase() { assertEquals(modificationTime, taskDao.fetch(taskId)?.modificationDate) } - private suspend fun insertList( - type: String = OpenTaskDao.ACCOUNT_TYPE_DAVx5, - account: String = "account" - ): Pair { - val url = UUIDHelper.newUUID() - val uri = openTaskDao.taskLists.buildUpon() - .appendQueryParameter(CALLER_IS_SYNCADAPTER, "true") - .appendQueryParameter(TaskLists.ACCOUNT_NAME, account) - .appendQueryParameter(TaskLists.ACCOUNT_TYPE, type) - .build() - val result = applyOperation( - BatchOperation.CpoBuilder.newInsert(uri) - .withValue(TaskContract.CommonSyncColumns._SYNC_ID, url) - .withValue(TaskLists.SYNC_ENABLED, "1") - ) - return Pair(result.uri!!.lastPathSegment!!, CaldavCalendar().apply { - uuid = UUIDHelper.newUUID() - this.account = "$type:$account" - this.url = url - caldavDao.insert(this) - }) - } - - private fun applyOperation(build: BatchOperation.CpoBuilder): ContentProviderResult = - context.contentResolver.applyBatch(openTaskDao.authority, arrayListOf(build.build()))[0] - companion object { val VTODO_WITH_START_DATE = """ BEGIN:VCALENDAR diff --git a/app/src/androidTest/java/org/tasks/opentasks/OpenTasksSynchronizerTest.kt b/app/src/androidTest/java/org/tasks/opentasks/OpenTasksSynchronizerTest.kt new file mode 100644 index 000000000..acd8ba3f5 --- /dev/null +++ b/app/src/androidTest/java/org/tasks/opentasks/OpenTasksSynchronizerTest.kt @@ -0,0 +1,87 @@ +package org.tasks.opentasks + +import dagger.hilt.android.testing.HiltAndroidTest +import dagger.hilt.android.testing.UninstallModules +import kotlinx.coroutines.runBlocking +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.tasks.R +import org.tasks.data.CaldavAccount +import org.tasks.data.CaldavAccount.Companion.TYPE_OPENTASKS +import org.tasks.data.CaldavDao +import org.tasks.injection.InjectingTestCase +import org.tasks.injection.ProductionModule +import org.tasks.preferences.Preferences +import javax.inject.Inject + +@UninstallModules(ProductionModule::class) +@HiltAndroidTest +class OpenTasksSynchronizerTest : InjectingTestCase() { + @Inject lateinit var openTaskDao: TestOpenTaskDao + @Inject lateinit var caldavDao: CaldavDao + @Inject lateinit var synchronizer: OpenTasksSynchronizer + @Inject lateinit var preferences: Preferences + + @Before + override fun setUp() { + super.setUp() + + openTaskDao.reset() + preferences.setBoolean(R.string.p_debug_pro, true) + } + + @Test + fun createNewAccounts() = runBlocking { + openTaskDao.insertList() + + synchronizer.sync() + + val accounts = caldavDao.getAccounts() + assertEquals(1, accounts.size) + with(accounts[0]) { + assertEquals("bitfire.at.davdroid:test_account", uuid) + assertEquals("test_account", name) + assertEquals(TYPE_OPENTASKS, accountType) + } + } + + @Test + fun cantSyncWithoutPro() = runBlocking { + preferences.setBoolean(R.string.p_debug_pro, false) + openTaskDao.insertList() + + synchronizer.sync() + + assertEquals( + context.getString(R.string.requires_pro_subscription), + caldavDao.getAccounts()[0].error + ) + } + + @Test + fun deleteRemovedAccounts() = runBlocking { + caldavDao.insert(CaldavAccount().apply { + uuid = "bitfire.at.davdroid:test_account" + accountType = TYPE_OPENTASKS + }) + + synchronizer.sync() + + assertTrue(caldavDao.getAccounts().isEmpty()) + } + + @Test + fun createNewLists() = runBlocking { + openTaskDao.insertList() + + synchronizer.sync() + + val lists = caldavDao.getCalendarsByAccount("bitfire.at.davdroid:test_account") + assertEquals(1, lists.size) + with(lists[0]) { + assertEquals(name, "default_list") + } + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/org/tasks/opentasks/TestOpenTaskDao.kt b/app/src/androidTest/java/org/tasks/opentasks/TestOpenTaskDao.kt new file mode 100644 index 000000000..5f043509e --- /dev/null +++ b/app/src/androidTest/java/org/tasks/opentasks/TestOpenTaskDao.kt @@ -0,0 +1,77 @@ +package org.tasks.opentasks + +import android.content.ContentProviderResult +import android.content.Context +import at.bitfire.ical4android.BatchOperation +import com.todoroo.astrid.helper.UUIDHelper +import dagger.hilt.android.qualifiers.ApplicationContext +import org.dmfs.tasks.contract.TaskContract +import org.tasks.TestUtilities +import org.tasks.data.CaldavCalendar +import org.tasks.data.CaldavDao +import org.tasks.data.MyAndroidTask +import org.tasks.data.OpenTaskDao +import javax.inject.Inject + +class TestOpenTaskDao @Inject constructor( + @ApplicationContext context: Context, + private val caldavDao: CaldavDao +) : OpenTaskDao(context, caldavDao) { + suspend fun insertList( + name: String = DEFAULT_LIST, + type: String = DEFAULT_TYPE, + account: String = DEFAULT_ACCOUNT + ): Pair { + val url = UUIDHelper.newUUID() + val uri = taskLists.buildUpon() + .appendQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER, "true") + .appendQueryParameter(TaskContract.TaskLists.ACCOUNT_NAME, account) + .appendQueryParameter(TaskContract.TaskLists.ACCOUNT_TYPE, type) + .build() + val result = applyOperation( + BatchOperation.CpoBuilder.newInsert(uri) + .withValue(TaskContract.CommonSyncColumns._SYNC_ID, url) + .withValue(TaskContract.TaskListColumns.LIST_NAME, name) + .withValue(TaskContract.TaskLists.SYNC_ENABLED, "1") + ) + return Pair(result.uri!!.lastPathSegment!!, CaldavCalendar().apply { + uuid = UUIDHelper.newUUID() + this.account = "$type:$account" + this.url = url + caldavDao.insert(this) + }) + } + + fun insertTask(listId: String, vtodo: String) { + applyOperation( + MyAndroidTask(TestUtilities.fromString(vtodo)) + .toBuilder(tasks, true) + .withValue(TaskContract.TaskColumns.LIST_ID, listId) + ) + } + + fun reset( + type: String = DEFAULT_TYPE, + account: String = DEFAULT_ACCOUNT + ) { + cr.delete( + taskLists.buildUpon() + .appendQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER, "true") + .appendQueryParameter(TaskContract.TaskLists.ACCOUNT_NAME, account) + .appendQueryParameter(TaskContract.TaskLists.ACCOUNT_TYPE, type) + .build(), + null, + null + ) + cr.delete(tasks, null, null) + } + + private fun applyOperation(build: BatchOperation.CpoBuilder): ContentProviderResult = + cr.applyBatch(authority, arrayListOf(build.build()))[0] + + companion object { + const val DEFAULT_ACCOUNT = "test_account" + const val DEFAULT_TYPE = ACCOUNT_TYPE_DAVx5 + const val DEFAULT_LIST = "default_list" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/data/OpenTaskDao.kt b/app/src/main/java/org/tasks/data/OpenTaskDao.kt index 1c9f9ff9a..b18b40503 100644 --- a/app/src/main/java/org/tasks/data/OpenTaskDao.kt +++ b/app/src/main/java/org/tasks/data/OpenTaskDao.kt @@ -23,11 +23,11 @@ import org.tasks.caldav.iCalendar.Companion.APPLE_SORT_ORDER import timber.log.Timber import javax.inject.Inject -class OpenTaskDao @Inject constructor( +open class OpenTaskDao @Inject constructor( @ApplicationContext context: Context, private val caldavDao: CaldavDao ) { - private val cr = context.contentResolver + protected val cr = context.contentResolver val authority = context.getString(R.string.opentasks_authority) val tasks: Uri = Tasks.getContentUri(authority) val taskLists: Uri = TaskLists.getContentUri(authority)