Skip to content

Commit

Permalink
Merge pull request #75 from opatry/google-tasks-bindings-unit-tests
Browse files Browse the repository at this point in the history
`:google:tasks` bindings unit tests
  • Loading branch information
opatry authored Oct 27, 2024
2 parents ed37075 + 3da6404 commit de58ae2
Show file tree
Hide file tree
Showing 18 changed files with 1,324 additions and 0 deletions.
2 changes: 2 additions & 0 deletions google/tasks/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ kotlin {

commonTest.dependencies {
implementation(libs.kotlin.test)
implementation(libs.ktor.client.mock)
implementation(libs.kotlinx.coroutines.test)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 Olivier Patry
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package net.opatry.google.tasks.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ErrorResponse(
@SerialName("error")
val error: Error
) {
@Serializable
data class Error(
@SerialName("code")
val code: Int,
@SerialName("message")
val message: String,
@SerialName("errors")
val errors: List<ErrorDetail>,
) {
@Serializable
data class ErrorDetail(
@SerialName("message")
val message: String,
@SerialName("domain")
val domain: String,
@SerialName("reason")
val reason: String,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 Olivier Patry
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package net.opatry.google.tasks.model

import kotlinx.coroutines.test.runTest
import net.opatry.google.tasks.util.loadJsonAsObject
import kotlin.test.Test
import kotlin.test.assertEquals


class ErrorModelTest {
@Test
fun `parse error response from json`() = runTest {
val errorResponse = loadJsonAsObject<ErrorResponse>("/error_400.json")
assertEquals(
ErrorResponse(
error = ErrorResponse.Error(
code = 400,
message = "Invalid task list ID",
errors = listOf(
ErrorResponse.Error.ErrorDetail(
message = "Invalid task list ID",
domain = "global",
reason = "invalid"
)
)
)
),
errorResponse
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2024 Olivier Patry
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package net.opatry.google.tasks.model

import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import net.opatry.google.tasks.util.loadJsonAsObject
import kotlin.test.Test
import kotlin.test.assertEquals

class TaskListModelTest {
@Test
fun `parse empty task lists from json`() = runTest {
val taskLists = loadJsonAsObject<ResourceListResponse<TaskList>>("/tasklists_empty.json")
assertEquals(
ResourceListResponse(
kind = ResourceType.TaskLists,
etag = "\"MjEwOTM2OTcxOQ\"",
items = emptyList()
),
taskLists
)
}

@Test
fun `parse task lists from json`() = runTest {
val taskLists = loadJsonAsObject<ResourceListResponse<TaskList>>("/tasklists.json")
assertEquals(
ResourceListResponse(
kind = ResourceType.TaskLists,
etag = "\"MjEwOTM2OTcxOQ\"",
items = listOf(
TaskList(
kind = ResourceType.TaskList,
id = "MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow",
etag = "\"LTkzOTI5MzMyNQ\"",
title = "My tasks",
updatedDate = Instant.parse("2024-10-26T08:48:46.790Z"),
selfLink = "https://www.googleapis.com/tasks/v1/users/@me/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow"
),
TaskList(
kind = ResourceType.TaskList,
id = "OXl0d1JibXgyeW1zWWFIMw",
etag = "\"LTE4NjM1MzE4NDk\"",
title = "Other tasks",
updatedDate = Instant.parse("2024-10-15T16:04:48.522Z"),
selfLink = "https://www.googleapis.com/tasks/v1/users/@me/lists/OXl0d1JibXgyeW1zWWFIMw"
),
)
),
taskLists
)
}

@Test
fun `parse task list from json`() = runTest {
val taskList = loadJsonAsObject<TaskList>("/tasklist.json")
assertEquals(
TaskList(
kind = ResourceType.TaskList,
id = "OXl0d1JibXgyeW1zWWFIMw",
etag = "\"LTE4NjM1MzE4NDk\"",
title = "Other tasks",
updatedDate = Instant.parse("2024-10-15T16:04:48.522Z"),
selfLink = "https://www.googleapis.com/tasks/v1/users/@me/lists/OXl0d1JibXgyeW1zWWFIMw"
),
taskList
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2024 Olivier Patry
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software
* is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


package net.opatry.google.tasks.model

import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import net.opatry.google.tasks.util.loadJsonAsObject
import kotlin.test.Test
import kotlin.test.assertEquals


class TaskModelTest {
@Test
fun `parse empty tasks from json`() = runTest {
val tasks = loadJsonAsObject<ResourceListResponse<Task>>("/tasks_empty.json")
assertEquals(
ResourceListResponse(
kind = ResourceType.Tasks,
etag = "\"LTkzOTI5MzMyNQ\"",
items = emptyList()
),
tasks
)
}

@Test
fun `parse tasks from json`() = runTest {
val tasks = loadJsonAsObject<ResourceListResponse<Task>>("/tasks_with_completed_and_hidden.json")
assertEquals(
ResourceListResponse(
kind = ResourceType.Tasks,
etag = "\"LTkzOTI5MzMyNQ\"",
items = listOf(
Task(
kind = ResourceType.Task,
id = "dnBVd2IwZUlMcjZWNU84YQ",
etag = "\"LTkzOTI4MTk4Nw\"",
title = "First task TODO",
updatedDate = Instant.parse("2024-10-26T08:48:57.000Z"),
selfLink = "https://www.googleapis.com/tasks/v1/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow/tasks/dnBVd2IwZUlMcjZWNU84YQ",
position = "00000000000000000000",
status = Task.Status.NeedsAction,
dueDate = Instant.parse("2024-10-28T00:00:00.000Z"),
links = emptyList(),
webViewLink = "https://tasks.google.com/task/vpUwb0eILr6V5O8a?sa=6"
),
Task(
kind = ResourceType.Task,
id = "M3R6eUVFQzJJUzQzZC12Qg",
etag = "\"LTk0NDMxMTUxOQ\"",
title = "A completed task",
updatedDate = Instant.parse("2024-10-26T07:25:08.000Z"),
selfLink = "https://www.googleapis.com/tasks/v1/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow/tasks/M3R6eUVFQzJJUzQzZC12Qg",
position = "09999998270072491951",
status = Task.Status.Completed,
dueDate = Instant.parse("2024-10-26T00:00:00.000Z"),
completedDate = Instant.parse("2024-10-26T07:25:08.000Z"),
isHidden = true,
links = emptyList(),
webViewLink = "https://tasks.google.com/task/3tzyEEC2IS43d-vB?sa=6"
),
Task(
kind = ResourceType.Task,
id = "OTJOZTNPYnJjbWQ0OF9mVQ",
etag = "\"LTE3MDM5ODAyMDc\"",
title = "🎵 with emoji",
updatedDate = Instant.parse("2024-10-17T12:23:59.000Z"),
selfLink = "https://www.googleapis.com/tasks/v1/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow/tasks/OTJOZTNPYnJjbWQ0OF9mVQ",
position = "00000000000000000002",
status = Task.Status.NeedsAction,
dueDate = Instant.parse("2024-10-28T00:00:00.000Z"),
links = emptyList(),
webViewLink = "https://tasks.google.com/task/92Ne3Obrcmd48_fU?sa=6"
),
Task(
kind = ResourceType.Task,
id = "d254c01jY1NBNEpydUJJdw",
etag = "\"LTE4OTYzOTA2NjI\"",
title = "Deleted task",
updatedDate = Instant.parse("2024-10-15T06:57:09.000Z"),
selfLink = "https://www.googleapis.com/tasks/v1/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow/tasks/d254c01jY1NBNEpydUJJdw",
position = "00000000000000000000",
status = Task.Status.NeedsAction,
isDeleted = true,
links = emptyList(),
webViewLink = "https://tasks.google.com/task/wnxsMccSA4JruBIw?sa=6"
),
Task(
kind = ResourceType.Task,
id = "T0dZdThPNDR1RUdydUdCbQ",
etag = "\"LTE5ODE3MDM5Mjg\"",
title = "Task with notes & due date",
updatedDate = Instant.parse("2024-10-14T07:15:16.000Z"),
selfLink = "https://www.googleapis.com/tasks/v1/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow/tasks/T0dZdThPNDR1RUdydUdCbQ",
position = "00000000000000000004",
notes = "Some notes",
status = Task.Status.NeedsAction,
dueDate = Instant.parse("2024-10-28T00:00:00.000Z"),
links = emptyList(),
webViewLink = "https://tasks.google.com/task/OGYu8O44uEGruGBm?sa=6"
)
)
),
tasks
)
}

@Test
fun `parse task from json`() = runTest {
val task = loadJsonAsObject<Task>("/task.json")
assertEquals(
Task(
kind = ResourceType.Task,
id = "dnBVd2IwZUlMcjZWNU84YQ",
etag = "\"LTkzOTI4MTk4Nw\"",
title = "First task TODO",
updatedDate = Instant.parse("2024-10-26T08:48:57.000Z"),
selfLink = "https://www.googleapis.com/tasks/v1/lists/MTAwNDEyMDI1NDY0NDEwNzQ0NDI6MDow/tasks/dnBVd2IwZUlMcjZWNU84YQ",
position = "00000000000000000000",
status = Task.Status.NeedsAction,
dueDate = Instant.parse("2024-10-28T00:00:00.000Z"),
links = emptyList(),
webViewLink = "https://tasks.google.com/task/vpUwb0eILr6V5O8a?sa=6"
),
task
)
}
}
Loading

0 comments on commit de58ae2

Please sign in to comment.