<file_sep>package com.subhag.api

import com.subhag.api.services.newsapp.NewsApiClient
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Test

class NewsApiTest {

    private val newsApi = NewsApiClient().newsApi

    @Test
    fun `Test GET top headlines from News API`() {
        runBlocking {
            val articlesResponse = newsApi.getTopHeadlinesFromAllSources()
            assertEquals(articlesResponse.isSuccessful, true)
            assertNotEquals(0, articlesResponse.body()?.articles?.size)
        }
    }

    @Test
    fun `Test GET search results given a query`() {
        runBlocking {
            val articlesResponse = newsApi.getAllArticles("<NAME>")
            assertEquals(articlesResponse.isSuccessful, true)
            assertNotEquals(0, articlesResponse.body()?.articles?.size)
        }
    }

    companion object {

        private const val STATUS_OK = "ok"

    }

}<file_sep>rootProject.name = "InShortsClone"
include ':app'
include ':api'
<file_sep>package com.subhag.api.models.responses

import com.subhag.api.models.entities.Article

data class ArticlesResponse(
    val articles: List<Article>,
    val status: String,
    val totalResults: Int
)<file_sep>package com.subhag.api.services.harperdb

import com.subhag.api.models.dto.UserDTO

class SQLHelper {

    companion object {

        fun getSQLCommandForGetUser(email: String): HarperDbSqlModel {
            return HarperDbSqlModel("SELECT * FROM taskify.user WHERE email = '${email}' LIMIT 1")
        }

        fun getSQLCommandForStoringUser(userDTO: UserDTO): HarperDbSqlModel {
            return HarperDbSqlModel(
                "INSERT INTO taskify.user (username,email, profile_img) "
                        + "VALUE ('${userDTO.username}','${userDTO.email}','${userDTO.profile_img}')"
            )
        }

    }
}<file_sep>package com.subhag.api.services.harperdb

import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

class HarperDbUserApiClient {

    private val retrofit = Retrofit
        .Builder()
        .baseUrl(HarperDbUserApi.BASE_URL)
        .addConverterFactory(MoshiConverterFactory.create())
        .build()

    val harperUserApi: HarperDbUserApi = retrofit.create(HarperDbUserApi::class.java)

}<file_sep>package com.subhag.api.models.entities

data class UserEntity(
    val username: String = "",
    val email: String = "",
    val profileImage: String = "",
    val hasCustomImage:Boolean = false
)
<file_sep>package com.subhag.api.services.harperdb

import com.subhag.api.BASIC_AUTH
import com.subhag.api.models.dto.UserDTO
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Header
import retrofit2.http.POST

interface HarperDbUserApi {

    @POST("/")
    suspend fun persistUserOnBackend(
        @Body body: HarperDbSqlModel,
        @Header("Authorization") header: String = BASIC_AUTH,
    ): Response<Any>

    @POST("/")
    suspend fun getUsers(
        @Body sqlModel: HarperDbSqlModel,
        @Header("Authorization") header: String = BASIC_AUTH
    ): Response<List<UserDTO>>

    companion object {

        const val BASE_URL = "https://taskify-cloud-subhag.harperdbcloud.com"

    }

}<file_sep>package com.subhag.api.services.newsapp

import com.subhag.api.models.responses.ArticlesResponse
import com.subhag.api.models.responses.TopHeadlinesFromAllSources
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query

interface NewsApi {

    @GET("/v2/top-headlines")
    suspend fun getTopHeadlinesFromAllSources(
        @Query("category") category: String? = null,
        @Query("country") country: String? = "in",
        @Query("sources") sources: String? = null,
        @Query("q") query: String? = null,
        @Query("pagesize") pageSize: Int? = null,
        @Query("page") page: Int? = null
    ): Response<TopHeadlinesFromAllSources>

    @GET("/v2/everything")
    suspend fun getAllArticles(
        @Query("q") query: String
    ): Response<ArticlesResponse>

    companion object {

        const val BASE_URL = "https://newsapi.org"

    }

}<file_sep>package com.subhag.api.services.newsapp

import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.concurrent.TimeUnit

class NewsApiClient {

    private val authInterceptor = Interceptor { chain ->
        val request = chain.request()
        val requestBuilder = request.newBuilder()
        requestBuilder.header(HEADER_X_API_KEY, API_KEY)
        chain.proceed(requestBuilder.build())
    }

    private val okHttpBuilder = OkHttpClient.Builder()
        .readTimeout(5, TimeUnit.SECONDS)
        .callTimeout(2, TimeUnit.SECONDS)

    private val okHttpClient = okHttpBuilder
        .addInterceptor(authInterceptor)
        .build()

    private val retrofit = Retrofit
        .Builder()
        .client(okHttpClient)
        .baseUrl(NewsApi.BASE_URL)
        .addConverterFactory(MoshiConverterFactory.create())
        .build()


    val newsApi: NewsApi = retrofit.create(NewsApi::class.java)

    companion object {

        private const val HEADER_X_API_KEY = "x-api-key"
        private const val API_KEY = "<KEY>"

    }

}<file_sep>package com.subhag.api.models.responses

import com.subhag.api.models.entities.Article
import com.subhag.api.models.entities.Source

data class TopHeadlinesFromAllSources(
    val sources: List<Source>,
    val status: String,
    val articles: List<Article>
)
<file_sep>package com.subhag.inshortsclone.di

import com.subhag.api.services.harperdb.HarperDbUserApiClient
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
object AppModule {

    @Provides
    @Singleton
    fun providesHarperAuthClient(harperAuthClient: HarperDbUserApiClient) = harperAuthClient

}<file_sep>package com.subhag.api.models.dto

data class UserDTO(
    val username: String = "",
    val email:String = "",
    val profile_img:String = ""
)
<file_sep>package com.subhag.api

import com.subhag.api.models.dto.UserDTO
import com.subhag.api.models.mapper.UserMapper
import com.subhag.api.services.harperdb.HarperDbUserApiClient
import com.subhag.api.services.harperdb.SQLHelper
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test

class HarperDbUserApiTest {

    private val harperDbUserApi = HarperDbUserApiClient().harperUserApi
    private val userMapper = UserMapper()

    @Test
    fun `Test GET UserInfo`() {
        runBlocking {
            val sqlCommand = SQLHelper.getSQLCommandForGetUser("<EMAIL>")
            val userResponse = harperDbUserApi.getUsers(sqlCommand)
            val user = userMapper.toDomainModel(userResponse.body()!!.first())
            assertEquals(userResponse.isSuccessful, true)
            assertEquals(user.username, "Subhag")
            assertEquals(user.email, "<EMAIL>")
        }
    }

    @Test
    fun `Test Persist User On Backend`() {
        runBlocking {
            val testUser = UserDTO("abc123", "<EMAIL>", "asdfasdf")
            val sqlCommand = SQLHelper.getSQLCommandForStoringUser(testUser)
            val addUserResponse = harperDbUserApi.persistUserOnBackend(sqlCommand)
            assertEquals(addUserResponse.isSuccessful, true)
        }
    }

}<file_sep>package com.subhag.api.models.mapper

interface Mapper <Network, Domain> {

    fun toDomainModel(network: Network): Domain

    fun toDomainList(network: List<Network>): List<Domain>

    fun toServiceModel(domain: Domain): Network

}<file_sep>package com.subhag.inshortsclone

import android.app.Application
import android.util.Log
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class NewsApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        Log.d(LOG_TAG,"")
    }

    companion object {

        var LOG_TAG: String = NewsApplication::class.java.simpleName

    }

}<file_sep>package com.subhag.api.services.harperdb

data class HarperDbSqlModel(
    val sql: String,
    val operation: String = "sql"
)
<file_sep>package com.subhag.api

const val BASIC_AUTH = "Basic <KEY>
