Bug 1863922 - Move highlights expanded state to ReviewQualityCheckState

fenix/121.0
rahulsainani 7 months ago committed by mergify[bot]
parent 9ea3a716eb
commit fc38da6d17

@ -10,6 +10,7 @@ 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
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.HighlightsInfo
/**
* Maps [ProductAnalysis] to [ProductReviewState].
@ -44,7 +45,7 @@ private fun ProductAnalysis.toProductReview(isInitialAnalysis: Boolean): Product
analysisStatus = needsAnalysis.toAnalysisStatus(),
adjustedRating = mappedRating,
productUrl = analysisURL!!,
highlights = mappedHighlights,
highlightsInfo = mappedHighlights?.let { HighlightsInfo(it) },
)
}
}

@ -78,8 +78,11 @@ class ReviewQualityCheckTelemetryMiddleware : ReviewQualityCheckMiddleware {
Shopping.surfaceNotNowClicked.record()
}
is ReviewQualityCheckAction.ShowMoreRecentReviewsClicked -> {
Shopping.surfaceShowMoreRecentReviewsClicked.record()
is ReviewQualityCheckAction.ExpandCollapseHighlights -> {
val state = store.state
if (state is ReviewQualityCheckState.OptedIn && state.isHighlightsExpanded) {
Shopping.surfaceShowMoreRecentReviewsClicked.record()
}
}
is ReviewQualityCheckAction.ExpandCollapseSettings -> {

@ -178,7 +178,7 @@ sealed interface ReviewQualityCheckAction : Action {
/**
* Triggered when the user expands the recent reviews card.
*/
object ShowMoreRecentReviewsClicked : TelemetryAction
object ExpandCollapseHighlights : TelemetryAction, UpdateAction
/**
* Triggered when the user expands or collapses the settings card.

@ -6,8 +6,6 @@ package org.mozilla.fenix.shopping.store
import androidx.compose.runtime.Immutable
import mozilla.components.lib.state.State
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.HighlightType
import java.util.SortedMap
private const val NUMBER_OF_HIGHLIGHTS_FOR_COMPACT_MODE = 2
@ -46,6 +44,7 @@ sealed interface ReviewQualityCheckState : State {
* @property productVendor The vendor of the product.
* @property isSettingsExpanded Whether or not the settings card is expanded.
* @property isInfoExpanded Whether or not the info card is expanded.
* @property isHighlightsExpanded Whether or not the highlights card is expanded.
*/
data class OptedIn(
val productReviewState: ProductReviewState = ProductReviewState.Loading,
@ -53,6 +52,7 @@ sealed interface ReviewQualityCheckState : State {
val productVendor: ProductVendor,
val isSettingsExpanded: Boolean = false,
val isInfoExpanded: Boolean = false,
val isHighlightsExpanded: Boolean = false,
) : ReviewQualityCheckState {
/**
@ -104,32 +104,51 @@ sealed interface ReviewQualityCheckState : State {
* @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.
* @property highlightsInfo Optional highlights based on recent reviews of the product.
* @property recommendedProductState The state of the recommended product.
*/
@Immutable
data class AnalysisPresent(
val productId: String,
val reviewGrade: Grade?,
val analysisStatus: AnalysisStatus,
val adjustedRating: Float?,
val productUrl: String,
val highlights: SortedMap<HighlightType, List<String>>?,
val highlightsInfo: HighlightsInfo?,
val recommendedProductState: RecommendedProductState = RecommendedProductState.Initial,
) : ProductReviewState {
init {
require(!(highlights == null && reviewGrade == null && adjustedRating == null)) {
require(!(highlightsInfo == null && reviewGrade == null && adjustedRating == null)) {
"AnalysisPresent state should only be created when at least one of " +
"reviewGrade, adjustedRating or highlights is not null"
}
}
val showMoreButtonVisible: Boolean =
highlights != null && highlights != highlights.forCompactMode()
val highlightsFadeVisible: Boolean =
highlights != null && showMoreButtonVisible &&
highlights.forCompactMode().entries.first().value.size > 1
/**
* Container for highlights and it's derived properties
*
* @property highlights highlights based on recent reviews of the product.
*/
@Immutable
data class HighlightsInfo(
val highlights: Map<HighlightType, List<String>>,
) {
/**
* Highlights to display in compact mode that contains first 2 highlights of the
* first highlight type.
*/
val highlightsForCompactMode: Map<HighlightType, List<String>> =
highlights.entries.first().let { entry ->
mapOf(
entry.key to entry.value.take(NUMBER_OF_HIGHLIGHTS_FOR_COMPACT_MODE),
)
}
val showMoreButtonVisible: Boolean = highlights != highlightsForCompactMode
val highlightsFadeVisible: Boolean =
showMoreButtonVisible && highlightsForCompactMode.entries.first().value.size > 1
}
/**
* The status of the product analysis.
@ -201,12 +220,3 @@ sealed interface ReviewQualityCheckState : State {
this
}
}
/**
* Highlights to display in compact mode that contains first 2 highlights of the first
* highlight type.
*/
fun Map<HighlightType, List<String>>.forCompactMode(): Map<HighlightType, List<String>> =
entries.first().let { entry ->
mapOf(entry.key to entry.value.take(NUMBER_OF_HIGHLIGHTS_FOR_COMPACT_MODE))
}

@ -75,6 +75,12 @@ private fun mapStateForUpdateAction(
}
}
ReviewQualityCheckAction.ExpandCollapseHighlights -> {
state.mapIfOptedIn {
it.copy(isHighlightsExpanded = !it.isHighlightsExpanded)
}
}
ReviewQualityCheckAction.ToggleProductRecommendation -> {
if (state is ReviewQualityCheckState.OptedIn && state.productRecommendationsPreference != null) {
if (state.productReviewState is ProductReviewState.AnalysisPresent &&

@ -49,10 +49,9 @@ 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.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.HighlightsInfo
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.RecommendedProductState
import org.mozilla.fenix.shopping.store.forCompactMode
import org.mozilla.fenix.theme.FirefoxTheme
import java.util.SortedMap
private val combinedParentHorizontalPadding = 32.dp
private val productRecommendationImageSize = 60.dp
@ -68,13 +67,14 @@ private const val PRODUCT_RECOMMENDATION_IMPRESSION_THRESHOLD = 0.5f
* @param productVendor The vendor of the product.
* @param isSettingsExpanded Whether or not the settings card is expanded.
* @param isInfoExpanded Whether or not the info card is expanded.
* @param isHighlightsExpanded Whether or not the highlights card is expanded.
* @param onOptOutClick Invoked when the user opts out of the review quality check feature.
* @param onReanalyzeClick Invoked when the user clicks to re-analyze a product.
* @param onProductRecommendationsEnabledStateChange Invoked when the user changes the product
* recommendations toggle state.
* @param onReviewGradeLearnMoreClick Invoked when the user clicks to learn more about review grades.
* @param onFooterLinkClick Invoked when the user clicks on the footer link.
* @param onShowMoreRecentReviewsClicked Invoked when the user clicks to show more recent reviews.
* @param onHighlightsExpandToggleClick Invoked when the user clicks to show more recent reviews.
* @param onSettingsExpandToggleClick Invoked when the user expands or collapses the settings card.
* @param onInfoExpandToggleClick Invoked when the user expands or collapses the info card.
* @param onRecommendedProductClick Invoked when the user clicks on the product recommendation.
@ -89,12 +89,13 @@ fun ProductAnalysis(
productVendor: ReviewQualityCheckState.ProductVendor,
isSettingsExpanded: Boolean,
isInfoExpanded: Boolean,
isHighlightsExpanded: Boolean,
onOptOutClick: () -> Unit,
onReanalyzeClick: () -> Unit,
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
onReviewGradeLearnMoreClick: () -> Unit,
onFooterLinkClick: () -> Unit,
onShowMoreRecentReviewsClicked: () -> Unit,
onHighlightsExpandToggleClick: () -> Unit,
onSettingsExpandToggleClick: () -> Unit,
onInfoExpandToggleClick: () -> Unit,
onRecommendedProductClick: (aid: String, url: String) -> Unit,
@ -133,12 +134,11 @@ fun ProductAnalysis(
)
}
if (productAnalysis.highlights != null) {
if (productAnalysis.highlightsInfo != null) {
HighlightsCard(
highlights = productAnalysis.highlights,
highlightsFadeVisible = productAnalysis.highlightsFadeVisible,
showMoreButtonVisible = productAnalysis.showMoreButtonVisible,
onShowMoreRecentReviewsClicked = onShowMoreRecentReviewsClicked,
highlightsInfo = productAnalysis.highlightsInfo,
onHighlightsExpandToggleClick = onHighlightsExpandToggleClick,
isExpanded = isHighlightsExpanded,
modifier = Modifier.fillMaxWidth(),
)
}
@ -254,20 +254,17 @@ private fun AdjustedProductRatingCard(
@Suppress("LongMethod")
@Composable
private fun HighlightsCard(
highlights: Map<HighlightType, List<String>>,
highlightsFadeVisible: Boolean,
showMoreButtonVisible: Boolean,
onShowMoreRecentReviewsClicked: () -> Unit,
highlightsInfo: HighlightsInfo,
isExpanded: Boolean,
onHighlightsExpandToggleClick: () -> Unit,
modifier: Modifier = Modifier,
) {
ReviewQualityCheckCard(modifier = modifier) {
var isExpanded by remember { mutableStateOf(false) }
val highlightsForCompactMode = remember(highlights) { highlights.forCompactMode() }
val highlightsToDisplay = remember(isExpanded, highlights) {
val highlightsToDisplay = remember(isExpanded, highlightsInfo.highlights) {
if (isExpanded) {
highlights
highlightsInfo.highlights
} else {
highlightsForCompactMode
highlightsInfo.highlightsForCompactMode
}
}
@ -309,7 +306,7 @@ private fun HighlightsCard(
targetState = isExpanded,
label = "HighlightsCard-Crossfade",
) { expanded ->
if (expanded.not() && highlightsFadeVisible) {
if (expanded.not() && highlightsInfo.highlightsFadeVisible) {
Spacer(
modifier = Modifier
.height(32.dp)
@ -327,7 +324,7 @@ private fun HighlightsCard(
}
}
if (showMoreButtonVisible) {
if (highlightsInfo.showMoreButtonVisible) {
Spacer(modifier = Modifier.height(8.dp))
Divider(modifier = Modifier.extendWidthToParentBorder())
@ -340,12 +337,7 @@ private fun HighlightsCard(
} else {
stringResource(R.string.review_quality_check_highlights_show_more)
},
onClick = {
if (!isExpanded) {
onShowMoreRecentReviewsClicked()
}
isExpanded = isExpanded.not()
},
onClick = onHighlightsExpandToggleClick,
)
}
}
@ -517,31 +509,33 @@ private class ProductAnalysisPreviewModel(
analysisStatus: AnalysisStatus = AnalysisStatus.UP_TO_DATE,
adjustedRating: Float? = 3.6f,
productUrl: String = "",
highlights: SortedMap<HighlightType, List<String>>? = sortedMapOf(
HighlightType.QUALITY to listOf(
"High quality",
"Excellent craftsmanship",
"Superior materials",
),
HighlightType.PRICE to listOf(
"Affordable prices",
"Great value for money",
"Discounted offers",
),
HighlightType.SHIPPING to listOf(
"Fast and reliable shipping",
"Free shipping options",
"Express delivery",
),
HighlightType.PACKAGING_AND_APPEARANCE to listOf(
"Elegant packaging",
"Attractive appearance",
"Beautiful design",
),
HighlightType.COMPETITIVENESS to listOf(
"Competitive pricing",
"Strong market presence",
"Unbeatable deals",
highlightsInfo: HighlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf(
"High quality",
"Excellent craftsmanship",
"Superior materials",
),
HighlightType.PRICE to listOf(
"Affordable prices",
"Great value for money",
"Discounted offers",
),
HighlightType.SHIPPING to listOf(
"Fast and reliable shipping",
"Free shipping options",
"Express delivery",
),
HighlightType.PACKAGING_AND_APPEARANCE to listOf(
"Elegant packaging",
"Attractive appearance",
"Beautiful design",
),
HighlightType.COMPETITIVENESS to listOf(
"Competitive pricing",
"Strong market presence",
"Unbeatable deals",
),
),
),
recommendedProductState: RecommendedProductState = RecommendedProductState.Initial,
@ -554,7 +548,7 @@ private class ProductAnalysisPreviewModel(
analysisStatus = analysisStatus,
adjustedRating = adjustedRating,
productUrl = productUrl,
highlights = highlights,
highlightsInfo = highlightsInfo,
recommendedProductState = recommendedProductState,
),
productVendor = productVendor,
@ -576,10 +570,12 @@ private class ProductAnalysisPreviewModelParameterProvider :
reviewGrade = null,
),
ProductAnalysisPreviewModel(
highlights = sortedMapOf(
HighlightType.QUALITY to listOf(
"High quality",
"Excellent craftsmanship",
highlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf(
"High quality",
"Excellent craftsmanship",
),
),
),
),
@ -613,6 +609,7 @@ private fun ProductAnalysisPreview(
var productRecommendationsEnabled by remember { mutableStateOf(model.productRecommendationsEnabled) }
var isSettingsExpanded by remember { mutableStateOf(false) }
var isInfoExpanded by remember { mutableStateOf(false) }
var isHighlightsExpanded by remember { mutableStateOf(false) }
ProductAnalysis(
productRecommendationsEnabled = productRecommendationsEnabled,
@ -620,6 +617,7 @@ private fun ProductAnalysisPreview(
productVendor = model.productVendor,
isSettingsExpanded = isSettingsExpanded,
isInfoExpanded = isInfoExpanded,
isHighlightsExpanded = isHighlightsExpanded,
onOptOutClick = {},
onReanalyzeClick = {},
onProductRecommendationsEnabledStateChange = {
@ -627,7 +625,7 @@ private fun ProductAnalysisPreview(
},
onReviewGradeLearnMoreClick = {},
onFooterLinkClick = {},
onShowMoreRecentReviewsClicked = {},
onHighlightsExpandToggleClick = { isHighlightsExpanded = !isHighlightsExpanded },
onSettingsExpandToggleClick = { isSettingsExpanded = !isSettingsExpanded },
onInfoExpandToggleClick = { isInfoExpanded = !isInfoExpanded },
onRecommendedProductClick = { _, _ -> },

@ -102,8 +102,8 @@ fun ReviewQualityCheckBottomSheet(
onNoAnalysisPresent = {
store.dispatch(ReviewQualityCheckAction.NoAnalysisDisplayed)
},
onShowMoreRecentReviewsClicked = {
store.dispatch(ReviewQualityCheckAction.ShowMoreRecentReviewsClicked)
onHighlightsExpandToggleClick = {
store.dispatch(ReviewQualityCheckAction.ExpandCollapseHighlights)
},
onRecommendedProductClick = { aid, url ->
onRequestDismiss(BottomSheetDismissSource.LINK_OPENED)
@ -134,7 +134,7 @@ private fun ProductReview(
onAnalyzeClick: () -> Unit,
onReanalyzeClick: () -> Unit,
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
onShowMoreRecentReviewsClicked: () -> Unit,
onHighlightsExpandToggleClick: () -> Unit,
onNoAnalysisPresent: () -> Unit,
onSettingsExpandToggleClick: () -> Unit,
onInfoExpandToggleClick: () -> Unit,
@ -155,10 +155,11 @@ private fun ProductReview(
productVendor = state.productVendor,
isSettingsExpanded = state.isSettingsExpanded,
isInfoExpanded = state.isInfoExpanded,
isHighlightsExpanded = state.isHighlightsExpanded,
onOptOutClick = onOptOutClick,
onReanalyzeClick = onReanalyzeClick,
onProductRecommendationsEnabledStateChange = onProductRecommendationsEnabledStateChange,
onShowMoreRecentReviewsClicked = onShowMoreRecentReviewsClicked,
onHighlightsExpandToggleClick = onHighlightsExpandToggleClick,
onSettingsExpandToggleClick = onSettingsExpandToggleClick,
onInfoExpandToggleClick = onInfoExpandToggleClick,
onReviewGradeLearnMoreClick = onReviewGradeLearnMoreClick,

@ -8,8 +8,8 @@ import mozilla.components.concept.engine.shopping.Highlight
import mozilla.components.concept.engine.shopping.ProductAnalysis
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.AnalysisStatus
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.HighlightsInfo
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.RecommendedProductState
import java.util.SortedMap
object ProductAnalysisTestData {
@ -43,7 +43,7 @@ object ProductAnalysisTestData {
reviewGrade: ReviewQualityCheckState.Grade? = ReviewQualityCheckState.Grade.A,
adjustedRating: Float? = 4.5f,
analysisStatus: AnalysisStatus = AnalysisStatus.UP_TO_DATE,
highlights: SortedMap<ReviewQualityCheckState.HighlightType, List<String>>? = null,
highlightsInfo: HighlightsInfo? = null,
recommendedProductState: RecommendedProductState = RecommendedProductState.Initial,
): ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent =
ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent(
@ -52,7 +52,7 @@ object ProductAnalysisTestData {
reviewGrade = reviewGrade,
adjustedRating = adjustedRating,
analysisStatus = analysisStatus,
highlights = highlights,
highlightsInfo = highlightsInfo,
recommendedProductState = recommendedProductState,
)
}

@ -11,6 +11,7 @@ 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
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.HighlightsInfo
class ProductAnalysisMapperTest {
@ -37,12 +38,14 @@ class ProductAnalysisMapperTest {
analysisStatus = AnalysisStatus.UP_TO_DATE,
adjustedRating = 3.4f,
productUrl = "https://example.com",
highlights = sortedMapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PRICE to listOf("\"price\""),
HighlightType.SHIPPING to listOf("\"shipping\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
highlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PRICE to listOf("\"price\""),
HighlightType.SHIPPING to listOf("\"shipping\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
),
),
)
@ -72,10 +75,12 @@ class ProductAnalysisMapperTest {
analysisStatus = AnalysisStatus.NEEDS_ANALYSIS,
adjustedRating = 3.4f,
productUrl = "https://example.com",
highlights = sortedMapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
highlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
),
),
)
@ -172,7 +177,7 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
adjustedRating = 3.5f,
highlights = null,
highlightsInfo = null,
)
assertEquals(expected, actual)
@ -189,7 +194,7 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
reviewGrade = ReviewQualityCheckState.Grade.B,
adjustedRating = null,
highlights = null,
highlightsInfo = null,
)
assertEquals(expected, actual)
@ -212,10 +217,12 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
adjustedRating = null,
highlights = sortedMapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
highlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
),
),
)
@ -239,10 +246,12 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
reviewGrade = ReviewQualityCheckState.Grade.B,
adjustedRating = null,
highlights = sortedMapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
highlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
),
),
)
@ -266,10 +275,12 @@ class ProductAnalysisMapperTest {
val expected = ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
adjustedRating = 3.4f,
highlights = sortedMapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
highlightsInfo = HighlightsInfo(
mapOf(
HighlightType.QUALITY to listOf("\"quality\""),
HighlightType.PACKAGING_AND_APPEARANCE to listOf("\"appearance\""),
HighlightType.COMPETITIVENESS to listOf("\"competitiveness\""),
),
),
)
@ -282,7 +293,8 @@ class ProductAnalysisMapperTest {
pageNotSupported = true,
).toProductReviewState()
val expected = ReviewQualityCheckState.OptedIn.ProductReviewState.Error.UnsupportedProductTypeError
val expected =
ReviewQualityCheckState.OptedIn.ProductReviewState.Error.UnsupportedProductTypeError
assertEquals(expected, actual)
}

@ -113,12 +113,42 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
@Test
fun `WHEN the expand button from the highlights card is clicked THEN the show more recent reviews event is recorded`() {
store.dispatch(ReviewQualityCheckAction.ShowMoreRecentReviewsClicked).joinBlocking()
store.waitUntilIdle()
val tested = ReviewQualityCheckStore(
initialState = ReviewQualityCheckState.OptedIn(
productRecommendationsPreference = true,
productVendor = ReviewQualityCheckState.ProductVendor.AMAZON,
isHighlightsExpanded = false,
),
middleware = listOf(
ReviewQualityCheckTelemetryMiddleware(),
),
)
tested.waitUntilIdle()
tested.dispatch(ReviewQualityCheckAction.ExpandCollapseHighlights).joinBlocking()
tested.waitUntilIdle()
assertNotNull(Shopping.surfaceShowMoreRecentReviewsClicked.testGetValue())
}
@Test
fun `WHEN the collapse button from the highlights card is clicked THEN the show more recent reviews event is not recorded`() {
val tested = ReviewQualityCheckStore(
initialState = ReviewQualityCheckState.OptedIn(
productRecommendationsPreference = true,
productVendor = ReviewQualityCheckState.ProductVendor.AMAZON,
isHighlightsExpanded = true,
),
middleware = listOf(
ReviewQualityCheckTelemetryMiddleware(),
),
)
tested.waitUntilIdle()
tested.dispatch(ReviewQualityCheckAction.ExpandCollapseHighlights).joinBlocking()
tested.waitUntilIdle()
assertNull(Shopping.surfaceShowMoreRecentReviewsClicked.testGetValue())
}
@Test
fun `WHEN the expand button from the settings card is clicked THEN the settings expand event is recorded`() {
val tested = ReviewQualityCheckStore(

@ -10,6 +10,7 @@ import org.junit.Assert.assertThrows
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mozilla.fenix.shopping.ProductAnalysisTestData
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent.HighlightsInfo
class ReviewQualityCheckStateTest {
@ -42,6 +43,7 @@ class ReviewQualityCheckStateTest {
"Unbeatable deals",
),
)
val highlightsInfo = HighlightsInfo(highlights)
val expected = mapOf(
ReviewQualityCheckState.HighlightType.QUALITY to listOf(
@ -50,7 +52,7 @@ class ReviewQualityCheckStateTest {
),
)
assertEquals(expected, highlights.forCompactMode())
assertEquals(expected, highlightsInfo.highlightsForCompactMode)
}
@Test
@ -60,6 +62,7 @@ class ReviewQualityCheckStateTest {
"Affordable prices",
),
)
val highlightsInfo = HighlightsInfo(highlights)
val expected = mapOf(
ReviewQualityCheckState.HighlightType.PRICE to listOf(
@ -67,7 +70,7 @@ class ReviewQualityCheckStateTest {
),
)
assertEquals(expected, highlights.forCompactMode())
assertEquals(expected, highlightsInfo.highlightsForCompactMode)
}
@Test
@ -76,7 +79,7 @@ class ReviewQualityCheckStateTest {
ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
adjustedRating = null,
highlights = null,
highlightsInfo = null,
)
}
}
@ -87,7 +90,7 @@ class ReviewQualityCheckStateTest {
ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
adjustedRating = 1.2f,
highlights = null,
highlightsInfo = null,
)
}
@ -95,7 +98,7 @@ class ReviewQualityCheckStateTest {
ProductAnalysisTestData.analysisPresent(
reviewGrade = ReviewQualityCheckState.Grade.A,
adjustedRating = null,
highlights = null,
highlightsInfo = null,
)
}
@ -103,8 +106,8 @@ class ReviewQualityCheckStateTest {
ProductAnalysisTestData.analysisPresent(
reviewGrade = null,
adjustedRating = null,
highlights = sortedMapOf(
ReviewQualityCheckState.HighlightType.QUALITY to listOf(""),
highlightsInfo = HighlightsInfo(
mapOf(ReviewQualityCheckState.HighlightType.QUALITY to listOf("")),
),
)
}
@ -116,7 +119,7 @@ class ReviewQualityCheckStateTest {
@Test
fun `WHEN AnalysisPresent has more than 2 highlights snippets THEN show more button and highlights fade are visible`() {
val highlights = sortedMapOf(
val highlights = mapOf(
ReviewQualityCheckState.HighlightType.QUALITY to listOf(
"High quality",
"Excellent craftsmanship",
@ -144,45 +147,45 @@ class ReviewQualityCheckStateTest {
),
)
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
highlightsInfo = HighlightsInfo(highlights),
)
assertTrue(analysis.highlightsFadeVisible)
assertTrue(analysis.showMoreButtonVisible)
assertTrue(analysis.highlightsInfo!!.highlightsFadeVisible)
assertTrue(analysis.highlightsInfo!!.showMoreButtonVisible)
}
@Test
fun `WHEN AnalysisPresent has exactly 1 highlights snippet THEN show more button and highlights fade are not visible`() {
val highlights = sortedMapOf(
val highlights = mapOf(
ReviewQualityCheckState.HighlightType.PRICE to listOf("Affordable prices"),
)
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
highlightsInfo = HighlightsInfo(highlights),
)
assertFalse(analysis.highlightsFadeVisible)
assertFalse(analysis.showMoreButtonVisible)
assertFalse(analysis.highlightsInfo!!.highlightsFadeVisible)
assertFalse(analysis.highlightsInfo!!.showMoreButtonVisible)
}
@Test
fun `WHEN AnalysisPresent has exactly 2 highlights snippets THEN show more button and highlights fade are not visible`() {
val highlights = sortedMapOf(
val highlights = mapOf(
ReviewQualityCheckState.HighlightType.SHIPPING to listOf(
"Fast and reliable shipping",
"Free shipping options",
),
)
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
highlightsInfo = HighlightsInfo(highlights),
)
assertFalse(analysis.highlightsFadeVisible)
assertFalse(analysis.showMoreButtonVisible)
assertFalse(analysis.highlightsInfo!!.highlightsFadeVisible)
assertFalse(analysis.highlightsInfo!!.showMoreButtonVisible)
}
@Test
fun `WHEN AnalysisPresent has a single highlights section and the section has more than 2 snippets THEN show more button and highlights fade are visible`() {
val highlights = sortedMapOf(
val highlights = mapOf(
ReviewQualityCheckState.HighlightType.SHIPPING to listOf(
"Fast and reliable shipping",
"Free shipping options",
@ -190,16 +193,16 @@ class ReviewQualityCheckStateTest {
),
)
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
highlightsInfo = HighlightsInfo(highlights),
)
assertTrue(analysis.highlightsFadeVisible)
assertTrue(analysis.showMoreButtonVisible)
assertTrue(analysis.highlightsInfo!!.highlightsFadeVisible)
assertTrue(analysis.highlightsInfo!!.showMoreButtonVisible)
}
@Test
fun `WHEN AnalysisPresent has only 1 highlight snippet for the first category and more for others THEN show more button is visible and highlights fade is not visible`() {
val highlights = sortedMapOf(
val highlights = mapOf(
ReviewQualityCheckState.HighlightType.QUALITY to listOf(
"High quality",
),
@ -215,10 +218,10 @@ class ReviewQualityCheckStateTest {
),
)
val analysis = ProductAnalysisTestData.analysisPresent(
highlights = highlights,
highlightsInfo = HighlightsInfo(highlights),
)
assertTrue(analysis.showMoreButtonVisible)
assertFalse(analysis.highlightsFadeVisible)
assertTrue(analysis.highlightsInfo!!.showMoreButtonVisible)
assertFalse(analysis.highlightsInfo!!.highlightsFadeVisible)
}
}

@ -307,6 +307,56 @@ class ReviewQualityCheckStoreTest {
assertEquals(expected, tested.state)
}
@Test
fun `GIVEN the user has opted in the feature WHEN the user expands highlights card THEN state should reflect that`() =
runTest {
val tested = ReviewQualityCheckStore(
initialState = ReviewQualityCheckState.OptedIn(
productRecommendationsPreference = null,
productVendor = ProductVendor.BEST_BUY,
isHighlightsExpanded = false,
),
middleware = emptyList(),
)
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
tested.dispatch(ReviewQualityCheckAction.ExpandCollapseHighlights).joinBlocking()
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
val expected = ReviewQualityCheckState.OptedIn(
productRecommendationsPreference = null,
productVendor = ProductVendor.BEST_BUY,
isHighlightsExpanded = true,
)
assertEquals(expected, tested.state)
}
@Test
fun `GIVEN the user has opted in the feature WHEN the user collapses highlights card THEN state should reflect that`() =
runTest {
val tested = ReviewQualityCheckStore(
initialState = ReviewQualityCheckState.OptedIn(
productRecommendationsPreference = null,
productVendor = ProductVendor.BEST_BUY,
isHighlightsExpanded = true,
),
middleware = emptyList(),
)
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
tested.dispatch(ReviewQualityCheckAction.ExpandCollapseHighlights).joinBlocking()
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
val expected = ReviewQualityCheckState.OptedIn(
productRecommendationsPreference = null,
productVendor = ProductVendor.BEST_BUY,
isHighlightsExpanded = false,
)
assertEquals(expected, tested.state)
}
@Test
fun `GIVEN the user has opted in the feature WHEN a product analysis is fetched successfully THEN state should reflect that`() =
runTest {

Loading…
Cancel
Save