diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9d1492d90f5c..2a2912f8e04b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -74,7 +74,8 @@
+ android:authorities="${applicationId}.utils.SearchSuggestionProvider"
+ android:exported="false" />
@@ -109,6 +111,7 @@
@@ -136,6 +139,7 @@
android:name=".features.product.view.ProductViewActivity"
android:launchMode="singleTop"
android:parentActivityName=".features.MainActivity"
+ android:exported="true"
android:windowSoftInputMode="stateUnchanged|adjustResize">
@@ -212,6 +217,7 @@
{
- imageReturnedPosition = position
+ imageReturnedPosition = holder.bindingAdapterPosition
if (isHardwareCameraInstalled(activity)) {
EasyImage.openCamera(activity, 0)
} else {
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/edit/overview/EditOverviewFragment.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/edit/overview/EditOverviewFragment.kt
index 9b1ae73fc6cb..97a256e1e154 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/edit/overview/EditOverviewFragment.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/edit/overview/EditOverviewFragment.kt
@@ -363,7 +363,7 @@ class EditOverviewFragment : ProductEditFragment() {
binding.btnEditImgFront.visibility = View.INVISIBLE
picasso
.load(imageFrontUrl)
- .resize(requireContext().dpsToPixel(50).toInt(), requireContext().dpsToPixel(50).toInt())
+ .resize(requireContext().dpsToPixel(50), requireContext().dpsToPixel(50))
.centerInside()
.into(binding.imgFront, object : Callback {
override fun onSuccess() = frontImageLoaded()
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/photos/ProductPhotosFragment.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/photos/ProductPhotosFragment.kt
index 8c07ab1b628a..08a17facbe54 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/photos/ProductPhotosFragment.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/photos/ProductPhotosFragment.kt
@@ -22,7 +22,6 @@ import javax.inject.Inject
/**
* @author prajwalm
- * @see R.layout.fragment_product_photos
*/
@AndroidEntryPoint
class ProductPhotosFragment : BaseFragment() {
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/images/ImageNameJsonParser.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/images/ImageNameJsonParser.kt
index 355440d5980b..d0d2f3c7e02b 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/images/ImageNameJsonParser.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/images/ImageNameJsonParser.kt
@@ -3,7 +3,7 @@ package openfoodfacts.github.scrachx.openfood.images
import com.fasterxml.jackson.databind.JsonNode
/**
- * @param this@extractImagesNameSortedByUploadTimeDesc json representing images entries given by api/v0/product/XXXX.json?fields=images
+ * @receiver json representing images entries given by api/v0/product/XXXX.json?fields=images
*/
internal fun JsonNode.extractImagesNameSortedByUploadTimeDesc(): List {
// a json object referring to images
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/OpenFoodAPIClient.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/OpenFoodAPIClient.kt
index 31d3ddd8fbfb..6295d5576dda 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/OpenFoodAPIClient.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/OpenFoodAPIClient.kt
@@ -63,7 +63,7 @@ class OpenFoodAPIClient @Inject constructor(
): ProductState {
sentryAnalytics.setBarcode(barcode)
return withContext(IO) {
- rawApi.getProductByBarcode(barcode, fields, localeManager.getLanguage(), getUserAgent(userAgent)).await()
+ rawApi.getProductByBarcode(barcode, fields, localeManager.getLanguage(), getUserAgent(userAgent))
}
}
@@ -120,7 +120,7 @@ class OpenFoodAPIClient @Inject constructor(
fields,
localeManager.getLanguage(),
getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)
- ).await()
+ )
}
// TODO: This is not part of the client, move it to another class (preferably a utility class)
@@ -138,7 +138,7 @@ class OpenFoodAPIClient @Inject constructor(
getAllFields(),
localeManager.getLanguage(),
getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)
- ).await()
+ )
} catch (err: Exception) {
when (err) {
is IOException -> Toast.makeText(activity, R.string.something_went_wrong, Toast.LENGTH_LONG).show()
@@ -159,7 +159,6 @@ class OpenFoodAPIClient @Inject constructor(
}
/**
- * @param barcode
* @return a list of product ingredients (can be empty)
*/
suspend fun getIngredients(product: Product) = withContext(IO) {
@@ -359,7 +358,7 @@ class OpenFoodAPIClient @Inject constructor(
fields,
localeManager.getLanguage(),
getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)
- ).await()
+ )
if (state.status == 0L) throw IOException("Could not sync history. Error with product ${state.code} ")
else {
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt
index caba9c8b943f..a4626195deeb 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/network/services/ProductsAPI.kt
@@ -46,12 +46,12 @@ interface ProductsAPI {
}
@GET("$API_P/product/{barcode}.json")
- fun getProductByBarcode(
+ suspend fun getProductByBarcode(
@Path("barcode") barcode: String,
@Query("fields") fields: String,
@Query("lc") locale: String,
@Header("User-Agent") header: String
- ): Single
+ ): ProductState
/**
* @param barcodes String of comma separated barcodes
@@ -198,46 +198,46 @@ interface ProductsAPI {
): Search
@GET("language/{language}.json")
- fun getProductsByLanguage(@Path("language") language: String): Single
+ suspend fun getProductsByLanguage(@Path("language") language: String): Search
@GET("label/{label}.json")
- fun getProductsByLabel(@Path("label") label: String): Single
+ suspend fun getProductsByLabel(@Path("label") label: String): Search
@GET("category/{category}.json")
- fun getProductsByCategory(@Path("category") category: String): Single
+ suspend fun getProductsByCategory(@Path("category") category: String): Search
@GET("state/{state}.json")
- fun getProductsByState(
+ suspend fun getProductsByState(
@Path("state") state: String,
@Query("fields") fields: String
- ): Single
+ ): Search
@GET("packaging/{packaging}.json")
- fun getProductsByPackaging(@Path("packaging") packaging: String): Single
+ suspend fun getProductsByPackaging(@Path("packaging") packaging: String): Search
@GET("brand/{brand}.json")
- fun getProductsByBrand(@Path("brand") brand: String): Single
+ suspend fun getProductsByBrand(@Path("brand") brand: String): Search
@GET("purchase-place/{purchasePlace}.json")
- fun getProductsByPurchasePlace(@Path("purchasePlace") purchasePlace: String): Single
+ suspend fun getProductsByPurchasePlace(@Path("purchasePlace") purchasePlace: String): Search
@GET("store/{store}.json")
- fun getProductsByStore(@Path("store") store: String): Single
+ suspend fun getProductsByStore(@Path("store") store: String): Search
@GET("country/{country}.json")
- fun byCountry(@Path("country") country: String): Single
+ suspend fun byCountry(@Path("country") country: String): Search
@GET("trace/{trace}.json")
- fun getProductsByTrace(@Path("trace") trace: String): Single
+ suspend fun getProductsByTrace(@Path("trace") trace: String): Search
@GET("packager-code/{packager_code}.json")
- fun getProductsByPackagerCode(@Path("packager_code") packagerCode: String): Single
+ suspend fun getProductsByPackagerCode(@Path("packager_code") packagerCode: String): Search
@GET("city/{city}.json")
- fun getProducsByCity(@Path("city") city: String): Single
+ suspend fun getProductsByCity(@Path("city") city: String): Search
@GET("nutrition-grade/{nutriscore}.json")
- fun getProductsByNutriScore(@Path("nutriscore") nutritionGrade: String): Single
+ suspend fun getProductsByNutriScore(@Path("nutriscore") nutritionGrade: String): Search
@GET("nutrient-level/{nutrient_level}.json")
fun byNutrientLevel(@Path("nutrient_level") nutrientLevel: String): Single
@@ -314,7 +314,7 @@ interface ProductsAPI {
fun getProductsByPeriodAfterOpening(@Path("PeriodAfterOpening") periodAfterOpening: String): Call
@GET("ingredient/{ingredient}.json")
- fun getProductsByIngredient(@Path("ingredient") ingredient: String): Single
+ suspend fun getProductsByIngredient(@Path("ingredient") ingredient: String): Search
/**
* This method gives a list of incomplete products
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/repositories/TaxonomiesManager.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/repositories/TaxonomiesManager.kt
index cccce19ab721..a15d6f5742bb 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/repositories/TaxonomiesManager.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/repositories/TaxonomiesManager.kt
@@ -4,6 +4,7 @@ import android.content.Context
import android.util.Log
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext
import openfoodfacts.github.scrachx.openfood.BuildConfig
import openfoodfacts.github.scrachx.openfood.utils.Utils
@@ -28,7 +29,7 @@ class TaxonomiesManager @Inject constructor(
* @return The timestamp of the last changes date of the taxonomy.json on the server
* or [TAXONOMY_NO_INTERNET] if there is no connection to the server.
*/
- private suspend fun getLastModifiedDateFromServer(taxonomy: Taxonomy) = withContext(Dispatchers.IO) {
+ private suspend fun getLastModifiedDateFromServer(taxonomy: Taxonomy) = withContext(IO) {
var lastModifiedDate: Long
val taxoUrl = URL(BuildConfig.OFWEBSITE + taxonomy.jsonUrl)
try {
@@ -85,7 +86,7 @@ class TaxonomiesManager @Inject constructor(
private suspend fun download(
taxonomy: Taxonomy,
productRepository: ProductRepository
- ) = withContext(Dispatchers.IO) {
+ ) = withContext(IO) {
val lastMod = getLastModifiedDateFromServer(taxonomy)
return@withContext if (lastMod != TAXONOMY_NO_INTERNET)
@@ -97,7 +98,7 @@ class TaxonomiesManager @Inject constructor(
taxonomy: Taxonomy,
localDownloadTime: Long,
productRepository: ProductRepository
- ) = withContext(Dispatchers.IO) {
+ ) = withContext(IO) {
val lastModRemote = getLastModifiedDateFromServer(taxonomy)
if (lastModRemote == 0L || lastModRemote > localDownloadTime)
diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt
index de6e5e6da5d1..09f438c9b9bb 100644
--- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt
+++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/PrefManager.kt
@@ -1,11 +1,12 @@
package openfoodfacts.github.scrachx.openfood.utils
import android.content.Context
+import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences
import androidx.core.content.edit
class PrefManager(context: Context) {
- private val pref: SharedPreferences = context.getSharedPreferences(PREF_NAME, PRIVATE_MODE)
+ private val pref: SharedPreferences = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE)
// First time launch
var isFirstTimeLaunch: Boolean
@@ -28,7 +29,6 @@ class PrefManager(context: Context) {
get() = pref.getLong(FIRST_TIME_LAUNCH_TIME, System.currentTimeMillis())
companion object {
- private const val PRIVATE_MODE = 0
private const val PREF_NAME = "open-facts-welcome"
private const val IS_FIRST_TIME_LAUNCH = "IsFirstTimeLaunch"
private const val FIRST_TIME_LAUNCH_TIME = "FirstTimeLaunchTime"
diff --git a/app/src/test/java/openfoodfacts/github/scrachx/openfood/models/entities/category/CategoryNameTest.kt b/app/src/test/java/openfoodfacts/github/scrachx/openfood/models/entities/category/CategoryNameTest.kt
index ea9b6f490b8e..10b270989637 100644
--- a/app/src/test/java/openfoodfacts/github/scrachx/openfood/models/entities/category/CategoryNameTest.kt
+++ b/app/src/test/java/openfoodfacts/github/scrachx/openfood/models/entities/category/CategoryNameTest.kt
@@ -28,7 +28,7 @@ class CategoryNameTest {
}
@Test
- fun getWikiDataIdWithoutQuote_returnsWholeWikiDataId(): Unit {
+ fun getWikiDataIdWithoutQuote_returnsWholeWikiDataId() {
val fakeWikiDataId = "ThisOneIncludesenButNotAQuote"
mCategoryName.wikiDataId = fakeWikiDataId
assertThat(mCategoryName.wikiDataId).isEqualTo(fakeWikiDataId)
diff --git a/app/src/testOff/java/openfoodfacts/github/scrachx/openfood/network/ProductsAPITest.kt b/app/src/testOff/java/openfoodfacts/github/scrachx/openfood/network/ProductsAPITest.kt
index 739e5f173d33..280240f0977d 100644
--- a/app/src/testOff/java/openfoodfacts/github/scrachx/openfood/network/ProductsAPITest.kt
+++ b/app/src/testOff/java/openfoodfacts/github/scrachx/openfood/network/ProductsAPITest.kt
@@ -1,18 +1,23 @@
package openfoodfacts.github.scrachx.openfood.network
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Subject.Factory
+import com.google.common.truth.Truth.assertAbout
import com.google.common.truth.Truth.assertThat
import io.reactivex.schedulers.Schedulers
+import kotlinx.coroutines.runBlocking
+import okhttp3.Credentials
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import openfoodfacts.github.scrachx.openfood.BuildConfig
-import openfoodfacts.github.scrachx.openfood.models.ProductState
import openfoodfacts.github.scrachx.openfood.models.Search
import openfoodfacts.github.scrachx.openfood.models.entities.SendProduct
+import openfoodfacts.github.scrachx.openfood.network.ProductsAPITest.SearchSubject.Companion.assertThat
import openfoodfacts.github.scrachx.openfood.network.services.ProductsAPI
import openfoodfacts.github.scrachx.openfood.utils.Utils
import openfoodfacts.github.scrachx.openfood.utils.getUserAgent
-import org.junit.Assert.fail
import org.junit.BeforeClass
import org.junit.Test
import retrofit2.Retrofit
@@ -22,167 +27,154 @@ import java.time.Duration
class ProductsAPITest {
@Test
- fun byLanguage() {
- val search = prodClient.getProductsByLanguage("italian").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by language found`() = runBlocking {
+ val search = prodClient.getProductsByLanguage("italian")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byLabel() {
- val search = prodClient.getProductsByLabel("utz-certified").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by label found`() = runBlocking {
+ val search = prodClient.getProductsByLabel("utz-certified")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byCategory() {
- val search = prodClient.getProductsByCategory("baby-foods").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by category found`() = runBlocking {
+ val search = prodClient.getProductsByCategory("baby-foods")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byState() {
+ fun `products by state found`() = runBlocking {
val fieldsToFetchFacets = "brands,product_name,image_small_url,quantity,nutrition_grades_tags"
- val search = prodClient.getProductsByState("complete", fieldsToFetchFacets).blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ val search = prodClient.getProductsByState("complete", fieldsToFetchFacets)
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byPackaging() {
- val search = prodClient.getProductsByPackaging("cardboard").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by packaging found`() = runBlocking {
+ val search = prodClient.getProductsByPackaging("cardboard")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byBrand() {
- val search = prodClient.getProductsByBrand("monoprix").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by brand found`() = runBlocking {
+ val search = prodClient.getProductsByBrand("monoprix")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byPurchasePlace() {
- val search = prodClient.getProductsByPurchasePlace("marseille-5").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by purchase place found`() = runBlocking {
+ val search = prodClient.getProductsByPurchasePlace("marseille-5")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byStore() {
- val search = prodClient.getProductsByStore("super-u").blockingGet() as Search
+ fun `products by store found`() = runBlocking {
+ val search = prodClient.getProductsByStore("super-u")
assertThat(search).isNotNull()
assertThat(search.products).isNotNull()
}
@Test
- fun byCountry() {
- val search = prodClient.byCountry("france").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotEmpty()
+ fun `products by country found`() = runBlocking {
+ val search = prodClient.byCountry("france")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byIngredient() {
- val search = prodClient.getProductsByIngredient("sucre").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotEmpty()
+ fun `products by ingredients found`() = runBlocking {
+ val search = prodClient.getProductsByIngredient("sucre")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun byTrace() {
- val search = prodClient.getProductsByTrace("eggs").blockingGet() as Search
- assertThat(search).isNotNull()
- assertThat(search.products).isNotNull()
+ fun `products by trace found`() = runBlocking {
+ val search = prodClient.getProductsByTrace("eggs")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun productByTrace_eggs_productsFound() {
- val response = prodClient.getProductsByTrace("eggs").blockingGet() as Search
- response.assertProductsFound()
+ fun `products by trace eggs found`() = runBlocking {
+ val response = prodClient.getProductsByTrace("eggs")
+ assertThat(response).hasFoundProducts()
}
@Test
- fun productByPackagerCode_emb35069c_productsFound() {
- val response = prodClient.getProductsByPackagerCode("emb-35069c").blockingGet() as Search
- response.assertProductsFound()
+ fun `product by packager code emb35069c found`() = runBlocking {
+ val search = prodClient.getProductsByPackagerCode("emb-35069c")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun productByNutritionGrade_a_productsFound() {
- val res = prodClient.getProductsByNutriScore("a").blockingGet() as Search
- res.assertProductsFound()
+ fun `product by nutriscore a found`() = runBlocking {
+ val search = prodClient.getProductsByNutriScore("a")
+ assertThat(search).hasFoundProducts()
}
@Test
- fun productByCity_Paris_noProductFound() {
- val response = prodClient.getProducsByCity("paris").blockingGet() as Search
- response.assertNoProductsFound()
+ fun `products by city paris not found`() = runBlocking {
+ val response = prodClient.getProductsByCity("paris")
+ assertThat(response).hasFoundNoProducts()
}
@Test
fun productByAdditive_e301_productsFound() {
val fieldsToFetchFacets = "brands,product_name,image_small_url,quantity,nutrition_grades_tags"
val response = prodClient.getProductsByAdditive("e301-sodium-ascorbate", fieldsToFetchFacets).blockingGet() as Search
- response.assertProductsFound()
+ assertThat(response).hasFoundProducts()
}
@Test
- fun product_notFound() {
+ fun `product not found`() = runBlocking {
val barcode = "457457457"
- prodClient.getProductByBarcode(
- barcode,
- "code",
- LC,
- getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)).subscribe({ productState ->
- assertThat(productState.status).isEqualTo(0)
- assertThat(productState.statusVerbose).isEqualTo("product not found")
- assertThat(productState.code).isEqualTo(barcode)
- }) {
- fail("Request returned error")
- it.printStackTrace()
- }
+ val state = prodClient.getProductByBarcode(
+ barcode,
+ "code",
+ LC,
+ getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)
+ )
+ assertThat(state.status).isEqualTo(0)
+ assertThat(state.statusVerbose).isEqualTo("product not found")
+ assertThat(state.code).isEqualTo(barcode)
}
@Test
- fun post_product() {
+ fun `post product`() = runBlocking {
val product = SendProduct().apply {
barcode = "1234567890"
- name = "ProductName"
- brands = "productbrand"
+ name = "test-product-name"
+ brands = "test-product-brand"
weight = "123"
weightUnit = "g"
lang = LC
}
val productDetails = mapOf(
- "lang" to product.lang,
- "product_name" to product.name,
- "brands" to product.brands,
- "quantity" to product.quantity
+ "lang" to product.lang,
+ "product_name" to product.name,
+ "brands" to product.brands,
+ "quantity" to product.quantity
)
- val body = devClientWithAuth
- .saveProduct(product.barcode, productDetails, "Automated test")
- .blockingGet() as ProductState
+ val body = devClientWithAuth.saveProduct(product.barcode, productDetails, "Automated test")
assertThat(body.status).isEqualTo(1)
assertThat(body.statusVerbose).isEqualTo("fields saved")
val fields = "product_name,brands,brands_tags,quantity"
val response = devClientWithAuth.getProductByBarcode(
- product.barcode,
- fields,
- LC,
- getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)).blockingGet() as ProductState
+ product.barcode,
+ fields,
+ LC,
+ getUserAgent(Utils.HEADER_USER_AGENT_SEARCH)
+ )
assertThat(response.product).isNotNull()
val savedProduct = response.product!!
+
assertThat(savedProduct.productName).isEqualTo(product.name)
assertThat(savedProduct.brands).isEqualTo(product.brands)
assertThat(savedProduct.brandsTags).contains(product.brands)
@@ -203,41 +195,60 @@ class ProductsAPITest {
@JvmStatic
fun setupClient() {
val httpClientWithAuth = OkHttpClient.Builder()
- .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
- .connectTimeout(Duration.ZERO)
- .readTimeout(Duration.ZERO)
- .addInterceptor {
- val origReq = it.request()
- it.proceed(origReq.newBuilder()
- .header("Authorization", "Basic b2ZmOm9mZg==")
- .header("Accept", "application/json")
- .method(origReq.method(), origReq.body()).build())
- }
- .build()
- prodClient = Retrofit.Builder()
- .baseUrl(BuildConfig.HOST)
- .client(httpClientWithAuth)
- .addConverterFactory(JacksonConverterFactory.create(jacksonObjectMapper()))
- .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
- .build()
- .create(ProductsAPI::class.java)
+ .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
+ .connectTimeout(Duration.ZERO)
+ .readTimeout(Duration.ZERO)
+ .addInterceptor {
+ val origReq = it.request()
+ it.proceed(
+ origReq.newBuilder()
+ .header("Authorization", Credentials.basic("off", "off"))
+ .header("Accept", "application/json")
+ .method(origReq.method(), origReq.body()).build()
+ )
+ }
+ .build()
+
+ prodClient = Retrofit.Builder()
+ .baseUrl(BuildConfig.HOST)
+ .client(httpClientWithAuth)
+ .addConverterFactory(JacksonConverterFactory.create(jacksonObjectMapper()))
+ .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
+ .build()
+ .create(ProductsAPI::class.java)
+
devClientWithAuth = Retrofit.Builder()
- .baseUrl(DEV_API)
- .addConverterFactory(JacksonConverterFactory.create())
- .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
- .client(httpClientWithAuth)
- .build()
- .create(ProductsAPI::class.java)
+ .baseUrl(DEV_API)
+ .addConverterFactory(JacksonConverterFactory.create())
+ .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
+ .client(httpClientWithAuth)
+ .build()
+ .create(ProductsAPI::class.java)
}
- private fun Search.assertProductsFound() {
- assertThat(count.toInt()).isGreaterThan(0)
- assertThat(products).isNotEmpty()
+ }
+
+ class SearchSubject private constructor(
+ failureMetadata: FailureMetadata,
+ private val actual: Search
+ ) : Subject(failureMetadata, actual) {
+
+ fun hasFoundProducts() {
+ check("count").that(actual.count.toInt()).isGreaterThan(0)
+ check("products").that(actual.products).isNotEmpty()
}
- private fun Search.assertNoProductsFound() {
- assertThat(count.toInt()).isEqualTo(0)
- assertThat(products).isEmpty()
+ fun hasFoundNoProducts() {
+ check("count").that(actual.count.toInt()).isEqualTo(0)
+ check("products").that(actual.products).isEmpty()
+ }
+
+ companion object {
+ private fun searches() = Factory(::SearchSubject)
+
+ fun assertThat(actual: Search): SearchSubject {
+ return assertAbout(searches()).that(actual)
+ }
}
}
}