mirror of
https://github.com/wismna/DoNext.git
synced 2025-12-06 00:02:40 -05:00
Add task dao tests
Finish task list dao tests
This commit is contained in:
@@ -0,0 +1,215 @@
|
|||||||
|
package com.wismna.geoffroy.donext.data.local.dao
|
||||||
|
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.wismna.geoffroy.donext.data.entities.TaskEntity
|
||||||
|
import com.wismna.geoffroy.donext.data.entities.TaskListEntity
|
||||||
|
import com.wismna.geoffroy.donext.data.local.AppDatabase
|
||||||
|
import com.wismna.geoffroy.donext.domain.model.Priority
|
||||||
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import junit.framework.TestCase.assertFalse
|
||||||
|
import junit.framework.TestCase.assertNotNull
|
||||||
|
import junit.framework.TestCase.assertNull
|
||||||
|
import junit.framework.TestCase.assertTrue
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class TaskDaoTest {
|
||||||
|
|
||||||
|
private lateinit var db: AppDatabase
|
||||||
|
private lateinit var taskDao: TaskDao
|
||||||
|
private lateinit var listDao: TaskListDao
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
db = Room.inMemoryDatabaseBuilder(
|
||||||
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
AppDatabase::class.java
|
||||||
|
).allowMainThreadQueries().build()
|
||||||
|
taskDao = db.taskDao()
|
||||||
|
listDao = db.taskListDao()
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
db.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun insertListAndReturnId(name: String = "List", order: Int = 0): Long {
|
||||||
|
listDao.insertTaskList(TaskListEntity(name = name, order = order))
|
||||||
|
return listDao.getTaskLists().first().first().id
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun insertAndGetTaskById_worksCorrectly() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val task = TaskEntity(
|
||||||
|
name = "Do laundry",
|
||||||
|
description = null,
|
||||||
|
taskListId = listId,
|
||||||
|
priority = Priority.NORMAL
|
||||||
|
)
|
||||||
|
|
||||||
|
taskDao.insertTask(task)
|
||||||
|
val inserted = taskDao.getTasksForList(listId).first().first()
|
||||||
|
val fetched = taskDao.getTaskById(inserted.id)
|
||||||
|
|
||||||
|
assertNotNull(fetched)
|
||||||
|
assertEquals("Do laundry", fetched!!.name)
|
||||||
|
assertEquals(listId, fetched.taskListId)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getTasksForList_returnsOrderedByDoneAndPriority() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val high = TaskEntity(name = "High", description = null, priority = Priority.HIGH, taskListId = listId)
|
||||||
|
val normal = TaskEntity(name = "Normal", description = null, priority = Priority.NORMAL, taskListId = listId)
|
||||||
|
val done = TaskEntity(name = "Done", description = null, priority = Priority.NORMAL, taskListId = listId, isDone = true)
|
||||||
|
|
||||||
|
taskDao.insertTask(normal)
|
||||||
|
taskDao.insertTask(done)
|
||||||
|
taskDao.insertTask(high)
|
||||||
|
|
||||||
|
val tasks = taskDao.getTasksForList(listId).first()
|
||||||
|
assertEquals(listOf("High", "Normal", "Done"), tasks.map { it.name })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateTask_updatesFields() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val task = TaskEntity(name = "Old", description = null, priority = Priority.NORMAL, taskListId = listId)
|
||||||
|
taskDao.insertTask(task)
|
||||||
|
val inserted = taskDao.getTasksForList(listId).first().first()
|
||||||
|
|
||||||
|
val updated = inserted.copy(name = "Updated")
|
||||||
|
taskDao.updateTask(updated)
|
||||||
|
|
||||||
|
val fetched = taskDao.getTaskById(inserted.id)
|
||||||
|
assertEquals("Updated", fetched!!.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun toggleTaskDone_setsCorrectValue() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val task = TaskEntity(name = "Toggle me", description = null, priority = Priority.NORMAL, taskListId = listId, isDone = false)
|
||||||
|
taskDao.insertTask(task)
|
||||||
|
val inserted = taskDao.getTasksForList(listId).first().first()
|
||||||
|
|
||||||
|
taskDao.toggleTaskDone(inserted.id, true)
|
||||||
|
assertTrue(taskDao.getTaskById(inserted.id)!!.isDone)
|
||||||
|
|
||||||
|
taskDao.toggleTaskDone(inserted.id, false)
|
||||||
|
assertFalse(taskDao.getTaskById(inserted.id)!!.isDone)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun toggleTaskDeleted_marksTaskDeleted() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val task = TaskEntity(name = "Trash me", description = null, priority = Priority.NORMAL, taskListId = listId)
|
||||||
|
taskDao.insertTask(task)
|
||||||
|
val inserted = taskDao.getTasksForList(listId).first().first()
|
||||||
|
|
||||||
|
taskDao.toggleTaskDeleted(inserted.id, true)
|
||||||
|
val deletedTask = taskDao.getTaskById(inserted.id)
|
||||||
|
assertTrue(deletedTask!!.isDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun toggleAllTasksFromListDeleted_marksAllDeleted() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val tasks = listOf(
|
||||||
|
TaskEntity(name = "A", description = null, priority = Priority.NORMAL, taskListId = listId),
|
||||||
|
TaskEntity(name = "B", description = null, priority = Priority.NORMAL, taskListId = listId)
|
||||||
|
)
|
||||||
|
tasks.forEach { taskDao.insertTask(it) }
|
||||||
|
|
||||||
|
taskDao.toggleAllTasksFromListDeleted(listId, true)
|
||||||
|
val fetched = taskDao.getTasksForList(listId).first()
|
||||||
|
assertTrue(fetched.isEmpty()) // filtered by deleted = 0
|
||||||
|
|
||||||
|
// confirm soft deletion
|
||||||
|
val softDeleted = fetched.size < 2
|
||||||
|
assertTrue(softDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun permanentDeleteTask_removesFromDatabase() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val task = TaskEntity(name = "Temp", description = null, priority = Priority.NORMAL, taskListId = listId)
|
||||||
|
taskDao.insertTask(task)
|
||||||
|
val inserted = taskDao.getTasksForList(listId).first().first()
|
||||||
|
|
||||||
|
taskDao.permanentDeleteTask(inserted.id)
|
||||||
|
assertNull(taskDao.getTaskById(inserted.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun permanentDeleteAllDeletedTasks_removesAllDeleted() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val active = TaskEntity(name = "Active", description = null, priority = Priority.NORMAL, taskListId = listId)
|
||||||
|
val deleted = TaskEntity(name = "Deleted", description = null, priority = Priority.NORMAL, taskListId = listId, isDeleted = true)
|
||||||
|
taskDao.insertTask(active)
|
||||||
|
taskDao.insertTask(deleted)
|
||||||
|
|
||||||
|
taskDao.permanentDeleteAllDeletedTasks()
|
||||||
|
val remaining = taskDao.getTasksForList(listId).first()
|
||||||
|
assertEquals(1, remaining.size)
|
||||||
|
assertEquals("Active", remaining.first().name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getDeletedTasksWithListName_returnsCorrectlyJoinedData() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId(name = "Work")
|
||||||
|
val deleted = TaskEntity(name = "Trash", taskListId = listId, description = null, priority = Priority.NORMAL, isDeleted = true)
|
||||||
|
taskDao.insertTask(deleted)
|
||||||
|
|
||||||
|
val results = taskDao.getDeletedTasksWithListName().first()
|
||||||
|
assertEquals(1, results.size)
|
||||||
|
assertEquals("Trash", results.first().task.name)
|
||||||
|
assertEquals("Work", results.first().listName)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getDueTodayTasks_returnsTasksWithinRange() = runBlocking {
|
||||||
|
val listId = insertListAndReturnId()
|
||||||
|
val todayStart = Instant.parse("2025-09-15T00:00:00Z").toEpochMilli()
|
||||||
|
val todayEnd = Instant.parse("2025-09-15T23:59:59Z").toEpochMilli()
|
||||||
|
|
||||||
|
val yesterday = TaskEntity(
|
||||||
|
name = "Yesterday",
|
||||||
|
description = null,
|
||||||
|
priority = Priority.NORMAL,
|
||||||
|
taskListId = listId,
|
||||||
|
dueDate = Instant.parse("2025-09-14T12:00:00Z").toEpochMilli()
|
||||||
|
)
|
||||||
|
val today = TaskEntity(
|
||||||
|
name = "Today",
|
||||||
|
description = null,
|
||||||
|
priority = Priority.NORMAL,
|
||||||
|
taskListId = listId,
|
||||||
|
dueDate = Instant.parse("2025-09-15T12:00:00Z").toEpochMilli()
|
||||||
|
)
|
||||||
|
val tomorrow = TaskEntity(
|
||||||
|
name = "Tomorrow",
|
||||||
|
description = null,
|
||||||
|
priority = Priority.NORMAL,
|
||||||
|
taskListId = listId,
|
||||||
|
dueDate = Instant.parse("2025-09-16T12:00:00Z").toEpochMilli()
|
||||||
|
)
|
||||||
|
|
||||||
|
taskDao.insertTask(yesterday)
|
||||||
|
taskDao.insertTask(today)
|
||||||
|
taskDao.insertTask(tomorrow)
|
||||||
|
|
||||||
|
val tasks = taskDao.getDueTodayTasks(todayStart, todayEnd).first()
|
||||||
|
assertEquals(1, tasks.size)
|
||||||
|
assertEquals("Today", tasks.first().name)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.wismna.geoffroy.donext.data.local.repository
|
package com.wismna.geoffroy.donext.data.local.dao
|
||||||
|
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
@@ -6,10 +6,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import com.wismna.geoffroy.donext.data.entities.TaskEntity
|
import com.wismna.geoffroy.donext.data.entities.TaskEntity
|
||||||
import com.wismna.geoffroy.donext.data.entities.TaskListEntity
|
import com.wismna.geoffroy.donext.data.entities.TaskListEntity
|
||||||
import com.wismna.geoffroy.donext.data.local.AppDatabase
|
import com.wismna.geoffroy.donext.data.local.AppDatabase
|
||||||
import com.wismna.geoffroy.donext.data.local.dao.TaskDao
|
|
||||||
import com.wismna.geoffroy.donext.data.local.dao.TaskListDao
|
|
||||||
import com.wismna.geoffroy.donext.domain.model.Priority
|
import com.wismna.geoffroy.donext.domain.model.Priority
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import junit.framework.TestCase.assertNotNull
|
||||||
|
import junit.framework.TestCase.assertTrue
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
@@ -19,7 +19,7 @@ import org.junit.runner.RunWith
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class TaskDaoTest {
|
class TaskListDaoTest {
|
||||||
|
|
||||||
private lateinit var db: AppDatabase
|
private lateinit var db: AppDatabase
|
||||||
private lateinit var taskDao: TaskDao
|
private lateinit var taskDao: TaskDao
|
||||||
@@ -40,6 +40,73 @@ class TaskDaoTest {
|
|||||||
db.close()
|
db.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun insertTaskList_insertsSuccessfully() = runBlocking {
|
||||||
|
val taskList = TaskListEntity(name = "Personal", order = 1)
|
||||||
|
listDao.insertTaskList(taskList)
|
||||||
|
|
||||||
|
val lists = listDao.getTaskLists().first()
|
||||||
|
assertEquals(1, lists.size)
|
||||||
|
assertEquals("Personal", lists.first().name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getTaskListById_returnsCorrectEntity() = runBlocking {
|
||||||
|
val taskList = TaskListEntity(name = "Groceries", order = 0)
|
||||||
|
listDao.insertTaskList(taskList)
|
||||||
|
|
||||||
|
val inserted = listDao.getTaskLists().first().first()
|
||||||
|
val fetched = listDao.getTaskListById(inserted.id)
|
||||||
|
|
||||||
|
assertNotNull(fetched)
|
||||||
|
assertEquals("Groceries", fetched!!.name)
|
||||||
|
assertEquals(inserted.id, fetched.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateTaskList_updatesSuccessfully() = runBlocking {
|
||||||
|
val taskList = TaskListEntity(name = "Work", order = 0)
|
||||||
|
listDao.insertTaskList(taskList)
|
||||||
|
|
||||||
|
val inserted = listDao.getTaskLists().first().first()
|
||||||
|
val updated = inserted.copy(name = "Updated Work")
|
||||||
|
listDao.updateTaskList(updated)
|
||||||
|
|
||||||
|
val fetched = listDao.getTaskListById(inserted.id)
|
||||||
|
assertEquals("Updated Work", fetched!!.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deleteTaskList_marksAsDeleted() = runBlocking {
|
||||||
|
val taskList = TaskListEntity(name = "Errands", order = 0)
|
||||||
|
listDao.insertTaskList(taskList)
|
||||||
|
|
||||||
|
val inserted = listDao.getTaskLists().first().first()
|
||||||
|
listDao.deleteTaskList(inserted.id, true)
|
||||||
|
|
||||||
|
// getTaskLists() filters deleted = 0, so result should be empty
|
||||||
|
val activeLists = listDao.getTaskLists().first()
|
||||||
|
assertTrue(activeLists.isEmpty())
|
||||||
|
|
||||||
|
// But the entity still exists in DB
|
||||||
|
val softDeleted = listDao.getTaskListById(inserted.id)
|
||||||
|
assertNotNull(softDeleted)
|
||||||
|
assertTrue(softDeleted!!.isDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getTaskLists_returnsOrderedByDisplayOrder() = runBlocking {
|
||||||
|
val first = TaskListEntity(name = "Zeta", order = 2)
|
||||||
|
val second = TaskListEntity(name = "Alpha", order = 0)
|
||||||
|
val third = TaskListEntity(name = "Beta", order = 1)
|
||||||
|
listDao.insertTaskList(first)
|
||||||
|
listDao.insertTaskList(second)
|
||||||
|
listDao.insertTaskList(third)
|
||||||
|
|
||||||
|
val lists = listDao.getTaskLists().first()
|
||||||
|
assertEquals(listOf("Alpha", "Beta", "Zeta"), lists.map { it.name })
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun overdueCount_correctlyCalculated() = runBlocking {
|
fun overdueCount_correctlyCalculated() = runBlocking {
|
||||||
listDao.insertTaskList(TaskListEntity(name = "Work", order = 0))
|
listDao.insertTaskList(TaskListEntity(name = "Work", order = 0))
|
||||||
@@ -85,7 +152,7 @@ class TaskDaoTest {
|
|||||||
|
|
||||||
val lists = listDao.getTaskListsWithOverdue(now)
|
val lists = listDao.getTaskListsWithOverdue(now)
|
||||||
|
|
||||||
TestCase.assertEquals(1, lists.first().first().overdueCount)
|
assertEquals(1, lists.first().first().overdueCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -94,7 +161,7 @@ class TaskDaoTest {
|
|||||||
val listId = listDao.getTaskLists().first().first().id
|
val listId = listDao.getTaskLists().first().first().id
|
||||||
|
|
||||||
val todayStart = Instant.parse("2025-09-15T00:00:00Z").toEpochMilli()
|
val todayStart = Instant.parse("2025-09-15T00:00:00Z").toEpochMilli()
|
||||||
val todayEnd = Instant.parse("2025-09-15T23:59:99Z").toEpochMilli()
|
val todayEnd = Instant.parse("2025-09-15T23:59:59Z").toEpochMilli()
|
||||||
|
|
||||||
// One task due yesterday
|
// One task due yesterday
|
||||||
taskDao.insertTask(
|
taskDao.insertTask(
|
||||||
@@ -129,7 +196,7 @@ class TaskDaoTest {
|
|||||||
priority = Priority.NORMAL
|
priority = Priority.NORMAL
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
// One task due in the future
|
// One task due today but done
|
||||||
taskDao.insertTask(
|
taskDao.insertTask(
|
||||||
TaskEntity(
|
TaskEntity(
|
||||||
name = "TodayDone",
|
name = "TodayDone",
|
||||||
@@ -140,7 +207,7 @@ class TaskDaoTest {
|
|||||||
priority = Priority.NORMAL
|
priority = Priority.NORMAL
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
// One task due in the future
|
// One task due today but deleted
|
||||||
taskDao.insertTask(
|
taskDao.insertTask(
|
||||||
TaskEntity(
|
TaskEntity(
|
||||||
name = "TodayDeleted",
|
name = "TodayDeleted",
|
||||||
@@ -155,7 +222,7 @@ class TaskDaoTest {
|
|||||||
|
|
||||||
val tasks = taskDao.getDueTodayTasks(todayStart, todayEnd)
|
val tasks = taskDao.getDueTodayTasks(todayStart, todayEnd)
|
||||||
|
|
||||||
TestCase.assertEquals(1, tasks.first().count())
|
assertEquals(1, tasks.first().count())
|
||||||
TestCase.assertEquals("Prepare slides", tasks.first().first().name)
|
assertEquals("Today", tasks.first().first().name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user