mirror of
https://github.com/hmalik144/EasyCC_Master.git
synced 2026-01-31 02:41:47 +00:00
Unit tests added
Query interceptor added Unit tests created - Repository test network - Repository test storage
This commit is contained in:
@@ -2,8 +2,8 @@ package com.appttude.h_mal.easycc.mvvm.application
|
||||
|
||||
import android.app.Application
|
||||
import com.appttude.h_mal.easycc.mvvm.data.repository.RepositoryImpl
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.NetworkConnectionInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.QueryInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.interceptors.NetworkConnectionInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.interceptors.QueryInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.api.CurrencyApi
|
||||
import com.appttude.h_mal.easycc.mvvm.data.prefs.PreferenceProvider
|
||||
import com.appttude.h_mal.easycc.mvvm.ui.app.MainViewModelFactory
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.data.network.api
|
||||
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.response.ResponseObject
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.NetworkConnectionInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.QueryInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.interceptors.NetworkConnectionInterceptor
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.interceptors.QueryInterceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Response
|
||||
import retrofit2.Retrofit
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.data.network
|
||||
package com.appttude.h_mal.easycc.mvvm.data.network.interceptors
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
@@ -7,6 +7,10 @@ import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Interceptor used in [CurrencyApi] to intercept network status
|
||||
*
|
||||
*/
|
||||
class NetworkConnectionInterceptor(
|
||||
context: Context
|
||||
) : Interceptor {
|
||||
@@ -1,14 +1,18 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.data.network
|
||||
package com.appttude.h_mal.easycc.mvvm.data.network.interceptors
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import com.appttude.h_mal.easycc.BuildConfig
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
|
||||
/**
|
||||
* Interceptor used in CurrencyApi
|
||||
* Adds apiKey to query parameters
|
||||
*/
|
||||
class QueryInterceptor() : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
@@ -16,7 +20,7 @@ class QueryInterceptor() : Interceptor {
|
||||
val originalHttpUrl: HttpUrl = original.url()
|
||||
|
||||
val url = originalHttpUrl.newBuilder()
|
||||
.addQueryParameter("apikey", "a4f93cc2ff05dd772321")
|
||||
.addQueryParameter("apikey", BuildConfig.CC_API_KEY)
|
||||
.build()
|
||||
|
||||
// Add amended Url back to request
|
||||
@@ -5,76 +5,80 @@ import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.appttude.h_mal.easycc.R
|
||||
|
||||
private const val CONVERSION_ONE = "conversion_one"
|
||||
private const val CONVERSION_TWO = "conversion_two"
|
||||
private const val CONVERSION_ONE_WIDGET = "conversion_one_widget"
|
||||
private const val CONVERSION_TWO_WIDGET = "conversion_two_widget"
|
||||
/**
|
||||
* Shared prefs class used for storing conversion name values as pairs
|
||||
* Then retrieving as pairs
|
||||
*
|
||||
*/
|
||||
private const val CURRENCY_ONE = "conversion_one"
|
||||
private const val CURRENCY_TWO = "conversion_two"
|
||||
|
||||
class PreferenceProvider(
|
||||
context: Context
|
||||
) {
|
||||
class PreferenceProvider(context: Context) {
|
||||
|
||||
private val appContext = context.applicationContext
|
||||
|
||||
// Instance of Shared preferences
|
||||
private val preference: SharedPreferences
|
||||
get() = PreferenceManager.getDefaultSharedPreferences(appContext)
|
||||
|
||||
private val defaultRate: String = context.resources.getStringArray(R.array.currency_arrays)[0]
|
||||
= PreferenceManager.getDefaultSharedPreferences(appContext)
|
||||
|
||||
// Lazy declaration of default rate if no rate is retrieved from
|
||||
private val defaultRate: String by lazy {
|
||||
context.resources.getStringArray(R.array.currency_arrays)[0]
|
||||
}
|
||||
|
||||
// Save currency pairs into prefs
|
||||
fun saveConversionPair(s1: String, s2: String) {
|
||||
preference.edit().putString(
|
||||
CONVERSION_ONE,
|
||||
s1
|
||||
).putString(
|
||||
CONVERSION_TWO,
|
||||
s2
|
||||
).apply()
|
||||
preference.edit()
|
||||
.putString(CURRENCY_ONE, s1)
|
||||
.putString(CURRENCY_TWO, s2)
|
||||
.apply()
|
||||
}
|
||||
|
||||
// Retrieve Currency pairs from prefs
|
||||
// Returns Pairs
|
||||
fun getConversionPair(): Pair<String?, String?> {
|
||||
val s1 = getLastConversionOne()
|
||||
val s2 = getLastConversionTwo()
|
||||
val fromString = getConversionString(CURRENCY_ONE)
|
||||
val toString = getConversionString(CURRENCY_TWO)
|
||||
|
||||
return Pair(s1,s2)
|
||||
return Pair(fromString, toString)
|
||||
}
|
||||
|
||||
private fun getLastConversionOne(): String? {
|
||||
return preference.getString(CONVERSION_ONE, defaultRate)
|
||||
|
||||
private fun getConversionString(conversionName: String): String? {
|
||||
return preference
|
||||
.getString(conversionName, defaultRate)
|
||||
}
|
||||
|
||||
private fun getLastConversionTwo(): String? {
|
||||
return preference.getString(CONVERSION_TWO, defaultRate)
|
||||
// Save currency pairs for widget
|
||||
fun saveWidgetConversionPair(fromString: String,
|
||||
toString: String, appWidgetId: Int) {
|
||||
|
||||
preference.edit()
|
||||
.putString("${appWidgetId}_$CURRENCY_ONE", fromString)
|
||||
.putString("${appWidgetId}_$CURRENCY_TWO", toString)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun saveWidgetConversionPair(s1: String, s2: String, id: Int) {
|
||||
preference.edit().putString(
|
||||
"${id}_$CONVERSION_ONE",
|
||||
s1
|
||||
).putString(
|
||||
"${id}_$CONVERSION_TWO",
|
||||
s2
|
||||
).apply()
|
||||
// Retrieve currency pairs for widget
|
||||
fun getWidgetConversionPair(appWidgetId: Int): Pair<String?, String?> {
|
||||
val fromString = getWidgetConversionString(appWidgetId, CURRENCY_ONE)
|
||||
val toString = getWidgetConversionString(appWidgetId, CURRENCY_TWO)
|
||||
|
||||
return Pair(fromString, toString)
|
||||
}
|
||||
|
||||
fun getWidgetConversionPair(id: Int): Pair<String?, String?> {
|
||||
val s1 = getWidgetLastConversionOne(id)
|
||||
val s2 = getWidgetLastConversionTwo(id)
|
||||
|
||||
return Pair(s1, s2)
|
||||
private fun getWidgetConversionString(
|
||||
appWidgetId: Int, conversionName: String): String? {
|
||||
return preference
|
||||
.getString("${appWidgetId}_$conversionName", defaultRate)
|
||||
}
|
||||
|
||||
private fun getWidgetLastConversionOne(id: Int): String? {
|
||||
return preference.getString("${id}_$CONVERSION_ONE", defaultRate)
|
||||
}
|
||||
fun removeWidgetConversion(id: Int) {
|
||||
preference.edit()
|
||||
.remove("${id}_$CURRENCY_ONE")
|
||||
.remove("${id}_$CURRENCY_TWO")
|
||||
.apply()
|
||||
|
||||
private fun getWidgetLastConversionTwo(id: Int): String? {
|
||||
return preference.getString("${id}_$CONVERSION_TWO", defaultRate)
|
||||
}
|
||||
|
||||
fun removeWidgetConversion(id: Int){
|
||||
preference.edit().remove("${id}_$CONVERSION_ONE").apply()
|
||||
preference.edit().remove("${id}_$CONVERSION_TWO").apply()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.data.repository
|
||||
|
||||
import com.appttude.h_mal.easycc.R
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.response.ResponseObject
|
||||
import com.appttude.h_mal.easycc.mvvm.utils.convertPairsListToString
|
||||
|
||||
/**
|
||||
* Main entry point for accessing currency data.
|
||||
*/
|
||||
|
||||
interface Repository {
|
||||
|
||||
suspend fun getData(s1: String, s2: String): ResponseObject
|
||||
suspend fun getData(fromCurrency: String, toCurrency: String): ResponseObject
|
||||
|
||||
fun getConversionPair(): Pair<String?, String?>
|
||||
|
||||
fun setConversionPair(s1: String, s2: String)
|
||||
fun setConversionPair(fromCurrency: String, toCurrency: String)
|
||||
|
||||
fun getArrayList(): Array<String>
|
||||
|
||||
fun getWidgetConversionPairs(id: Int): Pair<String?, String?>
|
||||
fun getWidgetConversionPairs(appWidgetId: Int): Pair<String?, String?>
|
||||
|
||||
fun setWidgetConversionPairs(s1: String, s2: String, id: Int)
|
||||
fun setWidgetConversionPairs(fromCurrency: String, toCurrency: String, appWidgetId: Int)
|
||||
|
||||
fun removeWidgetConversionPairs(id: Int)
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.data.repository
|
||||
|
||||
import android.content.Context
|
||||
import com.appttude.h_mal.easycc.BuildConfig
|
||||
import com.appttude.h_mal.easycc.mvvm.data.prefs.PreferenceProvider
|
||||
import com.appttude.h_mal.easycc.R
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.response.ResponseObject
|
||||
@@ -9,7 +8,9 @@ import com.appttude.h_mal.easycc.mvvm.data.network.SafeApiRequest
|
||||
import com.appttude.h_mal.easycc.mvvm.data.network.api.CurrencyApi
|
||||
import com.appttude.h_mal.easycc.mvvm.utils.convertPairsListToString
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of [Repository]. Single entry point for managing currency' data.
|
||||
*/
|
||||
class RepositoryImpl (
|
||||
private val api: CurrencyApi,
|
||||
private val prefs: PreferenceProvider,
|
||||
@@ -18,29 +19,31 @@ class RepositoryImpl (
|
||||
|
||||
private val appContext = context.applicationContext
|
||||
|
||||
override suspend fun getData(s1: String, s2: String
|
||||
override suspend fun getData(fromCurrency: String, toCurrency: String
|
||||
): ResponseObject{
|
||||
val currencyPair = convertPairsListToString(s1, s2)
|
||||
return responseUnwrap{
|
||||
api.getCurrencyRate(currencyPair)}
|
||||
// Set currency pairs as correct string for api query eg. AUD_GBP
|
||||
val currencyPair = convertPairsListToString(fromCurrency, toCurrency)
|
||||
return responseUnwrap{ api.getCurrencyRate(currencyPair)}
|
||||
}
|
||||
|
||||
override fun getConversionPair(): Pair<String?, String?> {
|
||||
return prefs.getConversionPair()
|
||||
}
|
||||
|
||||
override fun setConversionPair(s1: String, s2: String){
|
||||
prefs.saveConversionPair(s1, s2)
|
||||
override fun setConversionPair(fromCurrency: String, toCurrency: String){
|
||||
prefs.saveConversionPair(fromCurrency, toCurrency)
|
||||
}
|
||||
|
||||
override fun getArrayList(): Array<String> =
|
||||
appContext.resources.getStringArray(R.array.currency_arrays)
|
||||
|
||||
override fun getWidgetConversionPairs(id: Int): Pair<String?, String?> =
|
||||
prefs.getWidgetConversionPair(id)
|
||||
override fun getWidgetConversionPairs(appWidgetId: Int): Pair<String?, String?> =
|
||||
prefs.getWidgetConversionPair(appWidgetId)
|
||||
|
||||
override fun setWidgetConversionPairs(s1: String, s2: String, id: Int) =
|
||||
prefs.saveWidgetConversionPair(s1, s2, id)
|
||||
override fun setWidgetConversionPairs(fromCurrency: String,
|
||||
toCurrency: String, appWidgetId: Int) {
|
||||
return prefs.saveWidgetConversionPair(fromCurrency, toCurrency, appWidgetId)
|
||||
}
|
||||
|
||||
override fun removeWidgetConversionPairs(id: Int) =
|
||||
prefs.removeWidgetConversion(id)
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.widget.EditText
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.appttude.h_mal.easycc.mvvm.data.repository.Repository
|
||||
import com.appttude.h_mal.easycc.mvvm.utils.toTwoDp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -26,9 +27,7 @@ class MainViewModel(
|
||||
var rateListener: RateListener? = null
|
||||
|
||||
//operation results livedata based on outcome of operation
|
||||
val operationSuccess = MutableLiveData<Boolean>()
|
||||
val operationFailed = MutableLiveData<String>()
|
||||
|
||||
val operationSuccess = MutableLiveData<Pair<Boolean, String>>()
|
||||
val currencyRate = MutableLiveData<Double>()
|
||||
|
||||
private var conversionRate: Double = 0.00
|
||||
@@ -71,11 +70,6 @@ class MainViewModel(
|
||||
editText.setText(newTopVal.toBigDecimal().toPlainString())
|
||||
}
|
||||
|
||||
private fun Double.toTwoDp() = run {
|
||||
val df = DecimalFormat("#.##")
|
||||
java.lang.Double.valueOf(df.format(this))
|
||||
}
|
||||
|
||||
fun start(){
|
||||
if (rateIdFrom != rateIdTo){
|
||||
getExchangeRate()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.utils
|
||||
|
||||
import java.text.DecimalFormat
|
||||
|
||||
fun transformIntToArray(int: Int): IntArray{
|
||||
return intArrayOf(int)
|
||||
}
|
||||
@@ -12,4 +14,9 @@ fun String.trimToThree(): String{
|
||||
}
|
||||
|
||||
fun convertPairsListToString(s1: String, s2: String): String =
|
||||
"${s1.trimToThree()}_${s2.trimToThree()}"
|
||||
"${s1.trimToThree()}_${s2.trimToThree()}"
|
||||
|
||||
fun Double.toTwoDp() = run {
|
||||
val df = DecimalFormat("#.##")
|
||||
java.lang.Double.valueOf(df.format(this))
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class RepositoryStorageTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndRetrieveCredentials_PositiveResponse() {
|
||||
fun saveAndRetrieveWidgetPairs_PositiveResponse() {
|
||||
//GIVEN
|
||||
val s1 = "AUD - Australian Dollar"
|
||||
val s2 = "GBP - British Pound"
|
||||
|
||||
Reference in New Issue
Block a user