Skip to content

Commit

Permalink
Merge pull request #10262 from woocommerce/issue/10259-dashboard-erro…
Browse files Browse the repository at this point in the history
…r-banner

[My store] Fix error banner so it appears when stats data can't be loaded
  • Loading branch information
rachelmcr authored Jul 20, 2023
2 parents 364a95d + 519ae01 commit 6a158b5
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 4 deletions.
2 changes: 2 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
- [*] Orders with Coupons: Users can now select a coupon from a list when adding it to an order. [https://github.com/woocommerce/woocommerce-ios/pull/10255]
- [Internal] Orders: Improved error message when orders can't be loaded due to a parsing (decoding) error. [https://github.com/woocommerce/woocommerce-ios/pull/10252]
- [**] Product discounts: Users can now add discounts to products when creating an order. [https://github.com/woocommerce/woocommerce-ios/pull/10244]
- [Internal] Fixed a bug preventing the "We couldn't load your data" error banner from appearing on the My store dashboard. [https://github.com/woocommerce/woocommerce-ios/pull/10262]

- [Internal] A new way to create a product from an image using AI is being A/B tested. [https://github.com/woocommerce/woocommerce-ios/pull/10253]

14.5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ private extension DashboardViewController {

func onPullToRefresh() async {
ServiceLocator.analytics.track(.dashboardPulledToRefresh)
hideTopBannerView() // Hide error banner optimistically on pull to refresh
await withTaskGroup(of: Void.self) { group in
group.addTask { [weak self] in
guard let self else { return }
Expand Down
10 changes: 10 additions & 0 deletions WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ final class DashboardViewModel {
timeRange: StatsTimeRangeV4,
latestDateToInclude: Date,
onCompletion: ((Result<Void, Error>) -> Void)? = nil) {
guard stores.isAuthenticatedWithoutWPCom == false else { // Visit stats are only available for stores connected to WPCom
onCompletion?(.success(()))
return
}

let action = StatsActionV4.retrieveSiteVisitStats(siteID: siteID,
siteTimezone: siteTimezone,
timeRange: timeRange,
Expand All @@ -132,6 +137,11 @@ final class DashboardViewModel {
timeRange: StatsTimeRangeV4,
latestDateToInclude: Date,
onCompletion: ((Result<Void, Error>) -> Void)? = nil) {
guard stores.isAuthenticatedWithoutWPCom == false else { // Summary stats are only available for stores connected to WPCom
onCompletion?(.success(()))
return
}

let action = StatsActionV4.retrieveSiteSummaryStats(siteID: siteID,
siteTimezone: siteTimezone,
period: timeRange.summaryStatsGranularity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ private extension StoreStatsAndTopPerformersViewController {
DDLogError("⛔️ Error synchronizing order stats: \(error)")
periodSyncError = error
}
group.leave()
periodGroup.leave()
periodStoreStatsGroup.leave()
group.leave() // Leave this group last so `syncError` is set, if needed
}

group.enter()
Expand All @@ -254,9 +254,9 @@ private extension StoreStatsAndTopPerformersViewController {
DDLogError("⛔️ Error synchronizing visitor stats: \(error)")
periodSyncError = error
}
group.leave()
periodGroup.leave()
periodStoreStatsGroup.leave()
group.leave() // Leave this group last so `syncError` is set, if needed
}

group.enter()
Expand All @@ -270,9 +270,9 @@ private extension StoreStatsAndTopPerformersViewController {
DDLogError("⛔️ Error synchronizing summary stats: \(error)")
periodSyncError = error
}
group.leave()
periodGroup.leave()
periodStoreStatsGroup.leave()
group.leave() // Leave this group last so `syncError` is set, if needed
}

group.enter()
Expand All @@ -286,8 +286,8 @@ private extension StoreStatsAndTopPerformersViewController {
DDLogError("⛔️ Error synchronizing top earners stats: \(error)")
periodSyncError = error
}
group.leave()
periodGroup.leave()
group.leave() // Leave this group last so `syncError` is set, if needed

vc.removeTopPerformersGhostContent()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,36 @@ final class DashboardViewModelTests: XCTestCase {
let dictionary = try XCTUnwrap(userDefaults[.hasDismissedBlazeBanner] as? [String: Bool])
XCTAssertEqual(dictionary["\(sampleSiteID)"], true)
}

func test_wpcom_stats_not_synced_when_authenticated_without_wpcom() {
// Given
stores = MockStoresManager(sessionManager: .makeForTesting(authenticated: true, isWPCom: false))
stores.whenReceivingAction(ofType: StatsActionV4.self) { action in
switch action {
case .retrieveSiteVisitStats, .retrieveSiteSummaryStats:
XCTFail("WPCom stats should not be synced when store is authenticated without WPCom")
default:
XCTFail("Received unsupported action: \(action)")
}
}
let viewModel = DashboardViewModel(siteID: sampleSiteID, stores: stores)

// When
let siteVisitStatsResult: Result<Void, Error> = waitFor { promise in
viewModel.syncSiteVisitStats(for: self.sampleSiteID, siteTimezone: .current, timeRange: .thisMonth, latestDateToInclude: .init()) { result in
promise(result)
}
}
let siteSummaryStatsResult: Result<Void, Error> = waitFor { promise in
viewModel.syncSiteSummaryStats(for: self.sampleSiteID, siteTimezone: .current, timeRange: .thisMonth, latestDateToInclude: .init()) { result in
promise(result)
}
}

// Then
XCTAssertTrue(siteVisitStatsResult.isSuccess)
XCTAssertTrue(siteSummaryStatsResult.isSuccess)
}
}

private extension DashboardViewModelTests {
Expand Down

0 comments on commit 6a158b5

Please sign in to comment.