From 5470b069cc63c4ca43be68bca7bac3043b5e99c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20Rodrigues=20Galv=C3=A3o?= Date: Sun, 3 Mar 2024 00:51:38 -0300 Subject: [PATCH] feat: improve lib, add method getCepDataOrNull, change return type of methods and create tests --- .../emanuelgalvao/buscacep/ui/MainActivity.kt | 8 +- .../buscacep/viewmodel/MainViewModel.kt | 42 ++--- .../com/emanuelgalvao/buscacep/SearchCep.kt | 16 +- .../buscacep/callback/CepCallback.kt | 11 -- .../buscacep/callback/CepResponse.kt | 8 + .../buscacep/data/CepDataSource.kt | 51 +++-- .../buscacep/data/CepRepository.kt | 9 +- .../buscacep/manager/CepManager.kt | 11 +- .../buscacep/model/CepApiResponse.kt | 15 ++ .../emanuelgalvao/buscacep/model/CepData.kt | 14 ++ .../emanuelgalvao/buscacep/model/CepModel.kt | 12 -- .../buscacep/model/CepResponse.kt | 13 -- .../buscacep/network/ApiServices.kt | 10 +- .../buscacep/network/CepService.kt | 6 +- .../buscacep/network/RetrofitClient.kt | 30 ++- .../buscacep/utils/CepHandler.kt | 21 +-- .../buscacep/utils/CepValidator.kt | 29 +++ .../emanuelgalvao/buscacep/utils/Validator.kt | 33 ---- .../buscacep/data/CepDataSourceTest.kt | 175 +++++++++++++++++ .../buscacep/manager/CepManagerTest.kt | 177 +++++++++++++----- .../buscacep/utils/CepHandlerTest.kt | 23 +-- .../buscacep/utils/ValidatorTest.kt | 78 +------- 22 files changed, 479 insertions(+), 313 deletions(-) delete mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepCallback.kt create mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepResponse.kt create mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepApiResponse.kt create mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepData.kt delete mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepModel.kt delete mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepResponse.kt create mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepValidator.kt delete mode 100644 buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/Validator.kt create mode 100644 buscacep/src/test/java/com/emanuelgalvao/buscacep/data/CepDataSourceTest.kt diff --git a/app/src/main/java/com/emanuelgalvao/buscacep/ui/MainActivity.kt b/app/src/main/java/com/emanuelgalvao/buscacep/ui/MainActivity.kt index c0cc3dd..a544ee7 100644 --- a/app/src/main/java/com/emanuelgalvao/buscacep/ui/MainActivity.kt +++ b/app/src/main/java/com/emanuelgalvao/buscacep/ui/MainActivity.kt @@ -68,12 +68,8 @@ class MainActivity : AppCompatActivity() { showMessageDialog(getString(R.string.TITLE_SUCCESS), cepDetails) } - viewModel.error.observe(this) { errorStatus -> - showMessageDialog(getString(R.string.TITLE_ERROR), errorStatus.message) - } - - viewModel.validation.observe(this) { validationStatus -> - showMessageDialog(getString(R.string.TITLE_VALIDATION), validationStatus.message) + viewModel.error.observe(this) { message -> + showMessageDialog(getString(R.string.TITLE_ERROR), message) } } diff --git a/app/src/main/java/com/emanuelgalvao/buscacep/viewmodel/MainViewModel.kt b/app/src/main/java/com/emanuelgalvao/buscacep/viewmodel/MainViewModel.kt index 5b96dd0..85ed4a2 100644 --- a/app/src/main/java/com/emanuelgalvao/buscacep/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/emanuelgalvao/buscacep/viewmodel/MainViewModel.kt @@ -5,9 +5,8 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.emanuelgalvao.buscacep.SearchCep -import com.emanuelgalvao.buscacep.callback.CepCallback -import com.emanuelgalvao.buscacep.model.CepModel -import com.emanuelgalvao.buscacep.status.CepErrorStatus +import com.emanuelgalvao.buscacep.callback.CepResponse +import com.emanuelgalvao.buscacep.model.CepData import com.emanuelgalvao.buscacep.status.CepValidationStatus import kotlinx.coroutines.launch @@ -17,47 +16,36 @@ class MainViewModel: ViewModel() { val requesting: LiveData get() = _requesting - private val _success: MutableLiveData = MutableLiveData() - val success: LiveData + private val _success: MutableLiveData = MutableLiveData() + val success: LiveData get() = _success - private val _error: MutableLiveData = MutableLiveData() - val error: LiveData + private val _error: MutableLiveData = MutableLiveData() + val error: LiveData get() = _error - private val _validation: MutableLiveData = MutableLiveData() - val validation: LiveData - get() = _validation - fun searchCep(cep: String) { viewModelScope.launch { _requesting.postValue(true) - val callback = SearchCep.instance.getCepData(cep) - when (callback) { - is CepCallback.Success -> { - handleSuccess(callback.cepModel) - } - is CepCallback.Error -> { - handleError(callback.cepErrorStatus) + val response = SearchCep.getCepData(cep) + when (response) { + is CepResponse.Success -> { + handleSuccess(response.data) } - is CepCallback.Validation -> { - handleValidation(callback.cepValidationStatus) + is CepResponse.Error -> { + handleError(response.message) } } _requesting.postValue(false) } } - private fun handleSuccess(cepModel: CepModel) { + private fun handleSuccess(cepModel: CepData) { _success.postValue(cepModel) } - private fun handleError(cepErrorStatus: CepErrorStatus) { - _error.postValue(cepErrorStatus) - } - - private fun handleValidation(cepValidationStatus: CepValidationStatus) { - _validation.postValue(cepValidationStatus) + private fun handleError(message: String) { + _error.postValue(message) } } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/SearchCep.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/SearchCep.kt index 411b133..cb2f9c5 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/SearchCep.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/SearchCep.kt @@ -1,12 +1,13 @@ package com.emanuelgalvao.buscacep -import com.emanuelgalvao.buscacep.callback.CepCallback +import com.emanuelgalvao.buscacep.callback.CepResponse import com.emanuelgalvao.buscacep.data.CepDataSource import com.emanuelgalvao.buscacep.data.CepRepository import com.emanuelgalvao.buscacep.manager.CepManager +import com.emanuelgalvao.buscacep.model.CepData import com.emanuelgalvao.buscacep.network.ApiServices -class SearchCep private constructor() { +object SearchCep { private val cepRepository: CepRepository by lazy { CepDataSource(ApiServices.cepService) @@ -15,13 +16,12 @@ class SearchCep private constructor() { private val cepManager: CepManager by lazy { CepManager(cepRepository) } - companion object { - val instance: SearchCep by lazy { - SearchCep() - } - } - suspend fun getCepData(cep: String): CepCallback { + suspend fun getCepData(cep: String): CepResponse { return cepManager.getCepData(cep) } + + suspend fun getCepDataOrNull(cep: String): CepData? { + return cepManager.getCepDataOrNull(cep) + } } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepCallback.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepCallback.kt deleted file mode 100644 index 6338c0e..0000000 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepCallback.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.emanuelgalvao.buscacep.callback - -import com.emanuelgalvao.buscacep.model.CepModel -import com.emanuelgalvao.buscacep.status.CepErrorStatus -import com.emanuelgalvao.buscacep.status.CepValidationStatus - -sealed class CepCallback { - class Error(val cepErrorStatus: CepErrorStatus): CepCallback() - class Success(val cepModel: CepModel): CepCallback() - class Validation(val cepValidationStatus: CepValidationStatus): CepCallback() -} diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepResponse.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepResponse.kt new file mode 100644 index 0000000..3fead7b --- /dev/null +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/callback/CepResponse.kt @@ -0,0 +1,8 @@ +package com.emanuelgalvao.buscacep.callback + +import com.emanuelgalvao.buscacep.model.CepData + +sealed interface CepResponse { + class Error(val message: String): CepResponse + class Success(val data: CepData): CepResponse +} diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepDataSource.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepDataSource.kt index bf6d0da..54daea0 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepDataSource.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepDataSource.kt @@ -1,38 +1,49 @@ package com.emanuelgalvao.buscacep.data -import com.emanuelgalvao.buscacep.callback.CepCallback -import com.emanuelgalvao.buscacep.model.CepModel +import com.emanuelgalvao.buscacep.callback.CepResponse +import com.emanuelgalvao.buscacep.model.CepData import com.emanuelgalvao.buscacep.network.CepService import com.emanuelgalvao.buscacep.status.CepErrorStatus import com.emanuelgalvao.buscacep.status.CepValidationStatus import com.emanuelgalvao.buscacep.utils.CepHandler -import com.emanuelgalvao.buscacep.utils.Validator +import com.emanuelgalvao.buscacep.utils.CepValidator -internal class CepDataSource(private val cepApiService: CepService): CepRepository { +class CepDataSource(private val cepApiService: CepService): CepRepository { - override suspend fun searchCep(cep: String): CepCallback { - - val cepFormatted = CepHandler.instance.formatCepToCorrectFormat(cep) - - val validationStatus = Validator.instance.validateCep(cepFormatted) - - return if (validationStatus == CepValidationStatus.CEP_VALID) { - doSearchRequest(cepFormatted) + override suspend fun getCepData(cep: String): CepResponse { + val validationStatus = CepValidator.validate(cep) + return if (isCepValid(validationStatus)) { + doSearchRequest(cep) } else { - CepCallback.Validation(validationStatus) + CepResponse.Error(validationStatus.message) } } - private suspend fun doSearchRequest(cep: String): CepCallback { + override suspend fun getCepDataOrNull(cep: String): CepData? { + val validationStatus = CepValidator.validate(cep) + if (isCepValid(validationStatus)) { + val callback = doSearchRequest(cep) + if (callback is CepResponse.Success) { + return callback.data + } + } + return null + } + + private fun isCepValid(validationStatus: CepValidationStatus): Boolean { + return validationStatus == CepValidationStatus.CEP_VALID + } - val apiResponse = cepApiService.searchCep(cep) + private suspend fun doSearchRequest(cep: String): CepResponse { + val cepFormatted = CepHandler.formatCep(cep) + val apiResponse = cepApiService.searchCep(cepFormatted) return if (apiResponse.isSuccessful) { apiResponse.body()?.let { cepResponse -> if (cepResponse.erro) { - CepCallback.Error(CepErrorStatus.INVALID_CEP) + CepResponse.Error(CepErrorStatus.INVALID_CEP.message) } else { - val cepModel = CepModel( + val cepModel = CepData( bairro = cepResponse.bairro, cep = cepResponse.cep, complemento = cepResponse.complemento, @@ -44,11 +55,11 @@ internal class CepDataSource(private val cepApiService: CepService): CepReposito siafi = cepResponse.siafi, uf = cepResponse.uf ) - CepCallback.Success(cepModel) + CepResponse.Success(cepModel) } - } ?: CepCallback.Error(CepErrorStatus.SERVER_ERROR) + } ?: CepResponse.Error(CepErrorStatus.SERVER_ERROR.message) } else { - CepCallback.Error(CepErrorStatus.SERVER_ERROR) + CepResponse.Error(CepErrorStatus.SERVER_ERROR.message) } } } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepRepository.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepRepository.kt index ad99518..d1b1895 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepRepository.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/data/CepRepository.kt @@ -1,8 +1,11 @@ package com.emanuelgalvao.buscacep.data -import com.emanuelgalvao.buscacep.callback.CepCallback +import com.emanuelgalvao.buscacep.callback.CepResponse +import com.emanuelgalvao.buscacep.model.CepData -internal interface CepRepository { +interface CepRepository { - suspend fun searchCep(cep: String): CepCallback + suspend fun getCepData(cep: String): CepResponse + + suspend fun getCepDataOrNull(cep: String): CepData? } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/manager/CepManager.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/manager/CepManager.kt index 64b4a8a..7defee7 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/manager/CepManager.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/manager/CepManager.kt @@ -1,11 +1,16 @@ package com.emanuelgalvao.buscacep.manager -import com.emanuelgalvao.buscacep.callback.CepCallback +import com.emanuelgalvao.buscacep.callback.CepResponse import com.emanuelgalvao.buscacep.data.CepRepository +import com.emanuelgalvao.buscacep.model.CepData internal class CepManager(private val cepRepository: CepRepository) { - suspend fun getCepData(cep: String): CepCallback { - return cepRepository.searchCep(cep) + suspend fun getCepData(cep: String): CepResponse { + return cepRepository.getCepData(cep) + } + + suspend fun getCepDataOrNull(cep: String): CepData? { + return cepRepository.getCepDataOrNull(cep) } } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepApiResponse.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepApiResponse.kt new file mode 100644 index 0000000..0b0627d --- /dev/null +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepApiResponse.kt @@ -0,0 +1,15 @@ +package com.emanuelgalvao.buscacep.model + +data class CepApiResponse( + val bairro: String, + val cep: String, + val complemento: String, + val ddd: String, + val gia: String, + val ibge: String, + val localidade: String, + val logradouro: String, + val siafi: String, + val uf: String, + val erro: Boolean +) diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepData.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepData.kt new file mode 100644 index 0000000..9c7fa50 --- /dev/null +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepData.kt @@ -0,0 +1,14 @@ +package com.emanuelgalvao.buscacep.model + +data class CepData( + val bairro: String, + val cep: String, + val complemento: String, + val ddd: String, + val gia: String, + val ibge: String, + val localidade: String, + val logradouro: String, + val siafi: String, + val uf: String +) \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepModel.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepModel.kt deleted file mode 100644 index 4b75442..0000000 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.emanuelgalvao.buscacep.model - -data class CepModel(val bairro: String, - val cep: String, - val complemento: String, - val ddd: String, - val gia: String, - val ibge: String, - val localidade: String, - val logradouro: String, - val siafi: String, - val uf: String) \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepResponse.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepResponse.kt deleted file mode 100644 index 095cc44..0000000 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/model/CepResponse.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.emanuelgalvao.buscacep.model - -internal data class CepResponse(val bairro: String, - val cep: String, - val complemento: String, - val ddd: String, - val gia: String, - val ibge: String, - val localidade: String, - val logradouro: String, - val siafi: String, - val uf: String, - val erro: Boolean) diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/ApiServices.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/ApiServices.kt index 21d2b12..c5e3066 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/ApiServices.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/ApiServices.kt @@ -1,11 +1,5 @@ package com.emanuelgalvao.buscacep.network - -internal class ApiServices { - - companion object { - - val cepService: CepService = RetrofitClient.getClient().create(CepService::class.java) - - } +internal object ApiServices { + val cepService: CepService = RetrofitClient.getClient().create(CepService::class.java) } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/CepService.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/CepService.kt index f52bb50..c920871 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/CepService.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/CepService.kt @@ -1,12 +1,12 @@ package com.emanuelgalvao.buscacep.network -import com.emanuelgalvao.buscacep.model.CepResponse +import com.emanuelgalvao.buscacep.model.CepApiResponse import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path -internal interface CepService { +interface CepService { @GET("{cep}/json/") - suspend fun searchCep(@Path(value = "cep") cep: String) : Response + suspend fun searchCep(@Path(value = "cep") cep: String) : Response } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/RetrofitClient.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/RetrofitClient.kt index ab01a16..4081097 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/RetrofitClient.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/network/RetrofitClient.kt @@ -3,25 +3,21 @@ package com.emanuelgalvao.buscacep.network import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory -internal class RetrofitClient { +internal object RetrofitClient { - companion object { + private const val BASE_URL = "https://viacep.com.br/ws/" + private lateinit var client: Retrofit - private const val BASE_URL = "https://viacep.com.br/ws/" - - private lateinit var client: Retrofit - - fun getClient(): Retrofit { - if (!this::client.isInitialized) - initializeClient() - return client - } + fun getClient(): Retrofit { + if (!this::client.isInitialized) + initializeClient() + return client + } - private fun initializeClient() { - client = Retrofit.Builder() - .addConverterFactory(GsonConverterFactory.create()) - .baseUrl(BASE_URL) - .build() - } + private fun initializeClient() { + client = Retrofit.Builder() + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl(BASE_URL) + .build() } } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepHandler.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepHandler.kt index 71407c8..65963b2 100644 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepHandler.kt +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepHandler.kt @@ -1,32 +1,23 @@ package com.emanuelgalvao.buscacep.utils -internal class CepHandler private constructor() { +internal object CepHandler { - companion object { - val instance: CepHandler by lazy { - CepHandler() - } - } - - fun formatCepToCorrectFormat(cep: String): String { - var cepFormatted = cep - - cepFormatted = removeDashs(cepFormatted) + fun formatCep(cep: String): String { + var cepFormatted = removeDashs(cep) cepFormatted = removeSpaces(cepFormatted) cepFormatted = removeDots(cepFormatted) - return cepFormatted } - fun removeDashs(cep: String): String { + private fun removeDashs(cep: String): String { return cep.replace("-", "") } - fun removeSpaces(cep: String): String { + private fun removeSpaces(cep: String): String { return cep.replace(" ", "") } - fun removeDots(cep: String): String { + private fun removeDots(cep: String): String { return cep.replace(".", "") } } \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepValidator.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepValidator.kt new file mode 100644 index 0000000..ebcf115 --- /dev/null +++ b/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/CepValidator.kt @@ -0,0 +1,29 @@ +package com.emanuelgalvao.buscacep.utils + +import com.emanuelgalvao.buscacep.status.CepValidationStatus + +internal object CepValidator { + + private const val CEP_LENGTH = 8 + + fun validate(cep: String): CepValidationStatus { + val cepFormatted = CepHandler.formatCep(cep) + return when (false) { + isNotEmpty(cepFormatted) -> CepValidationStatus.CEP_EMPTY + isNotNull(cepFormatted) -> CepValidationStatus.CEP_NULL + correctLength(cepFormatted) -> CepValidationStatus.CEP_INCORRECT_LENGTH + containsOnlyNumbers(cepFormatted) -> CepValidationStatus.CEP_CONTAINS_LETTERS + else -> { + CepValidationStatus.CEP_VALID + } + } + } + + private fun isNotEmpty(cep: String): Boolean = cep.isNotEmpty() + + private fun isNotNull(cep: String?): Boolean = cep != null + + private fun correctLength(cep: String): Boolean = cep.length == CEP_LENGTH + + private fun containsOnlyNumbers(cep: String): Boolean = cep.all { it.isDigit() } +} \ No newline at end of file diff --git a/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/Validator.kt b/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/Validator.kt deleted file mode 100644 index 9d32533..0000000 --- a/buscacep/src/main/java/com/emanuelgalvao/buscacep/utils/Validator.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.emanuelgalvao.buscacep.utils - -import com.emanuelgalvao.buscacep.status.CepValidationStatus - -internal class Validator private constructor() { - - companion object { - val instance: Validator by lazy { - Validator() - } - } - - fun validateCep(cep: String): CepValidationStatus { - - return when (false) { - isNotEmpty(cep) -> CepValidationStatus.CEP_EMPTY - isNotNull(cep) -> CepValidationStatus.CEP_NULL - correctLength(cep) -> CepValidationStatus.CEP_INCORRECT_LENGTH - containsOnlyNumbers(cep) -> CepValidationStatus.CEP_CONTAINS_LETTERS - else -> { - CepValidationStatus.CEP_VALID - } - } - } - - fun isNotEmpty(cep: String): Boolean = cep.isNotEmpty() - - fun isNotNull(cep: String?): Boolean = cep != null - - fun correctLength(cep: String): Boolean = cep.length == 8 - - fun containsOnlyNumbers(cep: String): Boolean = cep.all { it.isDigit() } -} \ No newline at end of file diff --git a/buscacep/src/test/java/com/emanuelgalvao/buscacep/data/CepDataSourceTest.kt b/buscacep/src/test/java/com/emanuelgalvao/buscacep/data/CepDataSourceTest.kt new file mode 100644 index 0000000..9ef51d1 --- /dev/null +++ b/buscacep/src/test/java/com/emanuelgalvao/buscacep/data/CepDataSourceTest.kt @@ -0,0 +1,175 @@ +package com.emanuelgalvao.buscacep.data + +import com.emanuelgalvao.buscacep.callback.CepResponse +import com.emanuelgalvao.buscacep.model.CepApiResponse +import com.emanuelgalvao.buscacep.model.CepData +import com.emanuelgalvao.buscacep.network.CepService +import com.emanuelgalvao.buscacep.status.CepErrorStatus +import com.emanuelgalvao.buscacep.status.CepValidationStatus +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import okhttp3.MediaType +import okhttp3.ResponseBody +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnitRunner +import org.mockito.kotlin.whenever +import retrofit2.Response + +@RunWith(MockitoJUnitRunner::class) +@OptIn(ExperimentalCoroutinesApi::class) +class CepDataSourceTest { + + private lateinit var cepDataSource: CepDataSource + + @Mock + private lateinit var cepService: CepService + + @Before + fun setup() { + cepDataSource = CepDataSource(cepService) + } + + @Test + fun `getCepData method should return CepResponse SUCCESS when cep is valid`() = runTest { + val cep = "01001000" + whenever(cepService.searchCep(cep)) + .thenReturn(Response.success(getFakeCepApiResponse())) + + val response = cepDataSource.getCepData(cep) + + Assert.assertTrue(response is CepResponse.Success) + } + + @Test + fun `getCepData method should return CepResponse Error INVALID_CEP when cep does not exists`() = runTest { + val cep = "99999999" + whenever(cepService.searchCep(cep)) + .thenReturn(Response.success(getFakeCepApiResponse(error = true))) + + val response = cepDataSource.getCepData(cep) + val responseMessage = (response as? CepResponse.Error)?.message + + Assert.assertEquals(CepErrorStatus.INVALID_CEP.message, responseMessage) + } + + @Test + fun `getCepData method should return CepResponse Error SERVER_ERROR when cep is valid but an error occurred on server`() = runTest { + val cep = "01001000" + whenever(cepService.searchCep(cep)) + .thenReturn(Response.error(500, ResponseBody.create(MediaType.parse(""), ""))) + + val response = cepDataSource.getCepData(cep) + val responseMessage = (response as? CepResponse.Error)?.message + + Assert.assertEquals(CepErrorStatus.SERVER_ERROR.message, responseMessage) + } + + @Test + fun `getCepData method should return CepResponse Error CEP_EMPTY when cep is empty`() = runTest { + val cep = "" + + val response = cepDataSource.getCepData(cep) + val responseMessage = (response as? CepResponse.Error)?.message + + Assert.assertEquals(CepValidationStatus.CEP_EMPTY.message, responseMessage) + } + + @Test + fun `getCepData method should return CepResponse Error CEP_CONTAINS_LETTERS when cep contains letters`() = runTest { + val cep = "010010A0" + + val response = cepDataSource.getCepData(cep) + val responseMessage = (response as? CepResponse.Error)?.message + + Assert.assertEquals(CepValidationStatus.CEP_CONTAINS_LETTERS.message, responseMessage) + } + + @Test + fun `getCepData method should return CepResponse Error CEP_INCORRECT_LENGTH when cep length is different than 8`() = runTest { + val cep = "0100100" + + val response = cepDataSource.getCepData(cep) + val responseMessage = (response as? CepResponse.Error)?.message + + Assert.assertEquals(CepValidationStatus.CEP_INCORRECT_LENGTH.message, responseMessage) + } + + @Test + fun `getCepDataOrNull method should return CepData when cep is valid`() = runTest { + val cep = "01001000" + whenever(cepService.searchCep(cep)) + .thenReturn(Response.success(getFakeCepApiResponse())) + + val response = cepDataSource.getCepDataOrNull(cep) + + Assert.assertTrue(response is CepData) + } + + @Test + fun `getCepDataOrNull method should return null when cep does not exists`() = runTest { + val cep = "99999999" + whenever(cepService.searchCep(cep)) + .thenReturn(Response.success(getFakeCepApiResponse(error = true))) + + val response = cepDataSource.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep is valid but an error occurred on server`() = runTest { + val cep = "01001000" + whenever(cepService.searchCep(cep)) + .thenReturn(Response.error(500, ResponseBody.create(MediaType.parse(""), ""))) + + val response = cepDataSource.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep is empty`() = runTest { + val cep = "" + + val response = cepDataSource.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep contains letters`() = runTest { + val cep = "010010A0" + + val response = cepDataSource.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull Method should return null when cep length is different than 8`() = runTest { + val cep = "0100100" + + val response = cepDataSource.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + private fun getFakeCepApiResponse(error: Boolean = false) = + CepApiResponse( + bairro = "Sé", + cep = "01001-000", + complemento = "lado ímpar", + ddd = "11", + gia= "1004", + ibge = "3550308", + localidade = "São Paulo", + logradouro = "Praça da Sé", + siafi = "7107", + uf = "SP", + erro = error + ) +} \ No newline at end of file diff --git a/buscacep/src/test/java/com/emanuelgalvao/buscacep/manager/CepManagerTest.kt b/buscacep/src/test/java/com/emanuelgalvao/buscacep/manager/CepManagerTest.kt index 3d6401a..f457038 100644 --- a/buscacep/src/test/java/com/emanuelgalvao/buscacep/manager/CepManagerTest.kt +++ b/buscacep/src/test/java/com/emanuelgalvao/buscacep/manager/CepManagerTest.kt @@ -1,8 +1,8 @@ package com.emanuelgalvao.buscacep.manager -import com.emanuelgalvao.buscacep.callback.CepCallback +import com.emanuelgalvao.buscacep.callback.CepResponse import com.emanuelgalvao.buscacep.data.CepRepository -import com.emanuelgalvao.buscacep.model.CepModel +import com.emanuelgalvao.buscacep.model.CepData import com.emanuelgalvao.buscacep.status.CepErrorStatus import com.emanuelgalvao.buscacep.status.CepValidationStatus import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -13,6 +13,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.junit.MockitoJUnitRunner +import org.mockito.kotlin.any import org.mockito.kotlin.whenever @RunWith(MockitoJUnitRunner::class) @@ -30,93 +31,171 @@ internal class CepManagerTest { } @Test - fun `when cep is valid, the callback should return success`() = runTest { + fun `getCepData method should return CepResponse SUCCESS when cep is valid`() = runTest { val cep = "01001000" - val cepModel = CepModel( - bairro = "Sé", - cep = "01001-000", - complemento = "lado ímpar", - ddd = "11", - gia= "1004", - ibge = "3550308", - localidade = "São Paulo", - logradouro = "Praça da Sé", - siafi = "7107", - uf = "SP" - ) - whenever(cepRepository.searchCep(cep)) - .thenReturn(CepCallback.Success(cepModel)) - val callback = cepManager.getCepData(cep) + whenever(cepRepository.getCepData(any())) + .thenReturn(CepResponse.Success(getFakeCepData())) + + val response = cepManager.getCepData(cep) - Assert.assertTrue(callback is CepCallback.Success) + Assert.assertTrue(response is CepResponse.Success) } @Test - fun `when cep is valid, but an error occurred on the server, the callback should return error with status server error`() = runTest { + fun `getCepData method should return CepResponse Error SERVER_ERROR when cep is valid but an error occurred on the server`() = runTest { val cep = "01001000" - whenever(cepRepository.searchCep(cep)) - .thenReturn(CepCallback.Error(CepErrorStatus.SERVER_ERROR)) + whenever(cepRepository.getCepData(cep)) + .thenReturn(CepResponse.Error(CepErrorStatus.SERVER_ERROR.message)) - val callback = cepManager.getCepData(cep) - val errorStatus = (callback as? CepCallback.Error)?.cepErrorStatus + val response = cepManager.getCepData(cep) + val errorMessage = (response as? CepResponse.Error)?.message - Assert.assertTrue(errorStatus == CepErrorStatus.SERVER_ERROR) + Assert.assertEquals(CepErrorStatus.SERVER_ERROR.message, errorMessage) } @Test - fun `when cep is valid, but not exist, the callback should return error with status invalid cep`() = runTest { + fun `getCepData method should return CepResponse Error INVALID_CEP when cep not exist`() = runTest { val cep = "99999999" - whenever(cepRepository.searchCep(cep)) - .thenReturn(CepCallback.Error(CepErrorStatus.INVALID_CEP)) + whenever(cepRepository.getCepData(cep)) + .thenReturn(CepResponse.Error(CepErrorStatus.INVALID_CEP.message)) - val callback = cepManager.getCepData(cep) - val errorStatus = (callback as? CepCallback.Error)?.cepErrorStatus + val response = cepManager.getCepData(cep) + val errorStatus = (response as? CepResponse.Error)?.message - Assert.assertTrue(errorStatus == CepErrorStatus.INVALID_CEP) + Assert.assertEquals(CepErrorStatus.INVALID_CEP.message, errorStatus) } @Test - fun `when cep is empty, the callback should return validation with status empty`() = runTest { + fun `getCepData method should return CepResponse Error CEP_EMPTY when cep is empty`() = runTest { val cep = "" - whenever(cepRepository.searchCep(cep)) - .thenReturn(CepCallback.Validation(CepValidationStatus.CEP_EMPTY)) + whenever(cepRepository.getCepData(cep)) + .thenReturn(CepResponse.Error(CepValidationStatus.CEP_EMPTY.message)) - val callback = cepManager.getCepData(cep) - val validationStatus = (callback as? CepCallback.Validation)?.cepValidationStatus + val response = cepManager.getCepData(cep) + val errorMessage = (response as? CepResponse.Error)?.message - Assert.assertTrue(validationStatus == CepValidationStatus.CEP_EMPTY) + Assert.assertEquals(CepValidationStatus.CEP_EMPTY.message, errorMessage) } @Test - fun `when cep contains letters, the callback should return validation with status contains letters`() = runTest { + fun `getCepData method should return CepResponse Error CEP_CONTAINS_LETTERS when cep contains letters`() = runTest { val cep = "O10010A0" - whenever(cepRepository.searchCep(cep)) - .thenReturn(CepCallback.Validation(CepValidationStatus.CEP_CONTAINS_LETTERS)) + whenever(cepRepository.getCepData(cep)) + .thenReturn(CepResponse.Error(CepValidationStatus.CEP_CONTAINS_LETTERS.message)) - val callback = cepManager.getCepData(cep) - val validationStatus = (callback as? CepCallback.Validation)?.cepValidationStatus + val response = cepManager.getCepData(cep) + val errorMessage = (response as? CepResponse.Error)?.message - Assert.assertTrue(validationStatus == CepValidationStatus.CEP_CONTAINS_LETTERS) + Assert.assertEquals(CepValidationStatus.CEP_CONTAINS_LETTERS.message, errorMessage) } @Test - fun `when cep lenght is different than 8, the callback should return validation with status incorrect length`() = runTest { + fun `getCepData method should return CepResponse Error CEP_INCORRECT_LENGTH when cep length is different than 8`() = runTest { val cep = "O10010000" - whenever(cepRepository.searchCep(cep)) - .thenReturn(CepCallback.Validation(CepValidationStatus.CEP_INCORRECT_LENGTH)) + whenever(cepRepository.getCepData(cep)) + .thenReturn(CepResponse.Error(CepValidationStatus.CEP_INCORRECT_LENGTH.message)) - val callback = cepManager.getCepData(cep) - val validationStatus = (callback as? CepCallback.Validation)?.cepValidationStatus + val response = cepManager.getCepData(cep) + val errorMessage = (response as? CepResponse.Error)?.message - Assert.assertTrue(validationStatus == CepValidationStatus.CEP_INCORRECT_LENGTH) + Assert.assertEquals(CepValidationStatus.CEP_INCORRECT_LENGTH.message, errorMessage) } + + @Test + fun `getCepDataOrNull method should return CepData when cep is valid`() = runTest { + + val cep = "01001000" + + whenever(cepRepository.getCepDataOrNull(any())) + .thenReturn(getFakeCepData()) + + val response = cepManager.getCepDataOrNull(cep) + + Assert.assertTrue(response is CepData) + } + + @Test + fun `getCepDataOrNull method should return null when cep is valid but an error occurred on the server`() = runTest { + + val cep = "01001000" + + whenever(cepRepository.getCepDataOrNull(cep)) + .thenReturn(null) + + val response = cepManager.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep not exist`() = runTest { + + val cep = "99999999" + + whenever(cepRepository.getCepDataOrNull(cep)) + .thenReturn(null) + + val response = cepManager.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep is empty`() = runTest { + + val cep = "" + whenever(cepRepository.getCepDataOrNull(cep)) + .thenReturn(null) + + val response = cepManager.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep contains letters`() = runTest { + + val cep = "O10010A0" + whenever(cepRepository.getCepDataOrNull(cep)) + .thenReturn(null) + + val response = cepManager.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + @Test + fun `getCepDataOrNull method should return null when cep length is different than 8`() = runTest { + + val cep = "O10010000" + whenever(cepRepository.getCepDataOrNull(cep)) + .thenReturn(null) + + val response = cepManager.getCepDataOrNull(cep) + + Assert.assertNull(response) + } + + private fun getFakeCepData() = + CepData( + bairro = "Sé", + cep = "01001-000", + complemento = "lado ímpar", + ddd = "11", + gia= "1004", + ibge = "3550308", + localidade = "São Paulo", + logradouro = "Praça da Sé", + siafi = "7107", + uf = "SP" + ) } \ No newline at end of file diff --git a/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/CepHandlerTest.kt b/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/CepHandlerTest.kt index 5fa5605..c21a592 100644 --- a/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/CepHandlerTest.kt +++ b/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/CepHandlerTest.kt @@ -6,34 +6,27 @@ import org.junit.Test internal class CepHandlerTest { - private lateinit var cepHandler: CepHandler - - @Before - fun setup() { - cepHandler = CepHandler.instance - } - @Test - fun `when cep constains dashs, the function remove dashs should return cep without dashs`() { + fun `formatCep method should return cep without dashs`() { val cep = "01001-000" - Assert.assertEquals("01001000", cepHandler.removeDashs(cep)) + Assert.assertEquals("01001000", CepHandler.formatCep(cep)) } @Test - fun `when cep constains spaces, the function remove spaces should return cep without spaces`() { + fun `formatCep method should return cep without spaces`() { val cep = "01001 000" - Assert.assertEquals("01001000", cepHandler.removeSpaces(cep)) + Assert.assertEquals("01001000", CepHandler.formatCep(cep)) } @Test - fun `when cep constains dots, the function remove dots should return cep without dots`() { + fun `formatCep method should return cep without dots`() { val cep = "01.001.000" - Assert.assertEquals("01001000", cepHandler.removeDots(cep)) + Assert.assertEquals("01001000", CepHandler.formatCep(cep)) } @Test - fun `when cep is in incorrect format, the format cep function should return cep in correct format`() { + fun `formatCep method should return cep in correct format`() { val cep = "01.001-000 " - Assert.assertEquals("01001000", cepHandler.formatCepToCorrectFormat(cep)) + Assert.assertEquals("01001000", CepHandler.formatCep(cep)) } } \ No newline at end of file diff --git a/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/ValidatorTest.kt b/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/ValidatorTest.kt index 65f17d0..8b77215 100644 --- a/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/ValidatorTest.kt +++ b/buscacep/src/test/java/com/emanuelgalvao/buscacep/utils/ValidatorTest.kt @@ -7,89 +7,27 @@ import org.junit.Test class ValidatorTest { - private lateinit var validator: Validator - - @Before - fun setup() { - validator = Validator.instance - } - @Test - fun `when cep is empty, the not empty validation should return false`() { + fun `validate method should return CEP_EMPTY status when cep is empty`() { val cep = "" - Assert.assertFalse(validator.isNotEmpty(cep)) - } - - @Test - fun `when cep is not empty, the not empty validation should return true`() { - val cep = "01001000" - Assert.assertTrue(validator.isNotEmpty(cep)) - } - - @Test - fun `when cep is null, the not null validation should return false`() { - val cep = null - Assert.assertFalse(validator.isNotNull(cep)) + Assert.assertEquals(CepValidationStatus.CEP_EMPTY, CepValidator.validate(cep)) } @Test - fun `when cep is not null, the not null validation should return true`() { - val cep = "01001000" - Assert.assertTrue(validator.isNotNull(cep)) - } - - @Test - fun `when cep lenght is different than 8, the length validation should return false`() { + fun `validate method should return CEP_INCORRECT_LENGTH status when cep length is different than 8`() { val cep = "0100100" - Assert.assertFalse(validator.correctLength(cep)) + Assert.assertEquals(CepValidationStatus.CEP_INCORRECT_LENGTH, CepValidator.validate(cep)) } @Test - fun `when cep length is equals to 8, the length validation should return true`() { - val cep = "01001000" - Assert.assertTrue(validator.correctLength(cep)) - } - - @Test - fun `when cep contains letters, the numbers validation should return false`() { + fun `validate method should return CEP_CONTAINS_LETTERS status when cep contains letters`() { val cep = "O10010A0" - Assert.assertFalse(validator.containsOnlyNumbers(cep)) + Assert.assertEquals(CepValidationStatus.CEP_CONTAINS_LETTERS, CepValidator.validate(cep)) } @Test - fun `when cep contains symbols, the numbers validation should return false`() { - val cep = "01001-00" - Assert.assertFalse(validator.containsOnlyNumbers(cep)) - } - - @Test - fun `when cep contains only numbers, the numbers validation should return true`() { + fun `validate method should return CEP_VALID when cep is valid`() { val cep = "01001000" - Assert.assertTrue(validator.containsOnlyNumbers(cep)) - } - - @Test - fun `when cep is empty, the cep validation should return status empty`() { - val cep = "" - Assert.assertEquals(CepValidationStatus.CEP_EMPTY, validator.validateCep(cep)) - } - - @Test - fun `when cep length is different than 8, the cep validation should return status incorrect length`() { - val cep = "010010001" - Assert.assertEquals(CepValidationStatus.CEP_INCORRECT_LENGTH, validator.validateCep(cep)) + Assert.assertEquals(CepValidationStatus.CEP_VALID, CepValidator.validate(cep)) } - - @Test - fun `when cep contains letters, the cep validation should return status contains letters`() { - val cep = "0100100A" - Assert.assertEquals(CepValidationStatus.CEP_CONTAINS_LETTERS, validator.validateCep(cep)) - } - - @Test - fun `when cep is valid, the cep validation should return status valid`() { - val cep = "01001000" - Assert.assertEquals(CepValidationStatus.CEP_VALID, validator.validateCep(cep)) - } - } \ No newline at end of file