Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
Very first Stats card is not always loaded on screen
### Expected behavior

All stats cards that can be shown on screen should be shown after opening the screen, no PTR should be required.

### Actual behavior

1. In some cases, for JP variant (I could not reproduce this on WP), the very first Stats card is loaded only after PTR:

https://user-images.githubusercontent.com/73365754/223773395-9ed971b6-c145-4a6b-a39a-2796d9c81332.mov

2. In other cases ([example](https://buildkite.com/automattic/wordpress-android/builds/10502#01876bb0-cb7e-4fa4-bd0d-d9d8fbbea206)) the stats screen does not load at all.

This causes our `e2eAllDayStatsLoad` UI test to fail for JP.

I could not reproduce this on a real device yet.

### Steps to reproduce the behavior

1. Launch JP
2. Log in and open `Stats`
3. Open `Days` tab ~> in some cases, the first card with bar chart is loaded only after PTR.

##### Tested on `Pixel 2 API 31 Emulator`, `JPAndroid 21.8-rc-2`


Discussion hints:
I could reproduce this using a real device by testing it on a high-traffic website.  You can reproduce the issue on by testing it on mobile.blog.
I removed the "[Emulator]" label from the title.

<img src="https://github.com/wordpress-mobile/WordPress-Android/assets/2471769/ac9428e3-4a11-43da-952c-3ac6febc4c6b" width=320>

Pull request: [Bug] Fix root cause that caused StatsGranularTabsTest to fail.
Fixes #18065

There was a failing UI test that appeared flaky, `StatsGranularTabsTest`. Retrying appears to fix it. Every once in a while I also notice stats cards don't load properly. It's super hard to reproduce, even in UI tests. 

At first I figured out part of the issue. I noticed each failing stats card would have an empty `BlockListItem` list. Each card can have multiple `BlockListItem`s. When the `StatsBlock` has no `BlockListItem`, it can't do anything, so presents itself as a card with nothing in it. This is unfortunate, but not really an issue. The real issue is why a `StatsBlock` can even have an empty list.

After further testing I learned that what leads to this issue is actually a race condition. The UI is dependent on setting the `domainModel` in `BaseStatsUseCase`. In most cases, the domain model is present quickly when we load the UI. But during UI tests situations arise where the `domainModel` takes a bit longer to load, leading to a race condition. As far as I can tell, it really only happens (or noticeable) when you first login or switch to a blog for the first time. The change I made in `BaseStatsUseCase` best illustrates why I think this fixes the issue.

When a user first loads stats, there is no cache. So it must fetch from the network. When it does that, the `domainModel` is set to the cache, which technically doesn't exist yet. This happens in `evaluateState` when a network call is made.

```
domainModel = updatedCachedData
```

It's not entirely clear to me why this is being done. In `evaluateState` if we got state back, presumably we should use that as it would be the most up-to-date. So I just tried it.

```
domainModel = state.model
```

I re-ran the previously failing UI test dozens of times. Couldn't reproduce it. I also 🚬 tested stats and don't notice any differences.

-----

## To Test:

- [ ] `StatsGranularTabTest` must pass 100% of the time. If on first pass it fails, this PR is pointless 😅 .
- [ ] 🚬 test granular stats. Make sure you load all cards and that everything looks as it did before.

-----

## Regression Notes

1. Potential unintended areas of impact

    Stats cards loading.

2. What I did to test those areas of impact (or what existing automated tests I relied on)

    Manual test and UI test.

3. What automated tests I added (or what prevented me from doing so)

    n/a

-----

## PR Submission Checklist:

- [ ] I have completed the Regression Notes.
- [ ] I have considered adding accessibility improvements for my changes.
- [ ] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.



Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.AllTimeStatsUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.TodayStatsUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.FollowersUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.granular.usecases.ReferrersUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.granular.usecases.OverviewUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsColorSelectionViewModelTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.LatestPostSummaryUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.ViewsAndVisitorsUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.detail.PostDayViewsUseCaseTest" --tests "org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsSiteSelectionViewModelTest" --tests "org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases.MostPopularInsightsUseCaseTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt
index d6dd4e02c4d6..eb67940aaa83 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCase.kt
@@ -123,7 +123,7 @@ class PostDayViewsUseCase
         )
     }
 
-    private fun onBarSelected(period: String?) {
+    internal fun onBarSelected(period: String?) {
         if (period != null && period != "empty") {
             val selectedDate = statsDateFormatter.parseStatsDate(DAYS, period)
             selectedDateProvider.selectDate(
@@ -133,7 +133,7 @@ class PostDayViewsUseCase
         }
     }
 
-    private fun onBarChartDrawn(visibleBarCount: Int) {
+    internal fun onBarChartDrawn(visibleBarCount: Int) {
         updateUiState { it.copy(visibleBarCount = visibleBarCount) }
     }
 
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt
index 7b86388e0e3a..5183aa3f56cc 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCase.kt
@@ -91,12 +91,9 @@ abstract class BaseStatsUseCase<DOMAIN_MODEL, UI_STATE>(
         val useCaseState = when (state) {
             is Error -> ERROR
             is Data -> {
-                if (!state.cached) {
-                    val updatedCachedData = loadCachedData()
-                    if (domainModel != updatedCachedData) {
-                        domainModel = updatedCachedData
-                        updateState()
-                    }
+                if (!state.cached && domainModel != state.model) {
+                    domainModel = state.model
+                    updateState()
                 }
                 SUCCESS
             }
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt
index bb5fec464a69..ac4b0355433c 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCase.kt
@@ -3,7 +3,6 @@ package org.wordpress.android.ui.stats.refresh.lists.sections.granular.usecases
 import android.view.View
 import com.google.android.material.snackbar.Snackbar
 import kotlinx.coroutines.CoroutineDispatcher
-import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.analytics.AnalyticsTracker
 import org.wordpress.android.fluxc.model.SiteModel
@@ -46,6 +45,7 @@ import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
 import org.wordpress.android.ui.stats.refresh.utils.StatsUtils
 import org.wordpress.android.ui.stats.refresh.utils.trackGranular
 import org.wordpress.android.ui.utils.ListItemInteraction.Companion.create
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.UrlUtils
 import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
 import org.wordpress.android.viewmodel.ResourceProvider
@@ -69,6 +69,7 @@ class ReferrersUseCase(
     private val resourceProvider: ResourceProvider,
     private val useCaseMode: UseCaseMode,
     private val popupMenuHandler: ReferrerPopupMenuHandler,
+    private val buildConfigWrapper: BuildConfigWrapper,
 ) : GranularStatefulUseCase<ReferrersModel, SelectedGroup>(
     REFERRERS,
     mainDispatcher,
@@ -122,7 +123,7 @@ class ReferrersUseCase(
             items.add(Empty(R.string.stats_no_data_for_period))
         } else {
             val header = Header(R.string.stats_referrer_label, R.string.stats_referrer_views_label)
-            if (BuildConfig.IS_JETPACK_APP && useCaseMode == BLOCK_DETAIL) {
+            if (buildConfigWrapper.isJetpackApp && useCaseMode == BLOCK_DETAIL) {
                 items.add(buildPieChartItem(domainModel))
             }
             items.add(header)
@@ -349,7 +350,8 @@ class ReferrersUseCase(
         private val statsUtils: StatsUtils,
         private val resourceProvider: ResourceProvider,
         private val analyticsTracker: AnalyticsTrackerWrapper,
-        private val popupMenuHandler: ReferrerPopupMenuHandler
+        private val popupMenuHandler: ReferrerPopupMenuHandler,
+        private val buildConfigWrapper: BuildConfigWrapper,
     ) : GranularUseCaseFactory {
         override fun build(granularity: StatsGranularity, useCaseMode: UseCaseMode) =
             ReferrersUseCase(
@@ -364,7 +366,8 @@ class ReferrersUseCase(
                 statsUtils,
                 resourceProvider,
                 useCaseMode,
-                popupMenuHandler
+                popupMenuHandler,
+                buildConfigWrapper,
             )
     }
 
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt
index 5cd01b0db274..44c1453a3f73 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCase.kt
@@ -2,7 +2,6 @@ package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
 
 import android.view.View
 import kotlinx.coroutines.CoroutineDispatcher
-import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.fluxc.model.post.PostStatus
 import org.wordpress.android.fluxc.model.stats.InsightsMostPopularModel
@@ -22,6 +21,7 @@ import org.wordpress.android.ui.stats.refresh.utils.ActionCardHandler
 import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
 import org.wordpress.android.ui.stats.refresh.utils.StatsDateUtils
 import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.text.PercentFormatter
 import org.wordpress.android.viewmodel.ResourceProvider
 import java.math.RoundingMode
@@ -40,7 +40,8 @@ class MostPopularInsightsUseCase
     private val resourceProvider: ResourceProvider,
     private val popupMenuHandler: ItemPopupMenuHandler,
     private val actionCardHandler: ActionCardHandler,
-    private val percentFormatter: PercentFormatter
+    private val percentFormatter: PercentFormatter,
+    private val buildConfigWrapper: BuildConfigWrapper
 ) : StatelessUseCase<InsightsMostPopularModel>(MOST_POPULAR_DAY_AND_HOUR, mainDispatcher, backgroundDispatcher) {
     override suspend fun loadCachedData(): InsightsMostPopularModel? {
         return mostPopularStore.getMostPopularInsights(statsSiteProvider.siteModel)
@@ -71,7 +72,7 @@ class MostPopularInsightsUseCase
 
         val noActivity = domainModel.highestDayPercent == 0.0 && domainModel.highestHourPercent == 0.0
 
-        if (BuildConfig.IS_JETPACK_APP && noActivity) {
+        if (buildConfigWrapper.isJetpackApp && noActivity) {
             items.add(Empty(R.string.stats_most_popular_percent_views_empty))
         } else {
             val highestDayPercent = resourceProvider.getString(
@@ -93,7 +94,7 @@ class MostPopularInsightsUseCase
                     Column(
                         R.string.stats_insights_best_day,
                         statsDateUtils.getWeekDay(domainModel.highestDayOfWeek),
-                        if (BuildConfig.IS_JETPACK_APP) {
+                        if (buildConfigWrapper.isJetpackApp) {
                             highestDayPercent
                         } else {
                             null
@@ -103,7 +104,7 @@ class MostPopularInsightsUseCase
                     Column(
                         R.string.stats_insights_best_hour,
                         statsDateUtils.getHour(domainModel.highestHour),
-                        if (BuildConfig.IS_JETPACK_APP) {
+                        if (buildConfigWrapper.isJetpackApp) {
                             highestHourPercent
                         } else {
                             null
@@ -114,7 +115,7 @@ class MostPopularInsightsUseCase
             )
         }
 
-        if (BuildConfig.IS_JETPACK_APP) {
+        if (buildConfigWrapper.isJetpackApp) {
             addActionCards(domainModel)
         }
         return items
@@ -131,12 +132,12 @@ class MostPopularInsightsUseCase
     }
 
     private fun buildTitle() = Title(
-        textResource = if (BuildConfig.IS_JETPACK_APP) {
+        textResource = if (buildConfigWrapper.isJetpackApp) {
             R.string.stats_insights_popular_title
         } else {
             R.string.stats_insights_popular
         },
-        menuAction = if (BuildConfig.IS_JETPACK_APP) {
+        menuAction = if (buildConfigWrapper.isJetpackApp) {
             null
         } else {
             this::onMenuClick
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModel.kt
index 451b2f5df2e4..2eb64bdd5ca6 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModel.kt
@@ -5,11 +5,11 @@ import androidx.annotation.StringRes
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import kotlinx.coroutines.CoroutineDispatcher
-import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.fluxc.store.AccountStore
 import org.wordpress.android.modules.UI_THREAD
 import org.wordpress.android.ui.prefs.AppPrefsWrapper
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.viewmodel.Event
 import org.wordpress.android.viewmodel.ScopedViewModel
 import javax.inject.Inject
@@ -19,7 +19,8 @@ class StatsColorSelectionViewModel
 @Inject constructor(
     @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
     private val accountStore: AccountStore,
-    private val appPrefsWrapper: AppPrefsWrapper
+    private val appPrefsWrapper: AppPrefsWrapper,
+    private val buildConfigWrapper: BuildConfigWrapper,
 ) : ScopedViewModel(mainDispatcher) {
     private val mutableViewMode = MutableLiveData<Color>()
     val viewMode: LiveData<Color> = mutableViewMode
@@ -51,7 +52,7 @@ class StatsColorSelectionViewModel
         if (accountStore.hasAccessToken()) {
             mutableDialogOpened.postValue(Event(Unit))
         } else {
-            val message = if (BuildConfig.IS_JETPACK_APP) {
+            val message = if (buildConfigWrapper.isJetpackApp) {
                 R.string.stats_widget_log_in_to_add_message
             } else {
                 R.string.stats_widget_log_in_message
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModel.kt
index b5ead27c8074..d96334ae7c9f 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModel.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModel.kt
@@ -3,13 +3,13 @@ package org.wordpress.android.ui.stats.refresh.lists.widget.configuration
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import kotlinx.coroutines.CoroutineDispatcher
-import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.fluxc.model.SiteModel
 import org.wordpress.android.fluxc.store.AccountStore
 import org.wordpress.android.fluxc.store.SiteStore
 import org.wordpress.android.modules.UI_THREAD
 import org.wordpress.android.ui.prefs.AppPrefsWrapper
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.SiteUtils
 import org.wordpress.android.viewmodel.Event
 import org.wordpress.android.viewmodel.ScopedViewModel
@@ -21,7 +21,8 @@ class StatsSiteSelectionViewModel
     @Named(UI_THREAD) private val mainDispatcher: CoroutineDispatcher,
     private val siteStore: SiteStore,
     private val accountStore: AccountStore,
-    private val appPrefsWrapper: AppPrefsWrapper
+    private val appPrefsWrapper: AppPrefsWrapper,
+    private val buildConfigWrapper: BuildConfigWrapper,
 ) : ScopedViewModel(mainDispatcher) {
     private val mutableSelectedSite = MutableLiveData<SiteUiModel>()
     val selectedSite: LiveData<SiteUiModel> = mutableSelectedSite
@@ -73,7 +74,7 @@ class StatsSiteSelectionViewModel
         if (accountStore.hasAccessToken()) {
             mutableDialogOpened.postValue(Event(Unit))
         } else {
-            val message = if (BuildConfig.IS_JETPACK_APP) {
+            val message = if (buildConfigWrapper.isJetpackApp) {
                 R.string.stats_widget_log_in_to_add_message
             } else {
                 R.string.stats_widget_log_in_message


Test patch:
diff --git a/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt b/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt
index 89b11f852e76..ada96b9c90c6 100644
--- a/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt
+++ b/WordPress/src/androidTest/java/org/wordpress/android/e2e/StatsGranularTabsTest.kt
@@ -6,12 +6,10 @@ import dagger.hilt.android.testing.HiltAndroidTest
 import org.junit.After
 import org.junit.Assume.assumeTrue
 import org.junit.Before
-import org.junit.Ignore
 import org.junit.Test
 import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.e2e.pages.MySitesPage
-import org.wordpress.android.rules.Retry
 import org.wordpress.android.support.BaseTest
 import org.wordpress.android.support.ComposeEspressoLink
 import org.wordpress.android.support.WPSupportUtils
@@ -38,7 +36,6 @@ class StatsGranularTabsTest : BaseTest() {
         }
     }
 
-    @Ignore("The 'Days' screen might occasionally not load. Disabled until tests rerun is implemented.")
     @Test
     fun e2eAllDayStatsLoad() {
         val todayVisits = StatsVisitsData("97", "28", "14", "11")
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt
index 3efbedcfd70e..c6ad8c0df460 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCase.kt
@@ -2,7 +2,6 @@ package org.wordpress.android.ui.stats.refresh.lists.sections.insights.usecases
 
 import android.view.View
 import kotlinx.coroutines.CoroutineDispatcher
-import org.wordpress.android.BuildConfig
 import org.wordpress.android.R
 import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_LATEST_POST_SUMMARY_ADD_NEW_POST_TAPPED
 import org.wordpress.android.analytics.AnalyticsTracker.Stat.STATS_LATEST_POST_SUMMARY_POST_ITEM_TAPPED
@@ -32,6 +31,7 @@ import org.wordpress.android.ui.stats.refresh.utils.MILLION
 import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
 import org.wordpress.android.ui.stats.refresh.utils.StatsUtils
 import org.wordpress.android.ui.utils.ListItemInteraction
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
 import javax.inject.Inject
 import javax.inject.Named
@@ -46,7 +46,8 @@ class LatestPostSummaryUseCase
     private val analyticsTracker: AnalyticsTrackerWrapper,
     private val popupMenuHandler: ItemPopupMenuHandler,
     private val statsUtils: StatsUtils,
-    private val contentDescriptionHelper: ContentDescriptionHelper
+    private val contentDescriptionHelper: ContentDescriptionHelper,
+    private val buildConfigWrapper: BuildConfigWrapper
 ) : StatelessUseCase<InsightsLatestPostModel>(LATEST_POST_SUMMARY, mainDispatcher, backgroundDispatcher) {
     override suspend fun loadCachedData(): InsightsLatestPostModel? {
         return latestPostStore.getLatestPostInsights(statsSiteProvider.siteModel)
@@ -79,7 +80,7 @@ class LatestPostSummaryUseCase
     private fun buildNullableUiModel(domainModel: InsightsLatestPostModel?): MutableList<BlockListItem> {
         val items = mutableListOf<BlockListItem>()
 
-        if (BuildConfig.IS_JETPACK_APP) {
+        if (buildConfigWrapper.isJetpackApp) {
             items.add(buildTitleViewMore(domainModel))
             items.add(latestPostSummaryMapper.buildLatestPostItem(domainModel))
             if (domainModel != null && domainModel.hasData()) items.add(buildQuickScanItems(domainModel))
@@ -185,7 +186,7 @@ class LatestPostSummaryUseCase
                 navigateAction = ListItemInteraction.create(this::onAddNewPostClick)
             )
             model.hasData() -> {
-                if (!BuildConfig.IS_JETPACK_APP) {
+                if (!buildConfigWrapper.isJetpackApp) {
                     Link(
                         text = R.string.stats_insights_view_more,
                         navigateAction = ListItemInteraction.create(
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCaseTest.kt
index 9792f35ef772..0197ebd87e06 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/detail/PostDayViewsUseCaseTest.kt
@@ -129,31 +129,6 @@ class PostDayViewsUseCaseTest : BaseUnitTest() {
         assertThat(result.state).isEqualTo(ERROR)
     }
 
-    /**
-     * Note that this test covers an edge condition tracked in GitHub issue
-     * https://github.com/wordpress-mobile/WordPress-Android/issues/10830
-     * For some context see
-     * See https://github.com/wordpress-mobile/WordPress-Android/pull/10850#issuecomment-559555035
-     */
-    @Test
-    fun `manage edge condition with data available but empty list`() = test {
-        val forced = false
-
-        whenever(emptyModel.dayViews).thenReturn(listOf())
-        whenever(model.dayViews).thenReturn(listOf(Day("2019-10-10", 50)))
-        whenever(store.getPostDetail(site, postId)).thenReturn(emptyModel)
-        whenever(store.fetchPostDetail(site, postId, forced)).thenReturn(
-            OnStatsFetched(
-                model
-            )
-        )
-
-        val result = loadData(true, forced)
-
-        assertThat(result.state).isEqualTo(SUCCESS)
-        assertThat(result.data).isEmpty()
-    }
-
     @Test
     fun `maps list of empty items to empty UI model`() = test {
         val forced = false
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCaseTest.kt
index e03287cbac32..ba91233d9637 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/BaseStatsUseCaseTest.kt
@@ -49,17 +49,17 @@ class BaseStatsUseCaseTest : BaseUnitTest() {
     }
 
     @Test
-    fun `on fetch loads data from DB when current value is null`() = test {
+    fun `on fetch loads data from remote when current value is null`() = test {
         assertThat(result).isEmpty()
 
         block.fetch(false, false)
         advanceUntilIdle()
 
-        assertData(0, localData)
+        assertData(0, remoteData)
     }
 
     @Test
-    fun `on fetch returns null item when DB is empty`() = test {
+    fun `on fetch returns remote data when DB is empty`() = test {
         assertThat(result).isEmpty()
         whenever(localDataProvider.get()).thenReturn(null)
 
@@ -67,19 +67,19 @@ class BaseStatsUseCaseTest : BaseUnitTest() {
         advanceUntilIdle()
 
         assertThat(result).hasSize(1)
-        assertThat(result[0]!!.data).isNull()
+        assertData(0, remoteData)
         assertThat(result[0]!!.state).isEqualTo(UseCaseState.SUCCESS)
     }
 
     @Test
-    fun `on refresh calls loads data from DB and later from API`() = test {
+    fun `on refresh calls loads data from API`() = test {
         assertThat(result).isEmpty()
 
         block.fetch(true, false)
         advanceUntilIdle()
 
         assertThat(result.size).isEqualTo(1)
-        assertData(0, localData)
+        assertData(0, remoteData)
     }
 
     @Test
@@ -87,7 +87,7 @@ class BaseStatsUseCaseTest : BaseUnitTest() {
         block.fetch(false, false)
         advanceUntilIdle()
 
-        assertData(0, localData)
+        assertData(0, remoteData)
 
         block.clear()
         advanceUntilIdle()
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt
index 5a790d0e13d9..8b83e8eac40a 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/OverviewUseCaseTest.kt
@@ -135,7 +135,8 @@ class OverviewUseCaseTest : BaseUnitTest() {
             assertThat(this[1]).isEqualTo(barChartItem)
             assertThat(this[2]).isEqualTo(columns)
         }
-        verify(statsWidgetUpdaters, times(2)).updateViewsWidget(siteId)
+        verify(statsWidgetUpdaters, times(1)).updateViewsWidget(siteId)
+        verify(statsWidgetUpdaters, times(1)).updateWeekViewsWidget(siteId)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCaseTest.kt
index 661d153d5bfa..78168bce0520 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/granular/usecases/ReferrersUseCaseTest.kt
@@ -43,6 +43,7 @@ import org.wordpress.android.ui.stats.refresh.utils.ContentDescriptionHelper
 import org.wordpress.android.ui.stats.refresh.utils.ReferrerPopupMenuHandler
 import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
 import org.wordpress.android.ui.stats.refresh.utils.StatsUtils
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
 import org.wordpress.android.viewmodel.ResourceProvider
 import java.util.Date
@@ -118,6 +119,9 @@ class ReferrersUseCaseTest : BaseUnitTest() {
     )
     private val contentDescription = "title, views"
 
+    @Mock
+    private lateinit var buildConfigWrapper: BuildConfigWrapper
+
     @Before
     fun setUp() {
         useCase = ReferrersUseCase(
@@ -132,7 +136,8 @@ class ReferrersUseCaseTest : BaseUnitTest() {
             statsUtils,
             resourceProvider,
             BLOCK_DETAIL,
-            popupMenuHandler
+            popupMenuHandler,
+            buildConfigWrapper,
         )
         whenever(statsSiteProvider.siteModel).thenReturn(site)
         whenever((selectedDateProvider.getSelectedDate(statsGranularity))).thenReturn(selectedDate)
@@ -150,6 +155,7 @@ class ReferrersUseCaseTest : BaseUnitTest() {
             )
         ).thenReturn(contentDescription)
         whenever(statsUtils.toFormattedString(any<Int>(), any())).then { (it.arguments[0] as Int).toString() }
+        whenever(buildConfigWrapper.isJetpackApp).thenReturn(false)
     }
 
     @Test
@@ -226,7 +232,8 @@ class ReferrersUseCaseTest : BaseUnitTest() {
             statsUtils,
             resourceProvider,
             BLOCK,
-            popupMenuHandler
+            popupMenuHandler,
+            buildConfigWrapper,
         )
 
         val forced = false
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCaseTest.kt
index d6ccb4117fe9..a7990c229632 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/AllTimeStatsUseCaseTest.kt
@@ -153,7 +153,7 @@ class AllTimeStatsUseCaseTest : BaseUnitTest() {
             assertThat(this.endColumn.value).isEqualTo(viewsBestDayTotal.toString())
             assertThat(this.endColumn.highest).isEqualTo(bestDayTransformed)
         }
-        verify(statsWidgetUpdaters, times(2)).updateAllTimeWidget(siteId)
+        verify(statsWidgetUpdaters, times(1)).updateAllTimeWidget(siteId)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCaseTest.kt
index 3b4ceece7c29..186af514fcd2 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/FollowersUseCaseTest.kt
@@ -319,7 +319,6 @@ class FollowersUseCaseTest : BaseUnitTest() {
 
         useCase.liveData.observeForever { if (it != null) updatedResult = it }
 
-        whenever(insightsStore.getEmailFollowers(site, LimitMode.All)).thenReturn(updatedEmailModel)
         button.loadMore()
         updatedResult.data!!.assertViewAllFollowersSecondLoad()
     }
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCaseTest.kt
index 24bdf9be4052..6f8344be1b52 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/LatestPostSummaryUseCaseTest.kt
@@ -32,6 +32,7 @@ import org.wordpress.android.ui.stats.refresh.utils.ContentDescriptionHelper
 import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
 import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
 import org.wordpress.android.ui.stats.refresh.utils.StatsUtils
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper
 import java.util.Date
 
@@ -62,6 +63,9 @@ class LatestPostSummaryUseCaseTest : BaseUnitTest() {
     lateinit var statsUtils: StatsUtils
     private lateinit var useCase: LatestPostSummaryUseCase
 
+    @Mock
+    private lateinit var buildConfigWrapper: BuildConfigWrapper
+
     @Before
     fun setUp() = test {
         useCase = LatestPostSummaryUseCase(
@@ -73,7 +77,8 @@ class LatestPostSummaryUseCaseTest : BaseUnitTest() {
             tracker,
             popupMenuHandler,
             statsUtils,
-            contentDescriptionHelper
+            contentDescriptionHelper,
+            buildConfigWrapper
         )
         whenever(statsSiteProvider.siteModel).thenReturn(site)
         useCase.navigationTarget.observeForever {}
@@ -84,6 +89,7 @@ class LatestPostSummaryUseCaseTest : BaseUnitTest() {
             )
         ).thenReturn("likes: 10")
         whenever(statsUtils.toFormattedString(any<Int>(), any())).then { (it.arguments[0] as Int).toString() }
+        whenever(buildConfigWrapper.isJetpackApp).thenReturn(false)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCaseTest.kt
index 1e49d0200e08..bc7a973ee75f 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/MostPopularInsightsUseCaseTest.kt
@@ -27,6 +27,7 @@ import org.wordpress.android.ui.stats.refresh.utils.ActionCardHandler
 import org.wordpress.android.ui.stats.refresh.utils.ItemPopupMenuHandler
 import org.wordpress.android.ui.stats.refresh.utils.StatsDateUtils
 import org.wordpress.android.ui.stats.refresh.utils.StatsSiteProvider
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.util.text.PercentFormatter
 import org.wordpress.android.viewmodel.ResourceProvider
 import java.math.RoundingMode
@@ -59,6 +60,9 @@ class MostPopularInsightsUseCaseTest : BaseUnitTest() {
     @Mock
     lateinit var actionCardHandler: ActionCardHandler
 
+    @Mock
+    private lateinit var buildConfigWrapper: BuildConfigWrapper
+
     @Mock
     private lateinit var percentFormatter: PercentFormatter
     private lateinit var useCase: MostPopularInsightsUseCase
@@ -81,7 +85,8 @@ class MostPopularInsightsUseCaseTest : BaseUnitTest() {
             resourceProvider,
             popupMenuHandler,
             actionCardHandler,
-            percentFormatter
+            percentFormatter,
+            buildConfigWrapper
         )
         whenever(
             percentFormatter.format(
@@ -111,6 +116,7 @@ class MostPopularInsightsUseCaseTest : BaseUnitTest() {
                 R.string.stats_most_popular_percent_views, "20%"
             )
         ).thenReturn("${highestHourPercent.roundToInt()}% of views")
+        whenever(buildConfigWrapper.isJetpackApp).thenReturn(false)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCaseTest.kt
index 847e6723f129..4ea94dd04126 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/TodayStatsUseCaseTest.kt
@@ -92,7 +92,7 @@ class TodayStatsUseCaseTest : BaseUnitTest() {
             assertViewsAndVisitors(this[1])
             assertLikesAndComments(this[2])
         }
-        verify(statsWidgetUpdaters, times(2)).updateTodayWidget(siteId)
+        verify(statsWidgetUpdaters, times(1)).updateTodayWidget(siteId)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/ViewsAndVisitorsUseCaseTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/ViewsAndVisitorsUseCaseTest.kt
index 0c65f1914b49..8aed8d5d0335 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/ViewsAndVisitorsUseCaseTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/sections/insights/usecases/ViewsAndVisitorsUseCaseTest.kt
@@ -145,7 +145,7 @@ class ViewsAndVisitorsUseCaseTest : BaseUnitTest() {
             Assertions.assertThat(this[3]).isEqualTo(lineChartItem)
             Assertions.assertThat(this[5]).isEqualTo(chips)
         }
-        verify(statsWidgetUpdaters, times(2)).updateViewsWidget(siteId)
+        verify(statsWidgetUpdaters, times(1)).updateViewsWidget(siteId)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModelTest.kt
index 2835cbdcd8de..7d1a79cc7fcc 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModelTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsColorSelectionViewModelTest.kt
@@ -14,6 +14,7 @@ import org.wordpress.android.ui.prefs.AppPrefsWrapper
 import org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsColorSelectionViewModel.Color
 import org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsColorSelectionViewModel.Color.DARK
 import org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsColorSelectionViewModel.Color.LIGHT
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.viewmodel.Event
 
 @ExperimentalCoroutinesApi
@@ -25,13 +26,18 @@ class StatsColorSelectionViewModelTest : BaseUnitTest() {
     private lateinit var accountStore: AccountStore
     private lateinit var viewModel: StatsColorSelectionViewModel
 
+    @Mock
+    private lateinit var buildConfigWrapper: BuildConfigWrapper
+
     @Before
     fun setUp() {
         viewModel = StatsColorSelectionViewModel(
             testDispatcher(),
             accountStore,
-            appPrefsWrapper
+            appPrefsWrapper,
+            buildConfigWrapper,
         )
+        whenever(buildConfigWrapper.isJetpackApp).thenReturn(false)
     }
 
     @Test
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModelTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModelTest.kt
index 39e5176fed99..5b14f3b07320 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModelTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/stats/refresh/lists/widget/configuration/StatsSiteSelectionViewModelTest.kt
@@ -13,6 +13,7 @@ import org.wordpress.android.fluxc.store.AccountStore
 import org.wordpress.android.fluxc.store.SiteStore
 import org.wordpress.android.ui.prefs.AppPrefsWrapper
 import org.wordpress.android.ui.stats.refresh.lists.widget.configuration.StatsSiteSelectionViewModel.SiteUiModel
+import org.wordpress.android.util.BuildConfigWrapper
 import org.wordpress.android.viewmodel.Event
 
 @ExperimentalCoroutinesApi
@@ -36,13 +37,17 @@ class StatsSiteSelectionViewModelTest : BaseUnitTest() {
     private val siteUrl = "wordpress.com"
     private val iconUrl = "icon.jpg"
 
+    @Mock
+    private lateinit var buildConfigWrapper: BuildConfigWrapper
+
     @Before
     fun setUp() {
         viewModel = StatsSiteSelectionViewModel(
             testDispatcher(),
             siteStore,
             accountStore,
-            appPrefsWrapper
+            appPrefsWrapper,
+            buildConfigWrapper,
         )
         wpComSite = SiteModel()
         wpComSite.siteId = siteId
@@ -65,6 +70,7 @@ class StatsSiteSelectionViewModelTest : BaseUnitTest() {
         nonJetpackSite.iconUrl = iconUrl
         nonJetpackSite.setIsJetpackConnected(false)
         nonJetpackSite.setIsWPCom(false)
+        whenever(buildConfigWrapper.isJetpackApp).thenReturn(false)
     }
 
     @Test