all: move model classes to database, rename model to api

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-12-17 12:30:03 +05:30
parent 62d7590501
commit b18de72bdd
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
20 changed files with 46 additions and 34 deletions

1
api/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

18
api/build.gradle.kts Normal file
View file

@ -0,0 +1,18 @@
plugins {
id("com.android.library")
kotlin("android")
kotlin("kapt")
`lobsters-plugin`
}
dependencies {
kapt(Dependencies.AndroidX.Hilt.daggerCompiler)
kapt(Dependencies.ThirdParty.Moshi.codegen)
api(Dependencies.ThirdParty.Retrofit.lib)
implementation(project(":database"))
implementation(Dependencies.AndroidX.Hilt.dagger)
implementation(Dependencies.ThirdParty.Retrofit.moshi)
testImplementation(Dependencies.Kotlin.Coroutines.core)
testImplementation(Dependencies.Testing.junit)
testImplementation(Dependencies.Testing.mockWebServer)
}

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="dev.msfjarvis.lobsters.model" />

View file

@ -0,0 +1,18 @@
package dev.msfjarvis.lobsters.data.api
import dev.msfjarvis.lobsters.data.local.LobstersPost
import retrofit2.http.GET
import retrofit2.http.Query
/**
* Simple interface defining an API for lobste.rs
*/
interface LobstersApi {
@GET("hottest.json")
suspend fun getHottestPosts(@Query("page") page: Int): List<LobstersPost>
companion object {
const val BASE_URL = "https://lobste.rs"
}
}

View file

@ -0,0 +1,52 @@
package dev.msfjarvis.lobsters.injection
import com.squareup.moshi.Moshi
import dagger.Lazy
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dev.msfjarvis.lobsters.data.api.LobstersApi
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create
@Module
@InstallIn(ViewModelComponent::class)
object ApiModule {
@Provides
@BaseUrlQualifier
fun provideBaseUrl(): String {
return LobstersApi.BASE_URL
}
@Provides
fun provideClient(): OkHttpClient {
return OkHttpClient.Builder()
.build()
}
/**
* Using [Lazy] here is a trick I picked up from Zac Sweers, which he explained in more
* detail here: https://www.zacsweers.dev/dagger-party-tricks-deferred-okhttp-init/
*/
@Provides
fun provideRetrofit(
client: Lazy<OkHttpClient>,
moshi: Lazy<Moshi>,
@BaseUrlQualifier baseUrl: String
): Retrofit {
return Retrofit.Builder()
.client(client.get())
.baseUrl(baseUrl)
.addConverterFactory(MoshiConverterFactory.create(moshi.get()))
.build()
}
@Provides
fun provideApi(retrofit: Retrofit): LobstersApi {
return retrofit.create()
}
}

View file

@ -0,0 +1,11 @@
package dev.msfjarvis.lobsters.injection
import javax.inject.Qualifier
/**
* Qualifier for a string value that needs to be provided to the [ApiModule.provideRetrofit] method
* as the base URL of our API.
*/
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class BaseUrlQualifier

View file

@ -0,0 +1,16 @@
package dev.msfjarvis.lobsters.injection
import com.squareup.moshi.Moshi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object MoshiModule {
@Provides
fun provideMoshi(): Moshi {
return Moshi.Builder().build()
}
}

View file

@ -0,0 +1,71 @@
package dev.msfjarvis.lobsters.data.api
import dev.msfjarvis.lobsters.injection.ApiModule
import dev.msfjarvis.lobsters.injection.MoshiModule
import dev.msfjarvis.lobsters.util.TestUtils
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okhttp3.mockwebserver.RecordedRequest
import org.junit.AfterClass
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.BeforeClass
import org.junit.Test
class LobstersApiTest {
companion object {
private val webServer = MockWebServer()
private val apiData = TestUtils.getJson("hottest.json")
private val okHttp = ApiModule.provideClient()
private val retrofit = ApiModule.provideRetrofit(
{ okHttp },
{ MoshiModule.provideMoshi() },
"http://localhost:8080/"
)
private val apiClient = ApiModule.provideApi(retrofit)
@JvmStatic
@BeforeClass
fun setUp() {
webServer.start(8080)
webServer.dispatcher = object : Dispatcher() {
override fun dispatch(request: RecordedRequest): MockResponse {
return MockResponse().setBody(apiData).setResponseCode(200)
}
}
}
@JvmStatic
@AfterClass
fun tearDown() {
webServer.shutdown()
}
}
@Test
fun `api gets correct number of items`() = runBlocking {
val posts = apiClient.getHottestPosts(1)
assertEquals(25, posts.size)
}
@Test
fun `no moderator posts in test data`() = runBlocking {
val posts = apiClient.getHottestPosts(1)
val moderatorPosts = posts.asSequence()
.filter { it.submitter_user.isModerator }
.toSet()
assertTrue(moderatorPosts.isEmpty())
}
@Test
fun `posts with no urls`() = runBlocking {
val posts = apiClient.getHottestPosts(1)
val commentsOnlyPosts = posts.asSequence()
.filter { it.url.isEmpty() }
.toSet()
assertEquals(2, commentsOnlyPosts.size)
}
}

View file

@ -0,0 +1,12 @@
package dev.msfjarvis.lobsters.util
import java.io.File
object TestUtils {
fun getJson(path: String): String {
// Load the JSON response
val uri = javaClass.classLoader.getResource(path)
val file = File(uri.path)
return String(file.readBytes())
}
}

File diff suppressed because one or more lines are too long