Skip to content

Commit 1365091

Browse files
[CIAB] Hide Blaze and Payments from hub menu (#16096)
2 parents c69e785 + c5dc307 commit 1365091

File tree

5 files changed

+166
-23
lines changed

5 files changed

+166
-23
lines changed

WooCommerce/Classes/Blaze/BlazeEligibilityChecker.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ protocol BlazeEligibilityCheckerProtocol {
1313
/// Checks for Blaze eligibility for a site and its products.
1414
final class BlazeEligibilityChecker: BlazeEligibilityCheckerProtocol {
1515
private let stores: StoresManager
16+
private let siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol
1617

17-
init(stores: StoresManager = ServiceLocator.stores) {
18+
init(
19+
stores: StoresManager = ServiceLocator.stores,
20+
siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol = CIABEligibilityChecker()
21+
) {
1822
self.stores = stores
23+
self.siteCIABEligibilityChecker = siteCIABEligibilityChecker
1924
}
2025

2126
/// Checks if the site is eligible for Blaze.
@@ -39,7 +44,11 @@ final class BlazeEligibilityChecker: BlazeEligibilityCheckerProtocol {
3944
private extension BlazeEligibilityChecker {
4045
@MainActor
4146
func checkSiteEligibility(_ site: Site) async -> Bool {
42-
guard site.isAdmin && site.canBlaze else {
47+
guard
48+
site.isAdmin,
49+
site.canBlaze,
50+
siteCIABEligibilityChecker.isFeatureSupported(.blaze, for: site)
51+
else {
4352
return false
4453
}
4554

WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ final class HubMenuViewModel: ObservableObject {
8585
private let inboxEligibilityChecker: InboxEligibilityChecker
8686
private let blazeEligibilityChecker: BlazeEligibilityCheckerProtocol
8787
private let googleAdsEligibilityChecker: GoogleAdsEligibilityChecker
88+
private let siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol
8889

8990
private(set) lazy var inboxViewModel = InboxViewModel(siteID: siteID)
9091

9192
@Published private(set) var shouldShowNewFeatureBadgeOnPayments: Bool = false
9293

94+
@Published private var isSiteEligibleForPayments = false
9395
@Published private var isSiteEligibleForBlaze = false
9496
@Published private var isSiteEligibleForGoogleAds = false
9597
@Published private var isSiteEligibleForInbox = false
@@ -125,6 +127,7 @@ final class HubMenuViewModel: ObservableObject {
125127
inboxEligibilityChecker: InboxEligibilityChecker = InboxEligibilityUseCase(),
126128
blazeEligibilityChecker: BlazeEligibilityCheckerProtocol = BlazeEligibilityChecker(),
127129
googleAdsEligibilityChecker: GoogleAdsEligibilityChecker = DefaultGoogleAdsEligibilityChecker(),
130+
siteCIABEligibilityChecker: CIABEligibilityCheckerProtocol = CIABEligibilityChecker(),
128131
analytics: Analytics = ServiceLocator.analytics) {
129132
self.siteID = siteID
130133
self.credentials = stores.sessionManager.defaultCredentials
@@ -136,6 +139,7 @@ final class HubMenuViewModel: ObservableObject {
136139
self.inboxEligibilityChecker = inboxEligibilityChecker
137140
self.blazeEligibilityChecker = blazeEligibilityChecker
138141
self.googleAdsEligibilityChecker = googleAdsEligibilityChecker
142+
self.siteCIABEligibilityChecker = siteCIABEligibilityChecker
139143
self.cardPresentPaymentsOnboarding = CardPresentPaymentsOnboardingUseCase()
140144
self.analytics = analytics
141145
observeSiteForUIUpdates()
@@ -251,30 +255,55 @@ private extension HubMenuViewModel {
251255
}
252256

253257
func setupGeneralElements() {
254-
$shouldShowNewFeatureBadgeOnPayments
255-
.combineLatest($isSiteEligibleForInbox,
256-
$isSiteEligibleForBlaze,
257-
$isSiteEligibleForGoogleAds)
258-
.map { [weak self] combinedResult -> [HubMenuItem] in
259-
guard let self else { return [] }
260-
let (shouldShowBadgeOnPayments, eligibleForInbox, eligibleForBlaze, eligibleForGoogleAds) = combinedResult
261-
return createGeneralElements(
262-
shouldShowBadgeOnPayments: shouldShowBadgeOnPayments,
263-
eligibleForGoogleAds: eligibleForGoogleAds,
264-
eligibleForBlaze: eligibleForBlaze,
265-
eligibleForInbox: eligibleForInbox
266-
)
267-
}
268-
.assign(to: &$generalElements)
258+
Publishers.CombineLatest(
259+
$shouldShowNewFeatureBadgeOnPayments,
260+
$isSiteEligibleForPayments
261+
)
262+
.combineLatest(
263+
Publishers.CombineLatest3(
264+
$isSiteEligibleForInbox,
265+
$isSiteEligibleForBlaze,
266+
$isSiteEligibleForGoogleAds
267+
)
268+
)
269+
.map { [weak self] combinedResults -> [HubMenuItem] in
270+
guard let self else { return [] }
271+
272+
let ((shouldShowBadgeOnPayments, eligibleForPayments), (eligibleForInbox, eligibleForBlaze, eligibleForGoogleAds)) = combinedResults
273+
274+
let paymentsEligibility: PaymentsFeatureEligibility = eligibleForPayments ?
275+
.eligible(shouldShowBadgeOnPayments: shouldShowBadgeOnPayments) :
276+
.ineligible
277+
278+
return createGeneralElements(
279+
paymentsEligibility: paymentsEligibility,
280+
eligibleForGoogleAds: eligibleForGoogleAds,
281+
eligibleForBlaze: eligibleForBlaze,
282+
eligibleForInbox: eligibleForInbox
283+
)
284+
}
285+
.assign(to: &$generalElements)
286+
}
287+
288+
enum PaymentsFeatureEligibility {
289+
case ineligible
290+
case eligible(shouldShowBadgeOnPayments: Bool)
269291
}
270292

271-
func createGeneralElements(shouldShowBadgeOnPayments: Bool,
293+
func createGeneralElements(paymentsEligibility: PaymentsFeatureEligibility,
272294
eligibleForGoogleAds: Bool,
273295
eligibleForBlaze: Bool,
274296
eligibleForInbox: Bool) -> [HubMenuItem] {
275-
var items: [HubMenuItem] = [
276-
Payments(iconBadge: shouldShowBadgeOnPayments ? .dot : nil)
277-
]
297+
var items: [HubMenuItem] = []
298+
299+
switch paymentsEligibility {
300+
case .ineligible:
301+
break
302+
case .eligible(let shouldShowBadgeOnPayments):
303+
items.append(
304+
Payments(iconBadge: shouldShowBadgeOnPayments ? .dot : nil)
305+
)
306+
}
278307

279308
if shouldShowAISettings {
280309
items.append(AISettings())
@@ -354,7 +383,7 @@ private extension HubMenuViewModel {
354383
}
355384

356385
func updateMenuItemEligibility(with site: Yosemite.Site) {
357-
386+
isSiteEligibleForPayments = siteCIABEligibilityChecker.isFeatureSupported(.payments, for: site)
358387
isSiteEligibleForInbox = inboxEligibilityChecker.isEligibleForInbox(siteID: site.siteID)
359388

360389
Task { @MainActor in

WooCommerce/WooCommerceTests/Mocks/MockCIABEligibilityChecker.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ final class MockCIABEligibilityChecker: CIABEligibilityCheckerProtocol {
2626
}
2727

2828
func isFeatureSupported(_ feature: CIABAffectedFeature, for site: Site) -> Bool {
29-
return !mockedCIABDisabledFeatures.contains(feature) && mockedCIABSites.contains(site)
29+
return !mockedCIABDisabledFeatures.contains(feature) || !mockedCIABSites.contains(site)
3030
}
3131
}

WooCommerce/WooCommerceTests/ViewRelated/Blaze/BlazeEligibilityCheckerTests.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,53 @@ final class BlazeEligibilityCheckerTests: XCTestCase {
131131
XCTAssertTrue(isEligible)
132132
}
133133

134+
@MainActor
135+
func test_isEligible_is_true_when_site_is_non_ciab_and_other_requirements_met() async {
136+
// Given
137+
stores.authenticate(credentials: .wpcom(username: "", authToken: "", siteAddress: ""))
138+
let site = mockSite(isEligibleForBlaze: true,
139+
isJetpackThePluginInstalled: false,
140+
isJetpackConnected: true)
141+
let siteIsCIABChecker = MockCIABEligibilityChecker(
142+
mockedIsCurrentSiteCIAB: false,
143+
)
144+
let blazeEligibilityChecker = BlazeEligibilityChecker(
145+
stores: stores,
146+
siteCIABEligibilityChecker: siteIsCIABChecker
147+
)
148+
mockPluginFetch(remotePlugin: .fake().copy(plugin: Self.pluginSlug, active: true))
149+
150+
// When
151+
let isEligible = await blazeEligibilityChecker.isSiteEligible(site)
152+
153+
// Then
154+
XCTAssertTrue(isEligible)
155+
}
156+
157+
@MainActor
158+
func test_isEligible_is_false_when_site_is_ciab_and_other_requirements_met() async {
159+
// Given
160+
stores.authenticate(credentials: .wpcom(username: "", authToken: "", siteAddress: ""))
161+
let site = mockSite(isEligibleForBlaze: true,
162+
isJetpackThePluginInstalled: false,
163+
isJetpackConnected: true)
164+
let siteIsCIABChecker = MockCIABEligibilityChecker(
165+
mockedIsCurrentSiteCIAB: true,
166+
mockedCIABSites: [site]
167+
)
168+
let blazeEligibilityChecker = BlazeEligibilityChecker(
169+
stores: stores,
170+
siteCIABEligibilityChecker: siteIsCIABChecker
171+
)
172+
mockPluginFetch(remotePlugin: .fake().copy(plugin: Self.pluginSlug, active: true))
173+
174+
// When
175+
let isEligible = await blazeEligibilityChecker.isSiteEligible(site)
176+
177+
// Then
178+
XCTAssertFalse(isEligible)
179+
}
180+
134181
// MARK: - `isProductEligible`
135182

136183
@MainActor

WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,64 @@ final class HubMenuViewModelTests: XCTestCase {
166166
XCTAssertTrue(expectedElementsIDs.isSubset(of: generalElementsIds))
167167
}
168168

169+
@MainActor
170+
func test_generalElements_does_not_include_blaze_when_site_is_CIAB_site() {
171+
// Given
172+
let stores = MockStoresManager(sessionManager: .makeForTesting())
173+
// Setting site ID is required before setting `Site`.
174+
stores.updateDefaultStore(storeID: sampleSiteID)
175+
stores.updateDefaultStore(.fake().copy(siteID: sampleSiteID))
176+
177+
let blazeEligibilityChecker = MockBlazeEligibilityChecker(isSiteEligible: false)
178+
let mockCIABEligibilityChecker = MockCIABEligibilityChecker(
179+
mockedIsCurrentSiteCIAB: true,
180+
mockedCIABSites: [stores.sessionManager.defaultSite ?? .fake()]
181+
)
182+
183+
// When
184+
let viewModel = HubMenuViewModel(
185+
siteID: sampleSiteID,
186+
tapToPayBadgePromotionChecker: TapToPayBadgePromotionChecker(),
187+
stores: stores,
188+
blazeEligibilityChecker: blazeEligibilityChecker,
189+
siteCIABEligibilityChecker: mockCIABEligibilityChecker
190+
)
191+
192+
viewModel.setupMenuElements()
193+
194+
// Then
195+
XCTAssertNil(viewModel.generalElements.firstIndex(where: { $0.id == HubMenuViewModel.Blaze.id }))
196+
}
197+
198+
@MainActor
199+
func test_generalElements_does_not_include_payments_when_site_is_CIAB_site() {
200+
// Given
201+
let stores = MockStoresManager(sessionManager: .makeForTesting())
202+
// Setting site ID is required before setting `Site`.
203+
stores.updateDefaultStore(storeID: sampleSiteID)
204+
stores.updateDefaultStore(.fake().copy(siteID: sampleSiteID))
205+
206+
let blazeEligibilityChecker = MockBlazeEligibilityChecker(isSiteEligible: false)
207+
let mockCIABEligibilityChecker = MockCIABEligibilityChecker(
208+
mockedIsCurrentSiteCIAB: true,
209+
mockedCIABSites: [stores.sessionManager.defaultSite ?? .fake()]
210+
)
211+
212+
// When
213+
let viewModel = HubMenuViewModel(
214+
siteID: sampleSiteID,
215+
tapToPayBadgePromotionChecker: TapToPayBadgePromotionChecker(),
216+
stores: stores,
217+
blazeEligibilityChecker: blazeEligibilityChecker,
218+
siteCIABEligibilityChecker: mockCIABEligibilityChecker
219+
)
220+
221+
viewModel.setupMenuElements()
222+
223+
// Then
224+
XCTAssertNil(viewModel.generalElements.firstIndex(where: { $0.id == HubMenuViewModel.Payments.id }))
225+
}
226+
169227
@MainActor
170228
func test_generalElements_does_not_include_blaze_when_default_site_is_not_set() {
171229
// When

0 commit comments

Comments
 (0)