Skip to content

Commit 85234dd

Browse files
authored
Merge pull request #8471 from woocommerce/issue/8470-decouple-tracks-and-analytics-views
2 parents 9e4f46c + 04f07cf commit 85234dd

File tree

7 files changed

+75
-18
lines changed

7 files changed

+75
-18
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubViewModel.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ final class AnalyticsHubViewModel: ObservableObject {
99

1010
private let siteID: Int64
1111
private let stores: StoresManager
12+
private let analytics: Analytics
1213

1314
private var subscriptions = Set<AnyCancellable>()
1415

@@ -19,15 +20,19 @@ final class AnalyticsHubViewModel: ObservableObject {
1920
init(siteID: Int64,
2021
statsTimeRange: StatsTimeRangeV4,
2122
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter,
22-
stores: StoresManager = ServiceLocator.stores) {
23+
stores: StoresManager = ServiceLocator.stores,
24+
analytics: Analytics = ServiceLocator.analytics) {
2325
let selectedType = AnalyticsHubTimeRangeSelection.SelectionType(statsTimeRange)
2426
let timeRangeSelection = AnalyticsHubTimeRangeSelection(selectionType: selectedType)
2527

2628
self.siteID = siteID
2729
self.stores = stores
30+
self.analytics = analytics
2831
self.timeRangeSelectionType = selectedType
2932
self.timeRangeSelection = timeRangeSelection
30-
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: timeRangeSelection, usageTracksEventEmitter: usageTracksEventEmitter)
33+
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: timeRangeSelection,
34+
usageTracksEventEmitter: usageTracksEventEmitter,
35+
analytics: analytics)
3136
self.usageTracksEventEmitter = usageTracksEventEmitter
3237

3338
bindViewModelsWithData()
@@ -286,7 +291,8 @@ private extension AnalyticsHubViewModel {
286291
guard let self else { return }
287292
self.timeRangeSelection = AnalyticsHubTimeRangeSelection(selectionType: newSelectionType)
288293
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: self.timeRangeSelection,
289-
usageTracksEventEmitter: self.usageTracksEventEmitter)
294+
usageTracksEventEmitter: self.usageTracksEventEmitter,
295+
analytics: self.analytics)
290296

291297
// Update data on range selection change
292298
Task.init {
@@ -386,11 +392,19 @@ private extension AnalyticsHubViewModel {
386392
}
387393

388394
static func timeRangeCard(timeRangeSelection: AnalyticsHubTimeRangeSelection,
389-
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter) -> AnalyticsTimeRangeCardViewModel {
395+
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter,
396+
analytics: Analytics) -> AnalyticsTimeRangeCardViewModel {
390397
return AnalyticsTimeRangeCardViewModel(selectedRangeTitle: timeRangeSelection.rangeSelectionDescription,
391398
currentRangeSubtitle: timeRangeSelection.currentRangeDescription,
392399
previousRangeSubtitle: timeRangeSelection.previousRangeDescription,
393-
usageTracksEventEmitter: usageTracksEventEmitter)
400+
onTapped: {
401+
usageTracksEventEmitter.interacted()
402+
analytics.track(event: .AnalyticsHub.dateRangeButtonTapped())
403+
},
404+
onSelected: { selection in
405+
usageTracksEventEmitter.interacted()
406+
analytics.track(event: .AnalyticsHub.dateRangeOptionSelected(selection.tracksIdentifier))
407+
})
394408
}
395409
}
396410

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsTimeRangeCard.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,20 @@ struct AnalyticsTimeRangeCard: View {
1717
///
1818
@State private var showCustomRangeSelectionView: Bool = false
1919

20-
private let usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter
20+
/// Closure invoked when the time range card is tapped.
21+
///
22+
private var onTapped: () -> Void
23+
24+
/// Closure invoked when a time range is selected.
25+
///
26+
private var onSelected: (Range) -> Void
2127

2228
init(viewModel: AnalyticsTimeRangeCardViewModel, selectionType: Binding<AnalyticsHubTimeRangeSelection.SelectionType>) {
2329
self.timeRangeTitle = viewModel.selectedRangeTitle
2430
self.currentRangeDescription = viewModel.currentRangeSubtitle
2531
self.previousRangeDescription = viewModel.previousRangeSubtitle
26-
self.usageTracksEventEmitter = viewModel.usageTracksEventEmitter
32+
self.onSelected = viewModel.onSelected
33+
self.onTapped = viewModel.onTapped
2734
self._selectionType = selectionType
2835
}
2936

@@ -34,8 +41,7 @@ struct AnalyticsTimeRangeCard: View {
3441
items: Range.allCases,
3542
contentKeyPath: \.description,
3643
selected: internalSelectionBinding()) { selection in
37-
usageTracksEventEmitter.interacted()
38-
ServiceLocator.analytics.track(event: .AnalyticsHub.dateRangeOptionSelected(selection.tracksIdentifier))
44+
onSelected(selection)
3945
}
4046
.sheet(isPresented: $showCustomRangeSelectionView) {
4147
RangedDatePicker(startDate: selectionType.startDate, endDate: selectionType.endDate, datesFormatter: DatesFormatter()) { start, end in
@@ -49,9 +55,8 @@ struct AnalyticsTimeRangeCard: View {
4955
private func createTimeRangeContent() -> some View {
5056
VStack(alignment: .leading, spacing: Layout.verticalSpacing) {
5157
Button(action: {
52-
usageTracksEventEmitter.interacted()
53-
ServiceLocator.analytics.track(event: .AnalyticsHub.dateRangeButtonTapped())
5458
showTimeRangeSelectionView.toggle()
59+
onTapped()
5560
}, label: {
5661
HStack {
5762
Image(uiImage: .calendar)
@@ -152,8 +157,7 @@ struct TimeRangeCard_Previews: PreviewProvider {
152157
static var previews: some View {
153158
let viewModel = AnalyticsTimeRangeCardViewModel(selectedRangeTitle: "Month to Date",
154159
currentRangeSubtitle: "Nov 1 - 23, 2022",
155-
previousRangeSubtitle: "Oct 1 - 23, 2022",
156-
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter())
160+
previousRangeSubtitle: "Oct 1 - 23, 2022")
157161
AnalyticsTimeRangeCard(viewModel: viewModel, selectionType: .constant(.monthToDate))
158162
}
159163
}

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsTimeRangeCardViewModel.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ struct AnalyticsTimeRangeCardViewModel {
1616
///
1717
let previousRangeSubtitle: String
1818

19-
/// Analytics Usage Tracks Event Emitter
19+
/// Closure invoked when the time range card is tapped.
2020
///
21-
let usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter
21+
var onTapped: () -> Void = {}
22+
23+
/// Closure invoked when a time range is selected.
24+
///
25+
var onSelected: (AnalyticsTimeRangeCard.Range) -> Void = { _ in }
2226
}

WooCommerce/Classes/ViewRelated/Dashboard/Stats v4/StoreStatsAndTopPerformersPeriodViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ private extension StoreStatsAndTopPerformersPeriodViewController {
358358
}
359359

360360
@objc func seeMoreButtonTapped() {
361-
ServiceLocator.analytics.track(event: .AnalyticsHub.seeMoreAnalyticsTapped())
361+
viewModel.trackSeeMoreButtonTapped()
362362
let analyticsHubVC = AnalyticsHubHostingViewController(siteID: siteID, timeRange: timeRange, usageTracksEventEmitter: usageTracksEventEmitter)
363363
show(analyticsHubVC, sender: self)
364364
}

WooCommerce/Classes/ViewRelated/Dashboard/Stats v4/StoreStatsAndTopPerformersPeriodViewModel.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ final class StoreStatsAndTopPerformersPeriodViewModel {
6161
storesManager.dispatch(action)
6262
}
6363

64+
/// Tracks when the Analytics "See More" button is tapped
65+
///
66+
func trackSeeMoreButtonTapped() {
67+
analytics.track(event: .AnalyticsHub.seeMoreAnalyticsTapped())
68+
}
69+
70+
// MARK: Private helpers
71+
6472
/// Calculates and updates the value of `isInAppFeedbackCardVisible`.
6573
private func refreshIsInAppFeedbackCardVisibleValue() {
6674
// Abort right away if we don't need to calculate the real value.

WooCommerce/WooCommerceTests/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubViewModelTests.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ final class AnalyticsHubViewModelTests: XCTestCase {
66

77
private var stores: MockStoresManager!
88
private var eventEmitter: StoreStatsUsageTracksEventEmitter!
9+
private var analyticsProvider: MockAnalyticsProvider!
10+
private var analytics: Analytics!
911

1012
override func setUp() {
1113
stores = MockStoresManager(sessionManager: .makeForTesting())
12-
let analyticsProvider = MockAnalyticsProvider()
13-
let analytics = WooAnalytics(analyticsProvider: analyticsProvider)
14+
analyticsProvider = MockAnalyticsProvider()
15+
analytics = WooAnalytics(analyticsProvider: analyticsProvider)
1416
eventEmitter = StoreStatsUsageTracksEventEmitter(analytics: analytics)
1517
}
1618

@@ -167,4 +169,18 @@ final class AnalyticsHubViewModelTests: XCTestCase {
167169
// Then
168170
XCTAssertTrue(vm.showSessionsCard)
169171
}
172+
173+
func test_time_range_card_tracks_expected_events() throws {
174+
// Given
175+
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .today, usageTracksEventEmitter: eventEmitter, analytics: analytics)
176+
177+
// When
178+
vm.timeRangeCard.onTapped()
179+
vm.timeRangeCard.onSelected(.weekToDate)
180+
181+
// Then
182+
assertEqual(["analytics_hub_date_range_button_tapped", "analytics_hub_date_range_option_selected"], analyticsProvider.receivedEvents)
183+
let optionSelectedEventProperty = try XCTUnwrap(analyticsProvider.receivedProperties.last?["option"] as? String)
184+
assertEqual("Week to Date", optionSelectedEventProperty)
185+
}
170186
}

WooCommerce/WooCommerceTests/ViewRelated/Dashboard/Stats V4/StoreStatsAndTopPerformersPeriodViewModelTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,17 @@ final class StoreStatsAndTopPerformersPeriodViewModelTests: XCTestCase {
204204
// Then
205205
XCTAssertEqual([false, true, false], emittedValues)
206206
}
207+
208+
func test_trackSeeMoreButtonTapped_tracks_expected_event() {
209+
// Given
210+
let viewModel = makeViewModel()
211+
212+
// When
213+
viewModel.trackSeeMoreButtonTapped()
214+
215+
// Then
216+
assertEqual(["dashboard_see_more_analytics_tapped"], analyticsProvider.receivedEvents)
217+
}
207218
}
208219

209220
private extension StoreStatsAndTopPerformersPeriodViewModelTests {

0 commit comments

Comments
 (0)