refactor(api): use ApiResult in Shiori and wire into DI

This commit is contained in:
Harsh Shandilya 2023-10-31 12:07:10 +05:30
parent 62bffc33fd
commit 25a11bde59
No known key found for this signature in database
3 changed files with 71 additions and 43 deletions

View file

@ -7,6 +7,7 @@
package dev.msfjarvis.claw.api package dev.msfjarvis.claw.api
import android.annotation.SuppressLint import android.annotation.SuppressLint
import com.slack.eithernet.ApiResult
import dev.msfjarvis.claw.model.shiori.AuthRequest import dev.msfjarvis.claw.model.shiori.AuthRequest
import dev.msfjarvis.claw.model.shiori.AuthResponse import dev.msfjarvis.claw.model.shiori.AuthResponse
import dev.msfjarvis.claw.model.shiori.Bookmark import dev.msfjarvis.claw.model.shiori.Bookmark
@ -23,30 +24,32 @@ import retrofit2.http.PUT
private const val SESSION_ID_HEADER = "X-Session-Id" private const val SESSION_ID_HEADER = "X-Session-Id"
interface ShioriApi { interface ShioriApi {
@POST("/api/login") suspend fun login(@Body body: AuthRequest): AuthResponse @POST("/api/login") suspend fun login(@Body body: AuthRequest): ApiResult<AuthResponse, Unit>
@SuppressLint("RetrofitUsage") // POST without a body is apparently fine? @SuppressLint("RetrofitUsage") // POST without a body is apparently fine?
@POST("/api/logout") @POST("/api/logout")
suspend fun logout(@Header(SESSION_ID_HEADER) sessionId: String) suspend fun logout(@Header(SESSION_ID_HEADER) sessionId: String): ApiResult<Unit, Unit>
@GET("/api/bookmarks") @GET("/api/bookmarks")
suspend fun getBookmarks(@Header(SESSION_ID_HEADER) sessionId: String): BookmarksResponse suspend fun getBookmarks(
@Header(SESSION_ID_HEADER) sessionId: String,
): ApiResult<BookmarksResponse, Unit>
@POST("/api/bookmarks") @POST("/api/bookmarks")
suspend fun addBookmark( suspend fun addBookmark(
@Header(SESSION_ID_HEADER) sessionId: String, @Header(SESSION_ID_HEADER) sessionId: String,
@Body bookmarkRequest: BookmarkRequest, @Body bookmarkRequest: BookmarkRequest,
): Bookmark ): ApiResult<Bookmark, Unit>
@PUT("/api/bookmarks") @PUT("/api/bookmarks")
suspend fun editBookmark( suspend fun editBookmark(
@Header(SESSION_ID_HEADER) sessionId: String, @Header(SESSION_ID_HEADER) sessionId: String,
@Body bookmark: EditedBookmark, @Body bookmark: EditedBookmark,
): Bookmark ): ApiResult<Bookmark, Unit>
@HTTP(method = "DELETE", path = "/api/bookmarks", hasBody = true) @HTTP(method = "DELETE", path = "/api/bookmarks", hasBody = true)
suspend fun deleteBookmark( suspend fun deleteBookmark(
@Header(SESSION_ID_HEADER) sessionId: String, @Header(SESSION_ID_HEADER) sessionId: String,
@Body ids: List<Int>, @Body ids: List<Int>,
): Int ): ApiResult<Int, Unit>
} }

View file

@ -16,6 +16,7 @@ import dagger.multibindings.IntKey
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
import dev.msfjarvis.claw.api.LobstersApi import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.api.LobstersSearchApi import dev.msfjarvis.claw.api.LobstersSearchApi
import dev.msfjarvis.claw.api.ShioriApi
import dev.msfjarvis.claw.api.converters.CSRFTokenConverter import dev.msfjarvis.claw.api.converters.CSRFTokenConverter
import dev.msfjarvis.claw.api.converters.SearchConverter import dev.msfjarvis.claw.api.converters.SearchConverter
import javax.inject.Qualifier import javax.inject.Qualifier
@ -72,6 +73,8 @@ object RetrofitModule {
@Provides @Provides
fun provideSearchApi(@SearchApi retrofit: Retrofit): LobstersSearchApi = retrofit.create() fun provideSearchApi(@SearchApi retrofit: Retrofit): LobstersSearchApi = retrofit.create()
@Provides fun provideShioriApi(retrofit: Retrofit): ShioriApi = retrofit.create()
@Provides @Provides
@IntKey(0) @IntKey(0)
@IntoMap @IntoMap

View file

@ -8,11 +8,17 @@ package dev.msfjarvis.claw.api
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.slack.eithernet.ApiResultCallAdapterFactory
import com.slack.eithernet.ApiResultConverterFactory
import com.slack.eithernet.successOrNull
import dev.msfjarvis.claw.model.shiori.AuthRequest import dev.msfjarvis.claw.model.shiori.AuthRequest
import dev.msfjarvis.claw.model.shiori.AuthResponse import dev.msfjarvis.claw.model.shiori.AuthResponse
import dev.msfjarvis.claw.model.shiori.Bookmark
import dev.msfjarvis.claw.model.shiori.BookmarkRequest import dev.msfjarvis.claw.model.shiori.BookmarkRequest
import dev.msfjarvis.claw.model.shiori.BookmarksResponse
import dev.msfjarvis.claw.model.shiori.EditedBookmark import dev.msfjarvis.claw.model.shiori.EditedBookmark
import dev.msfjarvis.claw.model.shiori.Tag import dev.msfjarvis.claw.model.shiori.Tag
import dev.msfjarvis.claw.util.TestUtils.assertIs
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -31,7 +37,10 @@ class ShioriApiTest {
@BeforeEach @BeforeEach
fun setUp() { fun setUp() {
container.start() container.start()
runBlocking { credentials = api.login(AuthRequest(USER, PASSWORD)) } runBlocking {
credentials =
requireNotNull(api.login(AuthRequest(USER, PASSWORD)).successOrNull()) { "Login failed" }
}
} }
@AfterEach @AfterEach
@ -41,7 +50,8 @@ class ShioriApiTest {
@Test @Test
fun getBookmarks() = runTest { fun getBookmarks() = runTest {
val response = api.getBookmarks(credentials.session) val response = api.getBookmarks(credentials.session).successOrNull()
assertIs<BookmarksResponse>(response)
assertThat(response.page).isEqualTo(1) assertThat(response.page).isEqualTo(1)
assertThat(response.bookmarks).isEmpty() assertThat(response.bookmarks).isEmpty()
} }
@ -49,7 +59,8 @@ class ShioriApiTest {
@Test @Test
fun addBookmark() = runTest { fun addBookmark() = runTest {
val response = val response =
api.addBookmark( api
.addBookmark(
credentials.session, credentials.session,
BookmarkRequest( BookmarkRequest(
"https://example.com", "https://example.com",
@ -64,6 +75,8 @@ class ShioriApiTest {
.trimIndent(), .trimIndent(),
) )
) )
.successOrNull()
assertIs<Bookmark>(response)
assertThat(response.url).isEqualTo("https://example.com") assertThat(response.url).isEqualTo("https://example.com")
assertThat(response.title).isEqualTo("Example Domain") assertThat(response.title).isEqualTo("Example Domain")
assertThat(response.excerpt) assertThat(response.excerpt)
@ -80,7 +93,8 @@ class ShioriApiTest {
@Test @Test
fun editBookmark() = runTest { fun editBookmark() = runTest {
val response = val response =
api.addBookmark( api
.addBookmark(
credentials.session, credentials.session,
BookmarkRequest( BookmarkRequest(
"https://example.com", "https://example.com",
@ -95,6 +109,8 @@ class ShioriApiTest {
.trimIndent(), .trimIndent(),
) )
) )
.successOrNull()
assertIs<Bookmark>(response)
assertThat(response.tags).isEmpty() assertThat(response.tags).isEmpty()
val newBookmark = val newBookmark =
EditedBookmark( EditedBookmark(
@ -103,7 +119,8 @@ class ShioriApiTest {
title = response.title, title = response.title,
tags = listOf(Tag("examples")), tags = listOf(Tag("examples")),
) )
val edited = api.editBookmark(credentials.session, newBookmark) val edited = api.editBookmark(credentials.session, newBookmark).successOrNull()
assertIs<Bookmark>(edited)
assertThat(edited.tags).isNotEmpty() assertThat(edited.tags).isNotEmpty()
assertThat(edited.tags).containsExactly(Tag("examples")) assertThat(edited.tags).containsExactly(Tag("examples"))
} }
@ -111,7 +128,8 @@ class ShioriApiTest {
@Test @Test
fun deleteBookmark() = runTest { fun deleteBookmark() = runTest {
val response = val response =
api.addBookmark( api
.addBookmark(
credentials.session, credentials.session,
BookmarkRequest( BookmarkRequest(
"https://example.com", "https://example.com",
@ -126,7 +144,9 @@ class ShioriApiTest {
.trimIndent(), .trimIndent(),
) )
) )
val count = api.deleteBookmark(credentials.session, listOf(response.id)) .successOrNull()
assertIs<Bookmark>(response)
val count = api.deleteBookmark(credentials.session, listOf(response.id)).successOrNull()
assertThat(count).isEqualTo(1) assertThat(count).isEqualTo(1)
} }
@ -144,7 +164,9 @@ class ShioriApiTest {
get() = get() =
Retrofit.Builder() Retrofit.Builder()
.baseUrl("http://${container.host}:${container.firstMappedPort}") .baseUrl("http://${container.host}:${container.firstMappedPort}")
.addConverterFactory(ApiResultConverterFactory)
.addConverterFactory(json.asConverterFactory(MediaType.get("application/json"))) .addConverterFactory(json.asConverterFactory(MediaType.get("application/json")))
.addCallAdapterFactory(ApiResultCallAdapterFactory)
.build() .build()
.create<ShioriApi>() .create<ShioriApi>()
} }