Bug 1857215 - Part 1:Integrate review checker recommendations

fenix/121.0
rahulsainani 8 months ago committed by mergify[bot]
parent 37ba9c7c6c
commit 80b698e5e4

@ -0,0 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.shopping.middleware
/**
* Converts a string to an enum value, ignoring case. If the string does not match any of the
* enum values, the default value is returned.
*/
inline fun <reified T : Enum<T>> String.asEnumOrDefault(defaultValue: T? = null): T? =
enumValues<T>().firstOrNull { it.name.equals(this, ignoreCase = true) } ?: defaultValue

@ -28,7 +28,7 @@ private fun ProductAnalysis.toProductReview(isInitialAnalysis: Boolean): Product
}
} else {
val mappedRating = adjustedRating?.toFloat()
val mappedGrade = grade?.toGrade()
val mappedGrade = grade?.asEnumOrDefault<ReviewQualityCheckState.Grade>()
val mappedHighlights = highlights?.toHighlights()?.toSortedMap()
if (mappedGrade == null && mappedRating == null && mappedHighlights == null) {
@ -49,13 +49,6 @@ private fun ProductAnalysis.toProductReview(isInitialAnalysis: Boolean): Product
}
}
private fun String.toGrade(): ReviewQualityCheckState.Grade? =
try {
ReviewQualityCheckState.Grade.valueOf(this)
} catch (e: IllegalArgumentException) {
null
}
private fun Boolean.toAnalysisStatus(): AnalysisStatus =
when (this) {
true -> AnalysisStatus.NEEDS_ANALYSIS

@ -9,6 +9,7 @@ import kotlinx.coroutines.withContext
import mozilla.components.browser.state.selector.selectedTab
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.shopping.ProductAnalysis
import mozilla.components.concept.engine.shopping.ProductRecommendation
import mozilla.components.support.base.log.logger.Logger
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
@ -43,6 +44,13 @@ interface ReviewQualityCheckService {
* Returns the selected tab url.
*/
fun selectedTabUrl(): String?
/**
* Fetches product recommendations related to the product user is browsing in the current tab.
*
* @return [ProductRecommendation] if request succeeds, null otherwise.
*/
suspend fun productRecommendation(): ProductRecommendation?
}
/**
@ -110,8 +118,25 @@ class DefaultReviewQualityCheckService(
override fun selectedTabUrl(): String? =
browserStore.state.selectedTab?.content?.url
private inline fun <reified T : Enum<T>> String.asEnumOrDefault(defaultValue: T? = null): T? =
enumValues<T>().firstOrNull { it.name.equals(this, ignoreCase = true) } ?: defaultValue
override suspend fun productRecommendation(): ProductRecommendation? =
withContext(Dispatchers.Main) {
suspendCoroutine { continuation ->
browserStore.state.selectedTab?.let { tab ->
tab.engineState.engineSession?.requestProductRecommendations(
url = tab.content.url,
onResult = {
// Return the first available recommendation since ui requires only
// one recommendation.
continuation.resume(it.firstOrNull())
},
onException = {
logger.error("Error fetching product recommendation", it)
continuation.resume(null)
},
)
}
}
}
}
/**

@ -5,6 +5,7 @@
package org.mozilla.fenix.shopping.fake
import mozilla.components.concept.engine.shopping.ProductAnalysis
import mozilla.components.concept.engine.shopping.ProductRecommendation
import org.mozilla.fenix.shopping.middleware.AnalysisStatusDto
import org.mozilla.fenix.shopping.middleware.ReviewQualityCheckService
@ -13,6 +14,7 @@ class FakeReviewQualityCheckService(
private val reanalysis: AnalysisStatusDto? = null,
private val status: AnalysisStatusDto? = null,
private val selectedTabUrl: String? = null,
private val productRecommendation: ProductRecommendation? = null,
) : ReviewQualityCheckService {
private var analysisCount = 0
@ -28,4 +30,5 @@ class FakeReviewQualityCheckService(
override suspend fun analysisStatus(): AnalysisStatusDto? = status
override fun selectedTabUrl(): String? = selectedTabUrl
override suspend fun productRecommendation(): ProductRecommendation? = productRecommendation
}

@ -0,0 +1,46 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.shopping.middleware
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
class EnumMapperTest {
private enum class DeviceType {
PHONE,
TABLET,
WEARABLE,
OTHER_TYPE,
}
@Test
fun `GIVEN an enum WHEN a string is an enum object THEN it is mapped to the enum`() {
val phone = "phone"
val tablet = "TABLET"
val wearable = "WEARABLE"
val other = "other_type"
assertEquals(DeviceType.PHONE, phone.asEnumOrDefault<DeviceType>())
assertEquals(DeviceType.TABLET, tablet.asEnumOrDefault<DeviceType>())
assertEquals(DeviceType.WEARABLE, wearable.asEnumOrDefault<DeviceType>())
assertEquals(DeviceType.OTHER_TYPE, other.asEnumOrDefault<DeviceType>())
}
@Test
fun `GIVEN an enum WHEN a string is not an enum object and not default is passed THEN null is returned`() {
val input = "car"
assertNull(input.asEnumOrDefault<DeviceType>())
}
@Test
fun `GIVEN an enum WHEN a string is not an enum object and default is passed THEN default is returned`() {
val input = "car"
assertEquals(DeviceType.OTHER_TYPE, input.asEnumOrDefault(DeviceType.OTHER_TYPE))
}
}
Loading…
Cancel
Save