Bug 1856336 - Integrate rc impression and click APIs in network middleware

fenix/121.0
rahulsainani 7 months ago committed by mergify[bot]
parent 3e0a3d7238
commit 9e455f7158

@ -65,6 +65,6 @@ class ReviewQualityCheckNavigationMiddleware(
is ReviewQualityCheckAction.OpenPoweredByLink -> POWERED_BY_URL
is ReviewQualityCheckAction.OpenRecommendedProduct -> action.productUrl
is ReviewQualityCheckAction.RecommendedProductClick -> action.productUrl
}
}

@ -124,6 +124,14 @@ class ReviewQualityCheckNetworkMiddleware(
appStore.dispatch(ShoppingAction.RemoveFromProductAnalysed(it))
}
}
is ReviewQualityCheckAction.RecommendedProductClick -> {
reviewQualityCheckService.recordRecommendedProductClick(action.productAid)
}
is ReviewQualityCheckAction.RecommendedProductImpression -> {
reviewQualityCheckService.recordRecommendedProductImpression(action.productAid)
}
}
}
}

@ -51,6 +51,16 @@ interface ReviewQualityCheckService {
* @return [ProductRecommendation] if request succeeds, null otherwise.
*/
suspend fun productRecommendation(): ProductRecommendation?
/**
* Sends a click attribution event for a given product aid.
*/
suspend fun recordRecommendedProductClick(productAid: String)
/**
* Sends an impression attribution event for a given product aid.
*/
suspend fun recordRecommendedProductImpression(productAid: String)
}
/**
@ -137,6 +147,39 @@ class DefaultReviewQualityCheckService(
}
}
}
override suspend fun recordRecommendedProductClick(productAid: String) =
withContext(Dispatchers.Main) {
suspendCoroutine { continuation ->
browserStore.state.selectedTab?.engineState?.engineSession?.sendClickAttributionEvent(
aid = productAid,
onResult = {
continuation.resume(Unit)
},
onException = {
logger.error("Error sending click attribution event", it)
continuation.resume(Unit)
},
)
}
}
override suspend fun recordRecommendedProductImpression(productAid: String) {
withContext(Dispatchers.Main) {
suspendCoroutine { continuation ->
browserStore.state.selectedTab?.engineState?.engineSession?.sendImpressionAttributionEvent(
aid = productAid,
onResult = {
continuation.resume(Unit)
},
onException = {
logger.error("Error sending impression attribution event", it)
continuation.resume(Unit)
},
)
}
}
}
}
/**

@ -111,6 +111,26 @@ sealed interface ReviewQualityCheckAction : Action {
*/
object AnalyzeProduct : NetworkAction, UpdateAction, TelemetryAction
/**
* Triggered when the user clicks on the recommended product.
*
* @property productAid The product's aid.
* @property productUrl The product's link to open.
*/
data class RecommendedProductClick(
val productAid: String,
val productUrl: String,
) : NavigationMiddlewareAction, NetworkAction
/**
* Triggered when the user views the recommended product.
*
* @property productAid The product's aid.
*/
data class RecommendedProductImpression(
val productAid: String,
) : NetworkAction
/**
* Triggered when the user clicks on learn more link on the explainer card.
*/
@ -179,11 +199,4 @@ sealed interface ReviewQualityCheckAction : Action {
* Triggered when the user reports a product is back in stock.
*/
object ReportProductBackInStock : TelemetryAction
/**
* Triggered when the user clicks on the recommended product.
*
* @property productUrl The product's link to open.
*/
data class OpenRecommendedProduct(val productUrl: String) : NavigationMiddlewareAction
}

@ -92,7 +92,7 @@ fun ProductAnalysis(
onShowMoreRecentReviewsClicked: () -> Unit,
onSettingsExpandToggleClick: () -> Unit,
onInfoExpandToggleClick: () -> Unit,
onRecommendedProductClick: (String) -> Unit,
onRecommendedProductClick: (aid: String, url: String) -> Unit,
modifier: Modifier = Modifier,
) {
Column(
@ -149,7 +149,10 @@ fun ProductAnalysis(
ProductRecommendation(
product = productAnalysis.recommendedProductState,
onClick = {
onRecommendedProductClick(productAnalysis.recommendedProductState.productUrl)
onRecommendedProductClick(
productAnalysis.recommendedProductState.aid,
productAnalysis.recommendedProductState.productUrl,
)
},
)
}
@ -617,7 +620,7 @@ private fun ProductAnalysisPreview(
onShowMoreRecentReviewsClicked = {},
onSettingsExpandToggleClick = { isSettingsExpanded = !isSettingsExpanded },
onInfoExpandToggleClick = { isInfoExpanded = !isInfoExpanded },
onRecommendedProductClick = {},
onRecommendedProductClick = { _, _ -> },
)
}
}

@ -105,9 +105,9 @@ fun ReviewQualityCheckBottomSheet(
onShowMoreRecentReviewsClicked = {
store.dispatch(ReviewQualityCheckAction.ShowMoreRecentReviewsClicked)
},
onRecommendedProductClick = {
onRecommendedProductClick = { aid, url ->
onRequestDismiss(BottomSheetDismissSource.LINK_OPENED)
store.dispatch(ReviewQualityCheckAction.OpenRecommendedProduct(it))
store.dispatch(ReviewQualityCheckAction.RecommendedProductClick(aid, url))
},
)
}
@ -137,7 +137,7 @@ private fun ProductReview(
onInfoExpandToggleClick: () -> Unit,
onReviewGradeLearnMoreClick: () -> Unit,
onFooterLinkClick: () -> Unit,
onRecommendedProductClick: (String) -> Unit,
onRecommendedProductClick: (aid: String, url: String) -> Unit,
) {
Crossfade(
targetState = state.productReviewState,

@ -15,6 +15,8 @@ class FakeReviewQualityCheckService(
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 = {},
) : ReviewQualityCheckService {
private var analysisCount = 0
@ -30,5 +32,14 @@ class FakeReviewQualityCheckService(
override suspend fun analysisStatus(): AnalysisStatusDto? = status
override fun selectedTabUrl(): String? = selectedTabUrl
override suspend fun productRecommendation(): ProductRecommendation? = productRecommendation
override suspend fun recordRecommendedProductClick(productAid: String) {
recordClick(productAid)
}
override suspend fun recordRecommendedProductImpression(productAid: String) {
recordImpression(productAid)
}
}

@ -743,6 +743,77 @@ class ReviewQualityCheckStoreTest {
captureActionsMiddleware.assertNotDispatched(ReviewQualityCheckAction.UpdateRecommendedProduct::class)
}
@Test
fun `GIVEN product recommendations are enabled WHEN recommended product is clicked THEN click event is recorded`() =
runTest {
var productClicked: String? = null
val tested = ReviewQualityCheckStore(
middleware = provideReviewQualityCheckMiddleware(
reviewQualityCheckPreferences = FakeReviewQualityCheckPreferences(
isEnabled = true,
isProductRecommendationsEnabled = true,
),
reviewQualityCheckService = FakeReviewQualityCheckService(
productAnalysis = { ProductAnalysisTestData.productAnalysis() },
productRecommendation = ProductRecommendationTestData.productRecommendation(
aid = "342",
),
recordClick = {
productClicked = it
},
),
),
)
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
tested.waitUntilIdle()
tested.dispatch(ReviewQualityCheckAction.FetchProductAnalysis).joinBlocking()
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
tested.dispatch(
ReviewQualityCheckAction.RecommendedProductClick(
productAid = "342",
productUrl = "https://test.com",
),
).joinBlocking()
assertEquals("342", productClicked)
}
@Test
fun `GIVEN product recommendations are enabled WHEN recommended product is viewed THEN impression event is recorded`() =
runTest {
var productViewed: String? = null
val tested = ReviewQualityCheckStore(
middleware = provideReviewQualityCheckMiddleware(
reviewQualityCheckPreferences = FakeReviewQualityCheckPreferences(
isEnabled = true,
isProductRecommendationsEnabled = true,
),
reviewQualityCheckService = FakeReviewQualityCheckService(
productAnalysis = { ProductAnalysisTestData.productAnalysis() },
productRecommendation = ProductRecommendationTestData.productRecommendation(
aid = "342",
),
recordImpression = {
productViewed = it
},
),
),
)
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
tested.waitUntilIdle()
tested.dispatch(ReviewQualityCheckAction.FetchProductAnalysis).joinBlocking()
tested.waitUntilIdle()
dispatcher.scheduler.advanceUntilIdle()
tested.dispatch(
ReviewQualityCheckAction.RecommendedProductImpression(productAid = "342"),
).joinBlocking()
assertEquals("342", productViewed)
}
private fun provideReviewQualityCheckMiddleware(
reviewQualityCheckPreferences: ReviewQualityCheckPreferences = FakeReviewQualityCheckPreferences(),
reviewQualityCheckVendorsService: FakeReviewQualityCheckVendorsService = FakeReviewQualityCheckVendorsService(),

Loading…
Cancel
Save