mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-13 07:10:28 +00:00
Bug 1861694 - Use analysis status to restore (re)analysis state
This commit is contained in:
parent
6cb5a4cef4
commit
6af781a519
@ -227,17 +227,6 @@ sealed class AppAction : Action {
|
||||
*/
|
||||
data class ShoppingSheetStateUpdated(val expanded: Boolean) : ShoppingAction()
|
||||
|
||||
/**
|
||||
* [ShoppingAction] used to add a product to a set of products that are being analysed.
|
||||
*/
|
||||
data class AddToProductAnalysed(val productPageUrl: String) : ShoppingAction()
|
||||
|
||||
/**
|
||||
* [ShoppingAction] used to remove a product from the set of products that are being
|
||||
* analysed.
|
||||
*/
|
||||
data class RemoveFromProductAnalysed(val productPageUrl: String) : ShoppingAction()
|
||||
|
||||
/**
|
||||
* [ShoppingAction] used to update the expansion state of the highlights card.
|
||||
*/
|
||||
|
@ -7,14 +7,11 @@ package org.mozilla.fenix.components.appstate.shopping
|
||||
/**
|
||||
* State for shopping feature that's required to live the lifetime of a session.
|
||||
*
|
||||
* @property productsInAnalysis Set of product urls that are currently being analysed or were being
|
||||
* analysed when the sheet was closed.
|
||||
* @property shoppingSheetExpanded Boolean indicating if the shopping sheet is expanded and visible.
|
||||
* @property productCardState Map of product url to [CardState] that contains the state of different
|
||||
* cards in the shopping sheet.
|
||||
*/
|
||||
data class ShoppingState(
|
||||
val productsInAnalysis: Set<String> = emptySet(),
|
||||
val shoppingSheetExpanded: Boolean? = null,
|
||||
val productCardState: Map<String, CardState> = emptyMap(),
|
||||
) {
|
||||
|
@ -24,18 +24,6 @@ internal object ShoppingStateReducer {
|
||||
),
|
||||
)
|
||||
|
||||
is ShoppingAction.AddToProductAnalysed -> state.copy(
|
||||
shoppingState = state.shoppingState.copy(
|
||||
productsInAnalysis = state.shoppingState.productsInAnalysis + action.productPageUrl,
|
||||
),
|
||||
)
|
||||
|
||||
is ShoppingAction.RemoveFromProductAnalysed -> state.copy(
|
||||
shoppingState = state.shoppingState.copy(
|
||||
productsInAnalysis = state.shoppingState.productsInAnalysis - action.productPageUrl,
|
||||
),
|
||||
)
|
||||
|
||||
is ShoppingAction.HighlightsCardExpanded -> {
|
||||
val updatedValue =
|
||||
state.shoppingState.productCardState[action.productPageUrl]?.copy(
|
||||
|
@ -45,9 +45,9 @@ object ReviewQualityCheckMiddlewareProvider {
|
||||
): List<ReviewQualityCheckMiddleware> =
|
||||
listOf(
|
||||
providePreferencesMiddleware(settings, browserStore, appStore, scope),
|
||||
provideNetworkMiddleware(browserStore, appStore, context, scope),
|
||||
provideNetworkMiddleware(browserStore, context, scope),
|
||||
provideNavigationMiddleware(TabsUseCases.SelectOrAddUseCase(browserStore), context),
|
||||
provideTelemetryMiddleware(browserStore, appStore),
|
||||
provideTelemetryMiddleware(),
|
||||
)
|
||||
|
||||
private fun providePreferencesMiddleware(
|
||||
@ -65,13 +65,11 @@ object ReviewQualityCheckMiddlewareProvider {
|
||||
|
||||
private fun provideNetworkMiddleware(
|
||||
browserStore: BrowserStore,
|
||||
appStore: AppStore,
|
||||
context: Context,
|
||||
scope: CoroutineScope,
|
||||
) = ReviewQualityCheckNetworkMiddleware(
|
||||
reviewQualityCheckService = DefaultReviewQualityCheckService(browserStore),
|
||||
networkChecker = DefaultNetworkChecker(context),
|
||||
appStore = appStore,
|
||||
scope = scope,
|
||||
)
|
||||
|
||||
@ -83,11 +81,6 @@ object ReviewQualityCheckMiddlewareProvider {
|
||||
GetReviewQualityCheckSumoUrl(context),
|
||||
)
|
||||
|
||||
private fun provideTelemetryMiddleware(
|
||||
browserStore: BrowserStore,
|
||||
appStore: AppStore,
|
||||
) = ReviewQualityCheckTelemetryMiddleware(
|
||||
browserStore = browserStore,
|
||||
appStore = appStore,
|
||||
)
|
||||
private fun provideTelemetryMiddleware() =
|
||||
ReviewQualityCheckTelemetryMiddleware()
|
||||
}
|
||||
|
@ -6,11 +6,8 @@ package org.mozilla.fenix.shopping.middleware
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.concept.engine.shopping.ProductAnalysis
|
||||
import mozilla.components.lib.state.MiddlewareContext
|
||||
import mozilla.components.lib.state.Store
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.components.appstate.AppAction.ShoppingAction
|
||||
import org.mozilla.fenix.shopping.store.ReviewQualityCheckAction
|
||||
import org.mozilla.fenix.shopping.store.ReviewQualityCheckAction.FetchProductAnalysis
|
||||
import org.mozilla.fenix.shopping.store.ReviewQualityCheckAction.RetryProductAnalysis
|
||||
@ -25,13 +22,11 @@ import org.mozilla.fenix.shopping.store.ReviewQualityCheckState.OptedIn.ProductR
|
||||
*
|
||||
* @param reviewQualityCheckService The service that handles the network requests.
|
||||
* @param networkChecker The [NetworkChecker] instance to check the network status.
|
||||
* @param appStore The [AppStore] instance to access state and dispatch [ShoppingAction]s.
|
||||
* @param scope The [CoroutineScope] that will be used to launch coroutines.
|
||||
*/
|
||||
class ReviewQualityCheckNetworkMiddleware(
|
||||
private val reviewQualityCheckService: ReviewQualityCheckService,
|
||||
private val networkChecker: NetworkChecker,
|
||||
private val appStore: AppStore,
|
||||
private val scope: CoroutineScope,
|
||||
) : ReviewQualityCheckMiddleware {
|
||||
|
||||
@ -61,17 +56,19 @@ class ReviewQualityCheckNetworkMiddleware(
|
||||
scope.launch {
|
||||
when (action) {
|
||||
FetchProductAnalysis, RetryProductAnalysis -> {
|
||||
val productPageUrl = reviewQualityCheckService.selectedTabUrl()
|
||||
val productAnalysis = reviewQualityCheckService.fetchProductReview()
|
||||
val productReviewState = productAnalysis.toProductReviewState()
|
||||
store.updateProductReviewState(productReviewState)
|
||||
|
||||
productPageUrl?.let {
|
||||
store.restoreAnalysingStateIfRequired(
|
||||
productPageUrl = productPageUrl,
|
||||
productReviewState = productReviewState,
|
||||
productAnalysis = productAnalysis,
|
||||
)
|
||||
// Here the ProductReviewState should only updated after the analysis status API
|
||||
// returns a result. This makes sure that the UI doesn't show the reanalyse
|
||||
// button in case the product analysis is already in progress on the backend.
|
||||
if (productReviewState.isAnalysisPresentOrNoAnalysisPresent() &&
|
||||
reviewQualityCheckService.analysisStatus().isPendingOrInProgress()
|
||||
) {
|
||||
store.updateProductReviewState(productReviewState, true)
|
||||
store.dispatch(ReviewQualityCheckAction.RestoreReanalysis)
|
||||
} else {
|
||||
store.updateProductReviewState(productReviewState)
|
||||
}
|
||||
|
||||
if (productReviewState is ProductReviewState.AnalysisPresent) {
|
||||
@ -90,12 +87,6 @@ class ReviewQualityCheckNetworkMiddleware(
|
||||
return@launch
|
||||
}
|
||||
|
||||
// add product to the set of products that are being analysed
|
||||
val productPageUrl = reviewQualityCheckService.selectedTabUrl()
|
||||
productPageUrl?.let {
|
||||
appStore.dispatch(ShoppingAction.AddToProductAnalysed(it))
|
||||
}
|
||||
|
||||
val status = pollForAnalysisStatus()
|
||||
|
||||
if (status == null ||
|
||||
@ -121,11 +112,6 @@ class ReviewQualityCheckNetworkMiddleware(
|
||||
val productReviewState = productAnalysis.toProductReviewState()
|
||||
store.updateProductReviewState(productReviewState)
|
||||
}
|
||||
|
||||
// remove product from the set of products that are being analysed
|
||||
productPageUrl?.let {
|
||||
appStore.dispatch(ShoppingAction.RemoveFromProductAnalysed(it))
|
||||
}
|
||||
}
|
||||
|
||||
is ReviewQualityCheckAction.RecommendedProductClick -> {
|
||||
@ -141,27 +127,15 @@ class ReviewQualityCheckNetworkMiddleware(
|
||||
|
||||
private suspend fun pollForAnalysisStatus(): AnalysisStatusDto? =
|
||||
retry(
|
||||
predicate = { it == AnalysisStatusDto.PENDING || it == AnalysisStatusDto.IN_PROGRESS },
|
||||
predicate = { it.isPendingOrInProgress() },
|
||||
block = { reviewQualityCheckService.analysisStatus() },
|
||||
)
|
||||
|
||||
private fun Store<ReviewQualityCheckState, ReviewQualityCheckAction>.updateProductReviewState(
|
||||
productReviewState: ProductReviewState,
|
||||
restoreAnalysis: Boolean = false,
|
||||
) {
|
||||
dispatch(ReviewQualityCheckAction.UpdateProductReview(productReviewState))
|
||||
}
|
||||
|
||||
private fun Store<ReviewQualityCheckState, ReviewQualityCheckAction>.restoreAnalysingStateIfRequired(
|
||||
productPageUrl: String,
|
||||
productReviewState: ProductReviewState,
|
||||
productAnalysis: ProductAnalysis?,
|
||||
) {
|
||||
if (productReviewState.isAnalysisPresentOrNoAnalysisPresent() &&
|
||||
productAnalysis?.needsAnalysis == true &&
|
||||
appStore.state.shoppingState.productsInAnalysis.contains(productPageUrl)
|
||||
) {
|
||||
dispatch(ReviewQualityCheckAction.RestoreReanalysis)
|
||||
}
|
||||
dispatch(ReviewQualityCheckAction.UpdateProductReview(productReviewState, restoreAnalysis))
|
||||
}
|
||||
|
||||
private fun ProductReviewState.isAnalysisPresentOrNoAnalysisPresent() =
|
||||
@ -182,4 +156,7 @@ class ReviewQualityCheckNetworkMiddleware(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AnalysisStatusDto?.isPendingOrInProgress(): Boolean =
|
||||
this == AnalysisStatusDto.PENDING || this == AnalysisStatusDto.IN_PROGRESS
|
||||
}
|
||||
|
@ -41,11 +41,6 @@ interface ReviewQualityCheckService {
|
||||
*/
|
||||
suspend fun analysisStatus(): AnalysisStatusDto?
|
||||
|
||||
/**
|
||||
* Returns the selected tab url.
|
||||
*/
|
||||
fun selectedTabUrl(): String?
|
||||
|
||||
/**
|
||||
* Fetches product recommendations related to the product user is browsing in the current tab.
|
||||
*
|
||||
@ -126,9 +121,6 @@ class DefaultReviewQualityCheckService(
|
||||
}
|
||||
}
|
||||
|
||||
override fun selectedTabUrl(): String? =
|
||||
browserStore.state.selectedTab?.content?.url
|
||||
|
||||
override suspend fun productRecommendation(shouldRecordAvailableTelemetry: Boolean): ProductRecommendation? =
|
||||
withContext(Dispatchers.Main) {
|
||||
suspendCoroutine { continuation ->
|
||||
|
@ -4,13 +4,10 @@
|
||||
|
||||
package org.mozilla.fenix.shopping.middleware
|
||||
|
||||
import mozilla.components.browser.state.selector.selectedTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.lib.state.MiddlewareContext
|
||||
import mozilla.components.lib.state.Store
|
||||
import org.mozilla.fenix.GleanMetrics.Shopping
|
||||
import org.mozilla.fenix.GleanMetrics.ShoppingSettings
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.shopping.store.ReviewQualityCheckAction
|
||||
import org.mozilla.fenix.shopping.store.ReviewQualityCheckMiddleware
|
||||
import org.mozilla.fenix.shopping.store.ReviewQualityCheckState
|
||||
@ -22,10 +19,7 @@ private const val ACTION_DISABLED = "disabled"
|
||||
/**
|
||||
* Middleware that captures telemetry events for the review quality check feature.
|
||||
*/
|
||||
class ReviewQualityCheckTelemetryMiddleware(
|
||||
private val browserStore: BrowserStore,
|
||||
private val appStore: AppStore,
|
||||
) : ReviewQualityCheckMiddleware {
|
||||
class ReviewQualityCheckTelemetryMiddleware : ReviewQualityCheckMiddleware {
|
||||
|
||||
override fun invoke(
|
||||
context: MiddlewareContext<ReviewQualityCheckState, ReviewQualityCheckAction>,
|
||||
@ -108,9 +102,8 @@ class ReviewQualityCheckTelemetryMiddleware(
|
||||
}
|
||||
|
||||
is ReviewQualityCheckAction.UpdateProductReview -> {
|
||||
val productPageUrl = browserStore.state.selectedTab?.content?.url
|
||||
val state = store.state
|
||||
if (state.isStaleAnalysis() && !isProductInAnalysis(productPageUrl)) {
|
||||
if (state.isStaleAnalysis() && !action.restoreAnalysis) {
|
||||
Shopping.surfaceStaleAnalysisShown.record()
|
||||
}
|
||||
}
|
||||
@ -167,9 +160,4 @@ class ReviewQualityCheckTelemetryMiddleware(
|
||||
this is ReviewQualityCheckState.OptedIn &&
|
||||
this.productReviewState is ReviewQualityCheckState.OptedIn.ProductReviewState.AnalysisPresent &&
|
||||
this.productReviewState.analysisStatus == AnalysisStatus.NEEDS_ANALYSIS
|
||||
|
||||
private fun isProductInAnalysis(
|
||||
productPageUrl: String?,
|
||||
): Boolean =
|
||||
appStore.state.shoppingState.productsInAnalysis.contains(productPageUrl)
|
||||
}
|
||||
|
@ -89,8 +89,14 @@ sealed interface ReviewQualityCheckAction : Action {
|
||||
|
||||
/**
|
||||
* Triggered as a result of a [NetworkAction] to update the [ProductReviewState].
|
||||
*
|
||||
* @property productReviewState The product review state to update.
|
||||
* @property restoreAnalysis Signals whether the analysis will be restored right after the update.
|
||||
*/
|
||||
data class UpdateProductReview(val productReviewState: ProductReviewState) : UpdateAction, TelemetryAction
|
||||
data class UpdateProductReview(
|
||||
val productReviewState: ProductReviewState,
|
||||
val restoreAnalysis: Boolean,
|
||||
) : UpdateAction, TelemetryAction
|
||||
|
||||
/**
|
||||
* Triggered as a result of a [NetworkAction] to update the [RecommendedProductState].
|
||||
|
@ -47,38 +47,6 @@ class ShoppingActionTest {
|
||||
assertEquals(expected, store.state.shoppingState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN product analysed is added THEN state should reflect that`() {
|
||||
val store = AppStore()
|
||||
|
||||
store.dispatch(AppAction.ShoppingAction.AddToProductAnalysed("pdp")).joinBlocking()
|
||||
|
||||
val expected = ShoppingState(
|
||||
productsInAnalysis = setOf("pdp"),
|
||||
)
|
||||
|
||||
assertEquals(expected, store.state.shoppingState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN product analysed is removed THEN state should reflect that`() {
|
||||
val store = AppStore(
|
||||
initialState = AppState(
|
||||
shoppingState = ShoppingState(
|
||||
productsInAnalysis = setOf("pdp"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
store.dispatch(AppAction.ShoppingAction.RemoveFromProductAnalysed("pdp")).joinBlocking()
|
||||
|
||||
val expected = ShoppingState(
|
||||
productsInAnalysis = emptySet(),
|
||||
)
|
||||
|
||||
assertEquals(expected, store.state.shoppingState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN product analysis highlights card is expanded THEN state should reflect that`() {
|
||||
val store = AppStore(initialState = AppState(shoppingState = ShoppingState()))
|
||||
|
@ -13,7 +13,6 @@ class FakeReviewQualityCheckService(
|
||||
private val productAnalysis: (Int) -> ProductAnalysis? = { null },
|
||||
private val reanalysis: AnalysisStatusDto? = null,
|
||||
private val status: AnalysisStatusDto? = null,
|
||||
private val selectedTabUrl: String? = null,
|
||||
private val productRecommendation: () -> ProductRecommendation? = { null },
|
||||
private val recordClick: (String) -> Unit = {},
|
||||
private val recordImpression: (String) -> Unit = {},
|
||||
@ -31,8 +30,6 @@ class FakeReviewQualityCheckService(
|
||||
|
||||
override suspend fun analysisStatus(): AnalysisStatusDto? = status
|
||||
|
||||
override fun selectedTabUrl(): String? = selectedTabUrl
|
||||
|
||||
override suspend fun productRecommendation(shouldRecordAvailableTelemetry: Boolean): ProductRecommendation? {
|
||||
return productRecommendation.invoke()
|
||||
}
|
||||
|
@ -4,9 +4,6 @@
|
||||
|
||||
package org.mozilla.fenix.shopping.middleware
|
||||
|
||||
import mozilla.components.browser.state.state.BrowserState
|
||||
import mozilla.components.browser.state.state.createTab
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.service.glean.testing.GleanTestRule
|
||||
import mozilla.components.support.test.ext.joinBlocking
|
||||
import mozilla.components.support.test.libstate.ext.waitUntilIdle
|
||||
@ -19,8 +16,6 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.GleanMetrics.Shopping
|
||||
import org.mozilla.fenix.components.AppStore
|
||||
import org.mozilla.fenix.components.appstate.AppAction
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.shopping.ProductAnalysisTestData
|
||||
import org.mozilla.fenix.shopping.store.BottomSheetDismissSource
|
||||
@ -37,16 +32,12 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
val gleanTestRule = GleanTestRule(testContext)
|
||||
|
||||
private lateinit var store: ReviewQualityCheckStore
|
||||
private lateinit var browserStore: BrowserStore
|
||||
private lateinit var appStore: AppStore
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
browserStore = BrowserStore()
|
||||
appStore = AppStore()
|
||||
store = ReviewQualityCheckStore(
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
store.waitUntilIdle()
|
||||
@ -132,7 +123,7 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
isHighlightsExpanded = false,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
tested.waitUntilIdle()
|
||||
@ -152,7 +143,7 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
isHighlightsExpanded = true,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
tested.waitUntilIdle()
|
||||
@ -172,7 +163,7 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
isSettingsExpanded = false,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
tested.waitUntilIdle()
|
||||
@ -192,7 +183,7 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
isSettingsExpanded = true,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
tested.waitUntilIdle()
|
||||
@ -251,91 +242,76 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a product review has been updated WHEN stale analysis is present and product is not in analysis THEN the stale analysis event is recorded`() {
|
||||
val productTab = createTab(
|
||||
url = "pdp",
|
||||
)
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(productTab),
|
||||
selectedTabId = productTab.id,
|
||||
)
|
||||
val testedStore = ReviewQualityCheckStore(
|
||||
initialState = ReviewQualityCheckState.OptedIn(
|
||||
productReviewState = ProductAnalysisTestData.analysisPresent(
|
||||
analysisStatus = AnalysisPresent.AnalysisStatus.UP_TO_DATE,
|
||||
),
|
||||
productRecommendationsPreference = false,
|
||||
productRecommendationsExposure = true,
|
||||
productVendor = ReviewQualityCheckState.ProductVendor.AMAZON,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(BrowserStore(browserState), appStore),
|
||||
),
|
||||
)
|
||||
fun `GIVEN a product review has been updated WHEN restore analysis is false THEN the stale analysis event is recorded`() {
|
||||
val productReviewState = ProductAnalysisTestData.analysisPresent(
|
||||
analysisStatus = AnalysisPresent.AnalysisStatus.NEEDS_ANALYSIS,
|
||||
)
|
||||
|
||||
testedStore.dispatch(ReviewQualityCheckAction.UpdateProductReview(productReviewState)).joinBlocking()
|
||||
testedStore.waitUntilIdle()
|
||||
val tested = ReviewQualityCheckStore(
|
||||
initialState = ReviewQualityCheckState.OptedIn(
|
||||
productRecommendationsPreference = null,
|
||||
productRecommendationsExposure = true,
|
||||
productVendor = ReviewQualityCheckState.ProductVendor.BEST_BUY,
|
||||
),
|
||||
middleware = listOf(ReviewQualityCheckTelemetryMiddleware()),
|
||||
)
|
||||
|
||||
tested.dispatch(
|
||||
ReviewQualityCheckAction.UpdateProductReview(
|
||||
productReviewState = productReviewState,
|
||||
restoreAnalysis = false,
|
||||
),
|
||||
).joinBlocking()
|
||||
tested.waitUntilIdle()
|
||||
|
||||
assertNotNull(Shopping.surfaceStaleAnalysisShown.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a product review has been updated WHEN stale analysis is present and product is being analyzed THEN the stale analysis event is not recorded`() {
|
||||
val productTab = createTab(
|
||||
url = "pdp",
|
||||
)
|
||||
appStore.dispatch(AppAction.ShoppingAction.AddToProductAnalysed("pdp")).joinBlocking()
|
||||
appStore.waitUntilIdle()
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(productTab),
|
||||
selectedTabId = productTab.id,
|
||||
)
|
||||
val testedStore = ReviewQualityCheckStore(
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(BrowserStore(browserState), appStore),
|
||||
),
|
||||
)
|
||||
fun `GIVEN a product review has been updated WHEN restore analysis is true THEN the stale analysis event is not recorded`() {
|
||||
val productReviewState = ProductAnalysisTestData.analysisPresent(
|
||||
analysisStatus = AnalysisPresent.AnalysisStatus.NEEDS_ANALYSIS,
|
||||
)
|
||||
val tested = ReviewQualityCheckStore(
|
||||
initialState = ReviewQualityCheckState.OptedIn(
|
||||
productRecommendationsPreference = null,
|
||||
productRecommendationsExposure = true,
|
||||
productVendor = ReviewQualityCheckState.ProductVendor.BEST_BUY,
|
||||
),
|
||||
middleware = listOf(ReviewQualityCheckTelemetryMiddleware()),
|
||||
)
|
||||
|
||||
testedStore.dispatch(ReviewQualityCheckAction.UpdateProductReview(productReviewState)).joinBlocking()
|
||||
testedStore.waitUntilIdle()
|
||||
tested.dispatch(
|
||||
ReviewQualityCheckAction.UpdateProductReview(
|
||||
productReviewState = productReviewState,
|
||||
restoreAnalysis = true,
|
||||
),
|
||||
).joinBlocking()
|
||||
tested.waitUntilIdle()
|
||||
|
||||
assertNull(Shopping.surfaceStaleAnalysisShown.testGetValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN a product review has been updated WHEN it is not a stale analysis THEN the stale analysis event is not recorded`() {
|
||||
val productTab = createTab(
|
||||
url = "pdp",
|
||||
)
|
||||
val browserState = BrowserState(
|
||||
tabs = listOf(productTab),
|
||||
selectedTabId = productTab.id,
|
||||
)
|
||||
val testedStore = ReviewQualityCheckStore(
|
||||
val productReviewState = ProductAnalysisTestData.analysisPresent()
|
||||
|
||||
val tested = ReviewQualityCheckStore(
|
||||
initialState = ReviewQualityCheckState.OptedIn(
|
||||
productReviewState = ProductAnalysisTestData.analysisPresent(
|
||||
analysisStatus = AnalysisPresent.AnalysisStatus.NEEDS_ANALYSIS,
|
||||
),
|
||||
productRecommendationsPreference = false,
|
||||
productRecommendationsPreference = null,
|
||||
productRecommendationsExposure = true,
|
||||
productVendor = ReviewQualityCheckState.ProductVendor.AMAZON,
|
||||
productVendor = ReviewQualityCheckState.ProductVendor.BEST_BUY,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(BrowserStore(browserState), appStore),
|
||||
),
|
||||
)
|
||||
val productReviewState = ProductAnalysisTestData.analysisPresent(
|
||||
analysisStatus = AnalysisPresent.AnalysisStatus.REANALYZING,
|
||||
middleware = listOf(ReviewQualityCheckTelemetryMiddleware()),
|
||||
)
|
||||
|
||||
testedStore.dispatch(ReviewQualityCheckAction.UpdateProductReview(productReviewState)).joinBlocking()
|
||||
testedStore.waitUntilIdle()
|
||||
tested.dispatch(
|
||||
ReviewQualityCheckAction.UpdateProductReview(
|
||||
productReviewState = productReviewState,
|
||||
restoreAnalysis = true,
|
||||
),
|
||||
).joinBlocking()
|
||||
tested.waitUntilIdle()
|
||||
|
||||
assertNull(Shopping.surfaceStaleAnalysisShown.testGetValue())
|
||||
}
|
||||
@ -366,7 +342,7 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
isHighlightsExpanded = false,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
tested.waitUntilIdle()
|
||||
@ -386,7 +362,7 @@ class ReviewQualityCheckTelemetryMiddlewareTest {
|
||||
isHighlightsExpanded = false,
|
||||
),
|
||||
middleware = listOf(
|
||||
ReviewQualityCheckTelemetryMiddleware(browserStore, appStore),
|
||||
ReviewQualityCheckTelemetryMiddleware(),
|
||||
),
|
||||
)
|
||||
tested.waitUntilIdle()
|
||||
|
@ -716,23 +716,19 @@ class ReviewQualityCheckStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN that the product was being analysed earlier WHEN needsAnalysis is true THEN state should be restored to reanalysing`() =
|
||||
fun `GIVEN a product analysis WHEN analysis status is in progress or pending THEN state should be updated to reanalysing`() =
|
||||
runTest {
|
||||
val tested = ReviewQualityCheckStore(
|
||||
middleware = provideReviewQualityCheckMiddleware(
|
||||
reviewQualityCheckPreferences = FakeReviewQualityCheckPreferences(isEnabled = true),
|
||||
reviewQualityCheckService = FakeReviewQualityCheckService(
|
||||
productAnalysis = {
|
||||
ProductAnalysisTestData.productAnalysis(needsAnalysis = true)
|
||||
ProductAnalysisTestData.productAnalysis()
|
||||
},
|
||||
reanalysis = AnalysisStatusDto.PENDING,
|
||||
status = AnalysisStatusDto.COMPLETED,
|
||||
selectedTabUrl = "pdp",
|
||||
status = AnalysisStatusDto.IN_PROGRESS,
|
||||
),
|
||||
networkChecker = FakeNetworkChecker(isConnected = true),
|
||||
appStore = AppStore(
|
||||
AppState(shoppingState = ShoppingState(productsInAnalysis = setOf("pdp"))),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@ -763,7 +759,7 @@ class ReviewQualityCheckStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN that the product was not being analysed earlier WHEN needsAnalysis is true THEN state should display needs analysis as usual`() =
|
||||
fun `GIVEN a product analysis WHEN analysis status is completed THEN state should display analysis as usual`() =
|
||||
runTest {
|
||||
val tested = ReviewQualityCheckStore(
|
||||
middleware = provideReviewQualityCheckMiddleware(
|
||||
@ -772,18 +768,10 @@ class ReviewQualityCheckStoreTest {
|
||||
productAnalysis = {
|
||||
ProductAnalysisTestData.productAnalysis(needsAnalysis = true)
|
||||
},
|
||||
reanalysis = AnalysisStatusDto.PENDING,
|
||||
reanalysis = AnalysisStatusDto.COMPLETED,
|
||||
status = AnalysisStatusDto.COMPLETED,
|
||||
selectedTabUrl = "pdp",
|
||||
),
|
||||
networkChecker = FakeNetworkChecker(isConnected = true),
|
||||
appStore = AppStore(
|
||||
AppState(
|
||||
shoppingState = ShoppingState(
|
||||
productsInAnalysis = setOf("test", "another", "product"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@ -821,34 +809,51 @@ class ReviewQualityCheckStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `WHEN reanalysis is triggered THEN shopping state should contain the url of the product being analyzed`() =
|
||||
fun `GIVEN a product analysis WHEN analysis status fails THEN state should display analysis as usual`() =
|
||||
runTest {
|
||||
val captureActionsMiddleware = CaptureActionsMiddleware<AppState, AppAction>()
|
||||
val appStore = AppStore(middlewares = listOf(captureActionsMiddleware))
|
||||
val tested = ReviewQualityCheckStore(
|
||||
middleware = provideReviewQualityCheckMiddleware(
|
||||
reviewQualityCheckPreferences = FakeReviewQualityCheckPreferences(isEnabled = true),
|
||||
reviewQualityCheckService = FakeReviewQualityCheckService(
|
||||
productAnalysis = { ProductAnalysisTestData.productAnalysis() },
|
||||
reanalysis = AnalysisStatusDto.PENDING,
|
||||
status = AnalysisStatusDto.COMPLETED,
|
||||
selectedTabUrl = "pdp",
|
||||
productAnalysis = {
|
||||
ProductAnalysisTestData.productAnalysis()
|
||||
},
|
||||
reanalysis = null,
|
||||
status = null,
|
||||
),
|
||||
networkChecker = FakeNetworkChecker(isConnected = true),
|
||||
appStore = appStore,
|
||||
),
|
||||
)
|
||||
|
||||
val observedState = mutableListOf<ReviewQualityCheckState>()
|
||||
tested.observeForever {
|
||||
observedState.add(it)
|
||||
}
|
||||
|
||||
tested.waitUntilIdle()
|
||||
dispatcher.scheduler.advanceUntilIdle()
|
||||
tested.waitUntilIdle()
|
||||
tested.dispatch(ReviewQualityCheckAction.ReanalyzeProduct).joinBlocking()
|
||||
tested.dispatch(ReviewQualityCheckAction.FetchProductAnalysis).joinBlocking()
|
||||
tested.waitUntilIdle()
|
||||
dispatcher.scheduler.advanceUntilIdle()
|
||||
|
||||
captureActionsMiddleware.assertFirstAction(AppAction.ShoppingAction.AddToProductAnalysed::class) {
|
||||
assertEquals("pdp", it.productPageUrl)
|
||||
}
|
||||
val expected = ReviewQualityCheckState.OptedIn(
|
||||
productReviewState = ProductAnalysisTestData.analysisPresent(),
|
||||
productRecommendationsPreference = false,
|
||||
productRecommendationsExposure = true,
|
||||
productVendor = ProductVendor.BEST_BUY,
|
||||
)
|
||||
assertEquals(expected, tested.state)
|
||||
|
||||
val notExpected = ReviewQualityCheckState.OptedIn(
|
||||
productReviewState = ProductAnalysisTestData.analysisPresent(
|
||||
analysisStatus = AnalysisStatus.REANALYZING,
|
||||
),
|
||||
productRecommendationsPreference = false,
|
||||
productRecommendationsExposure = true,
|
||||
productVendor = ProductVendor.BEST_BUY,
|
||||
)
|
||||
assertFalse(observedState.contains(notExpected))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1165,7 +1170,6 @@ class ReviewQualityCheckStoreTest {
|
||||
ReviewQualityCheckNetworkMiddleware(
|
||||
reviewQualityCheckService = reviewQualityCheckService,
|
||||
networkChecker = networkChecker,
|
||||
appStore = appStore,
|
||||
scope = this.scope,
|
||||
),
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user