Bug 1853299 - Part 2: Update rc non error states for reanalysis

fenix/119.0
rahulsainani 9 months ago committed by mergify[bot]
parent 9b4f4e7d1e
commit 2316c8a96d

@ -10,6 +10,7 @@ import mozilla.components.concept.engine.shopping.ProductAnalysis
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.HighlightType
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.AnalysisStatus
/**
* Maps [ProductAnalysis] to [ProductReviewState].
@ -33,12 +34,12 @@ private fun GeckoProductAnalysis.toProductReview(): ProductReviewState =
val mappedHighlights = highlights?.toHighlights()?.toSortedMap()
if (mappedGrade == null && mappedRating == null && mappedHighlights == null) {
ProductReviewState.NoAnalysisPresent
ProductReviewState.NoAnalysisPresent()
} else {
ProductReviewState.AnalysisPresent(
productId = productId!!,
reviewGrade = mappedGrade,
needsAnalysis = needsAnalysis,
analysisStatus = needsAnalysis.toAnalysisStatus(),
adjustedRating = mappedRating,
productUrl = analysisURL!!,
highlights = mappedHighlights,
@ -53,6 +54,12 @@ private fun String.toGrade(): ReviewQualityCheckState.Grade? =
null
}
private fun Boolean.toAnalysisStatus(): AnalysisStatus =
when (this) {
true -> AnalysisStatus.NEEDS_ANALYSIS
false -> AnalysisStatus.UP_TO_DATE
}
private fun Highlight.toHighlights(): Map<HighlightType, List<String>>? =
HighlightType.values()
.associateWith { highlightsForType(it) }

@ -51,6 +51,10 @@ class ReviewQualityCheckNetworkMiddleware(
store.dispatch(ReviewQualityCheckAction.UpdateProductReview(productReviewState))
}
}
ReviewQualityCheckAction.ReanalyzeProduct -> {
// Bug 1853311 - Integrate analyze and analysis_status
}
}
}
}

@ -79,6 +79,11 @@ sealed interface ReviewQualityCheckAction : Action {
*/
object RetryProductAnalysis : NetworkAction, UpdateAction
/**
* Triggered when the user triggers product re-analysis.
*/
object ReanalyzeProduct : NetworkAction, UpdateAction
/**
* Triggered when opening a link from the review quality check feature.
*/

@ -54,15 +54,16 @@ sealed interface ReviewQualityCheckState : State {
/**
* Denotes no analysis is present for the product the user is browsing.
*/
object NoAnalysisPresent : ProductReviewState
data class NoAnalysisPresent(
val isReanalyzing: Boolean = false,
) : ProductReviewState
/**
* Denotes the state where analysis of the product is fetched and present.
*
* @property productId The id of the product, e.g ASIN, SKU.
* @property reviewGrade The review grade of the product.
* @property needsAnalysis If true, the analysis is stale and that to get the fresh
* data, reanalysis is needed.
* @property analysisStatus The status of the product analysis.
* @property adjustedRating The adjusted rating taking review quality into consideration.
* @property productUrl The url of the product the user is browsing.
* @property highlights Optional highlights based on recent reviews of the product.
@ -71,7 +72,7 @@ sealed interface ReviewQualityCheckState : State {
data class AnalysisPresent(
val productId: String,
val reviewGrade: Grade?,
val needsAnalysis: Boolean,
val analysisStatus: AnalysisStatus,
val adjustedRating: Float?,
val productUrl: String,
val highlights: SortedMap<HighlightType, List<String>>?,
@ -90,6 +91,13 @@ sealed interface ReviewQualityCheckState : State {
val highlightsFadeVisible: Boolean =
highlights != null && showMoreButtonVisible &&
highlights.forCompactMode().entries.first().value.size > 1
/**
* The status of the product analysis.
*/
enum class AnalysisStatus {
NEEDS_ANALYSIS, REANALYZING, UP_TO_DATE, COMPLETED
}
}
}
}

@ -5,6 +5,7 @@
package org.mozilla.fenix.shopping.store
import mozilla.components.lib.state.Store
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.AnalysisStatus
/**
* Store for review quality check feature.
@ -76,5 +77,25 @@ private fun mapStateForUpdateAction(
it.copy(productReviewState = ReviewQualityCheckState.OptedIn.ProductReviewState.Loading)
}
}
ReviewQualityCheckAction.ReanalyzeProduct -> {
state.mapIfOptedIn {
when (it.productReviewState) {
is ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent -> {
val productReviewState =
it.productReviewState.copy(analysisStatus = AnalysisStatus.REANALYZING)
it.copy(productReviewState = productReviewState)
}
is ReviewQualityCheckState.OptedIn.ProductReviewState.NoAnalysisPresent -> {
it.copy(productReviewState = it.productReviewState.copy(isReanalyzing = true))
}
else -> {
it
}
}
}
}
}
}

@ -40,6 +40,7 @@ import org.mozilla.fenix.compose.button.SecondaryButton
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.HighlightType
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.AnalysisStatus
import org.mozilla.fenix.shopping.store.forCompactMode
import org.mozilla.fenix.theme.FirefoxTheme
@ -71,10 +72,22 @@ fun ProductAnalysis(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
if (productAnalysis.needsAnalysis) {
ReanalyzeCard(
onReanalyzeClick = onReanalyzeClick,
)
when (productAnalysis.analysisStatus) {
AnalysisStatus.NEEDS_ANALYSIS -> {
ReanalyzeCard(onReanalyzeClick = onReanalyzeClick)
}
AnalysisStatus.REANALYZING -> {
// TBD
}
AnalysisStatus.COMPLETED -> {
// TBD
}
AnalysisStatus.UP_TO_DATE -> {
// no-op
}
}
if (productAnalysis.reviewGrade != null) {
@ -367,7 +380,7 @@ private fun ProductAnalysisPreview() {
productAnalysis = AnalysisPresent(
productId = "123",
reviewGrade = ReviewQualityCheckState.Grade.B,
needsAnalysis = false,
analysisStatus = AnalysisStatus.UP_TO_DATE,
adjustedRating = 3.6f,
productUrl = "123",
highlights = sortedMapOf(

@ -56,7 +56,9 @@ fun ReviewQualityCheckBottomSheet(
onRequestDismiss()
store.dispatch(ReviewQualityCheckAction.OptOut)
},
onReanalyzeClick = {},
onReanalyzeClick = {
store.dispatch(ReviewQualityCheckAction.ReanalyzeProduct)
},
onProductRecommendationsEnabledStateChange = {
store.dispatch(ReviewQualityCheckAction.ToggleProductRecommendation)
},

@ -7,6 +7,7 @@ package org.mozilla.fenix.shopping
import mozilla.components.browser.engine.gecko.shopping.GeckoProductAnalysis
import mozilla.components.browser.engine.gecko.shopping.Highlight
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.AnalysisStatus
import java.util.SortedMap
object ProductAnalysisTestData {
@ -38,7 +39,7 @@ object ProductAnalysisTestData {
productUrl: String = "https://test.com",
reviewGrade: ReviewQualityCheckState.Grade? = ReviewQualityCheckState.Grade.A,
adjustedRating: Float? = 4.5f,
needsAnalysis: Boolean = false,
analysisStatus: AnalysisStatus = AnalysisStatus.UP_TO_DATE,
highlights: SortedMap<ReviewQualityCheckState.HighlightType, List<String>>? = null,
): ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent =
ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent(
@ -46,7 +47,7 @@ object ProductAnalysisTestData {
productUrl = productUrl,
reviewGrade = reviewGrade,
adjustedRating = adjustedRating,
needsAnalysis = needsAnalysis,
analysisStatus = analysisStatus,
highlights = highlights,
)
}

@ -11,6 +11,7 @@ import org.junit.Test
import org.mozilla.fenix.shopping.ProductAnalysisTestData
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.HighlightType
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.AnalysisStatus
class ProductAnalysisMapperTest {
@ -34,7 +35,7 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
productId = "id1",
reviewGrade = ReviewQualityCheckState.Grade.C,
needsAnalysis = false,
analysisStatus = AnalysisStatus.UP_TO_DATE,
adjustedRating = 3.4f,
productUrl = "https://example.com",
highlights = sortedMapOf(
@ -54,7 +55,7 @@ class ProductAnalysisMapperTest {
val actual = ProductAnalysisTestData.productAnalysis(
productId = "id1",
grade = "C",
needsAnalysis = false,
needsAnalysis = true,
adjustedRating = 3.4,
analysisURL = "https://example.com",
highlights = Highlight(
@ -69,7 +70,7 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
productId = "id1",
reviewGrade = ReviewQualityCheckState.Grade.C,
needsAnalysis = false,
analysisStatus = AnalysisStatus.NEEDS_ANALYSIS,
adjustedRating = 3.4f,
productUrl = "https://example.com",
highlights = sortedMapOf(
@ -95,7 +96,7 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
productId = "id1",
reviewGrade = null,
needsAnalysis = false,
analysisStatus = AnalysisStatus.UP_TO_DATE,
adjustedRating = 3.4f,
productUrl = "https://example.com",
)
@ -128,7 +129,7 @@ class ProductAnalysisMapperTest {
adjustedRating = 0.0,
highlights = null,
).toProductReviewState()
val expected = ReviewQualityCheckState.OptedIn.ProductReviewState.NoAnalysisPresent
val expected = ReviewQualityCheckState.OptedIn.ProductReviewState.NoAnalysisPresent()
assertEquals(expected, actual)
}

@ -9,7 +9,7 @@ import org.junit.Assert.assertFalse
import org.junit.Assert.assertThrows
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent
import org.mozilla.fenix.shopping.ProductAnalysisTestData
class ReviewQualityCheckStateTest {
@ -73,12 +73,9 @@ class ReviewQualityCheckStateTest {
@Test
fun `WHEN AnalysisPresent is created with grade, rating and highlights as null THEN exception is thrown`() {
assertThrows(IllegalArgumentException::class.java) {
AnalysisPresent(
productId = "",
ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
needsAnalysis = false,
adjustedRating = null,
productUrl = "",
highlights = null,
)
}
@ -87,34 +84,25 @@ class ReviewQualityCheckStateTest {
@Test
fun `WHEN AnalysisPresent is created with at least one of grade, rating and highlights as not null THEN no exception is thrown`() {
val ratingPresent = kotlin.runCatching {
AnalysisPresent(
productId = "1",
ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
needsAnalysis = false,
adjustedRating = 1.2f,
productUrl = "",
highlights = null,
)
}
val gradePresent = kotlin.runCatching {
AnalysisPresent(
productId = "2",
ProductAnalysisTestData.analysisPresent(
reviewGrade = ReviewQualityCheckState.Grade.A,
needsAnalysis = false,
adjustedRating = null,
productUrl = "",
highlights = null,
)
}
val highlightsPresent = kotlin.runCatching {
AnalysisPresent(
productId = "2",
ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
needsAnalysis = false,
adjustedRating = null,
productUrl = "",
highlights = sortedMapOf(
ReviewQualityCheckState.HighlightType.QUALITY to listOf(""),
),
@ -155,12 +143,7 @@ class ReviewQualityCheckStateTest {
"Unbeatable deals",
),
)
val analysis = AnalysisPresent(
productId = "1",
reviewGrade = ReviewQualityCheckState.Grade.A,
needsAnalysis = false,
adjustedRating = 4.2f,
productUrl = "",
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
)
@ -173,12 +156,7 @@ class ReviewQualityCheckStateTest {
val highlights = sortedMapOf(
ReviewQualityCheckState.HighlightType.PRICE to listOf("Affordable prices"),
)
val analysis = AnalysisPresent(
productId = "1",
reviewGrade = ReviewQualityCheckState.Grade.A,
needsAnalysis = false,
adjustedRating = 4.2f,
productUrl = "",
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
)
@ -194,12 +172,7 @@ class ReviewQualityCheckStateTest {
"Free shipping options",
),
)
val analysis = AnalysisPresent(
productId = "1",
reviewGrade = ReviewQualityCheckState.Grade.A,
needsAnalysis = false,
adjustedRating = 4.2f,
productUrl = "",
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
)
@ -216,12 +189,7 @@ class ReviewQualityCheckStateTest {
"Express delivery",
),
)
val analysis = AnalysisPresent(
productId = "1",
reviewGrade = ReviewQualityCheckState.Grade.A,
needsAnalysis = false,
adjustedRating = 4.2f,
productUrl = "",
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
)
@ -246,12 +214,7 @@ class ReviewQualityCheckStateTest {
"Unbeatable deals",
),
)
val analysis = AnalysisPresent(
productId = "1",
reviewGrade = ReviewQualityCheckState.Grade.A,
needsAnalysis = false,
adjustedRating = 4.2f,
productUrl = "",
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
)

Loading…
Cancel
Save