From 19584bb218023324672bca8d815ff5754c6c454b Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 24 Mar 2025 14:38:38 +0700 Subject: [PATCH 1/8] Add allowMerchantAIAPIKey feature flag --- Experiments/Experiments/DefaultFeatureFlagService.swift | 2 ++ Experiments/Experiments/FeatureFlag.swift | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Experiments/Experiments/DefaultFeatureFlagService.swift b/Experiments/Experiments/DefaultFeatureFlagService.swift index 660b46b3210..2c7a138376d 100644 --- a/Experiments/Experiments/DefaultFeatureFlagService.swift +++ b/Experiments/Experiments/DefaultFeatureFlagService.swift @@ -97,6 +97,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService { return buildConfig == .localDeveloper || buildConfig == .alpha case .notificationSettings: return true + case .allowMerchantAIAPIKey: + return buildConfig == .localDeveloper || buildConfig == .alpha default: return true } diff --git a/Experiments/Experiments/FeatureFlag.swift b/Experiments/Experiments/FeatureFlag.swift index 84e44a7bc0c..54139cb6e66 100644 --- a/Experiments/Experiments/FeatureFlag.swift +++ b/Experiments/Experiments/FeatureFlag.swift @@ -208,4 +208,8 @@ public enum FeatureFlag: Int { /// Supports managing notification settings from the app settings /// case notificationSettings + + /// Allows merchants to use their own API keys for AI-powered features + /// + case allowMerchantAIAPIKey } From af0ff06994c48bdd49388e4dcaa6bd0b72a2dc57 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 24 Mar 2025 15:02:48 +0700 Subject: [PATCH 2/8] Render AI Settings row if eligible. Log tap event --- .../Classes/Analytics/WooAnalyticsStat.swift | 1 + .../Classes/Extensions/UIImage+Woo.swift | 4 +++ .../AI Settings/AISettingsView.swift | 7 +++++ .../ViewRelated/Hub Menu/HubMenu.swift | 4 +++ .../Hub Menu/HubMenuViewModel.swift | 26 +++++++++++++++++++ .../WooCommerce.xcodeproj/project.pbxproj | 12 +++++++++ 6 files changed, 54 insertions(+) create mode 100644 WooCommerce/Classes/ViewRelated/AI Settings/AISettingsView.swift diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 0fccc3acbc8..a4daef8aa11 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -1097,6 +1097,7 @@ enum WooAnalyticsStat: String { case hubMenuSwitchStoreTapped = "hub_menu_switch_store_tapped" case hubMenuOptionTapped = "hub_menu_option_tapped" case hubMenuSettingsTapped = "hub_menu_settings_tapped" + case hubMenuAISettingsTapped = "hub_menu_ai_settings_tapped" // MARK: Coupons case couponsLoaded = "coupons_loaded" diff --git a/WooCommerce/Classes/Extensions/UIImage+Woo.swift b/WooCommerce/Classes/Extensions/UIImage+Woo.swift index 360ca78a48d..809003ead6a 100644 --- a/WooCommerce/Classes/Extensions/UIImage+Woo.swift +++ b/WooCommerce/Classes/Extensions/UIImage+Woo.swift @@ -569,6 +569,10 @@ extension UIImage { return UIImage.gridicon(.cog) } + static var wandAndRaysInverse: UIImage { + return UIImage(systemName: "wand.and.rays.inverse")! + } + static func prologueBackgroundBubbles(tint: UIColor) -> UIImage { let image = UIImage(named: "login-prologue-background-bubbles")! return image.withTintColor(tint) diff --git a/WooCommerce/Classes/ViewRelated/AI Settings/AISettingsView.swift b/WooCommerce/Classes/ViewRelated/AI Settings/AISettingsView.swift new file mode 100644 index 00000000000..b7333dcf909 --- /dev/null +++ b/WooCommerce/Classes/ViewRelated/AI Settings/AISettingsView.swift @@ -0,0 +1,7 @@ +import SwiftUI + +struct AISettingsView: View { + var body: some View { + EmptyView() + } +} diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift index ad0ccaedc7d..c8b805dc843 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift @@ -69,6 +69,8 @@ struct HubMenu: View { ServiceLocator.analytics.track(event: .Blaze.blazeCampaignListEntryPointSelected(source: .menu)) case HubMenuViewModel.PointOfSaleEntryPoint.id: viewModel.showsPOS = true + case HubMenuViewModel.AISettings.id: + ServiceLocator.analytics.track(.hubMenuAISettingsTapped) default: break } @@ -183,6 +185,8 @@ private extension HubMenu { BlazeCampaignListHostingControllerRepresentable(siteID: viewModel.siteID, selectedCampaignID: campaignID) case .blazeCampaignCreation: BlazeCampaignListHostingControllerRepresentable(siteID: viewModel.siteID, startsCampaignCreationOnAppear: true) + case .aiSettings: + AISettingsView() } } .navigationBarTitleDisplayMode(.inline) diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift index f9ec4f2cf57..7752b9ee6a3 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift @@ -16,6 +16,7 @@ extension NSNotification.Name { /// Destination views that the hub menu can navigate to. enum HubMenuNavigationDestination: Hashable { case payments + case aiSettings case settings case blaze case blazeCampaignDetails(campaignID: String) @@ -111,6 +112,10 @@ final class HubMenuViewModel: ObservableObject { @Published private var isSiteEligibleForBlaze = false @Published private var isSiteEligibleForGoogleAds = false @Published private var isSiteEligibleForInbox = false + + private var shouldShowAISettings: Bool { + featureFlagService.isFeatureFlagEnabled(.allowMerchantAIAPIKey) + } private var cancellables: Set = [] @@ -345,6 +350,10 @@ private extension HubMenuViewModel { var items: [HubMenuItem] = [ Payments(iconBadge: shouldShowBadgeOnPayments ? .dot : nil) ] + + if shouldShowAISettings { + items.append(AISettings()) + } if eligibleForGoogleAds { items.append(GoogleAds()) @@ -546,6 +555,23 @@ extension HubMenuViewModel { let navigationDestination: HubMenuNavigationDestination? = .settings } + struct AISettings: HubMenuItem { + static var id = "ai-settings" + + let title: String = "AI Settings" + let description: String = "Manage your store's AI-powered features" + let icon: UIImage = .wandAndRaysInverse + let iconColor: UIColor = .primary + let accessibilityIdentifier: String = "ai-settings" + let trackingOption: String = "ai" + let iconBadge: HubMenuBadgeType? + let navigationDestination: HubMenuNavigationDestination? = .aiSettings + + init(iconBadge: HubMenuBadgeType? = nil) { + self.iconBadge = iconBadge + } + } + struct Payments: HubMenuItem { static var id = "payments" diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index caf14efd206..d115b3aebad 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -1606,6 +1606,7 @@ 68A905012ACCFC13004C71D3 /* CollapsibleProductCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A905002ACCFC13004C71D3 /* CollapsibleProductCard.swift */; }; 68AC9D292ACE598B0042F784 /* ProductImageThumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68AC9D282ACE598B0042F784 /* ProductImageThumbnail.swift */; }; 68AF3C3B2D01481C006F1ED2 /* POSReceiptEligibilityBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68AF3C3A2D01481A006F1ED2 /* POSReceiptEligibilityBanner.swift */; }; + 68B3BA262D9147480000B2F2 /* AISettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68B3BA252D9147440000B2F2 /* AISettingsView.swift */; }; 68B6F22B2ADE7ED500D171FC /* TooltipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68B6F22A2ADE7ED500D171FC /* TooltipView.swift */; }; 68C31B712A8617C500AE5C5A /* NewNoteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68C31B702A8617C500AE5C5A /* NewNoteViewModel.swift */; }; 68C53CBE2C1FE59B00C6D80B /* ItemListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68C53CBD2C1FE59B00C6D80B /* ItemListView.swift */; }; @@ -4777,6 +4778,7 @@ 68A905002ACCFC13004C71D3 /* CollapsibleProductCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsibleProductCard.swift; sourceTree = ""; }; 68AC9D282ACE598B0042F784 /* ProductImageThumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductImageThumbnail.swift; sourceTree = ""; }; 68AF3C3A2D01481A006F1ED2 /* POSReceiptEligibilityBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSReceiptEligibilityBanner.swift; sourceTree = ""; }; + 68B3BA252D9147440000B2F2 /* AISettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AISettingsView.swift; sourceTree = ""; }; 68B6F22A2ADE7ED500D171FC /* TooltipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipView.swift; sourceTree = ""; }; 68C31B702A8617C500AE5C5A /* NewNoteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewNoteViewModel.swift; sourceTree = ""; }; 68C53CBD2C1FE59B00C6D80B /* ItemListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListView.swift; sourceTree = ""; }; @@ -9901,6 +9903,14 @@ path = Analytics; sourceTree = ""; }; + 68B3BA242D91473D0000B2F2 /* AI Settings */ = { + isa = PBXGroup; + children = ( + 68B3BA252D9147440000B2F2 /* AISettingsView.swift */, + ); + path = "AI Settings"; + sourceTree = ""; + }; 68DF5A8B2CB38EC5000154C9 /* Coupons */ = { isa = PBXGroup; children = ( @@ -10740,6 +10750,7 @@ B56DB3EF2049C06D00D4AA8E /* ViewRelated */ = { isa = PBXGroup; children = ( + 68B3BA242D91473D0000B2F2 /* AI Settings */, B626C7192876599B0083820C /* Custom Fields */, 86023FA82B15CA8D00A28F07 /* Themes */, DED91DF72AD78A0C00CDCC53 /* Blaze */, @@ -16862,6 +16873,7 @@ B6C78B90293BAF37008934A1 /* AnalyticsHubLastYearRangeData.swift in Sources */, 314265B12645A07800500598 /* CardReaderSettingsConnectedViewController.swift in Sources */, B57C744520F55BA600EEFC87 /* NSObject+Helpers.swift in Sources */, + 68B3BA262D9147480000B2F2 /* AISettingsView.swift in Sources */, 0269576A23726304001BA0BF /* KeyboardFrameObserver.swift in Sources */, 45CE2D852625D7ED00E3CA00 /* SelectableItemRow.swift in Sources */, CEEC9B6421E7AB850055EEF0 /* AppRatingManager.swift in Sources */, From 31fa8efbca32854d3cad44ead771124a3f7fd8ce Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 24 Mar 2025 15:03:41 +0700 Subject: [PATCH 3/8] switch flag off --- Experiments/Experiments/DefaultFeatureFlagService.swift | 2 +- .../Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Experiments/Experiments/DefaultFeatureFlagService.swift b/Experiments/Experiments/DefaultFeatureFlagService.swift index 2c7a138376d..18d4424252d 100644 --- a/Experiments/Experiments/DefaultFeatureFlagService.swift +++ b/Experiments/Experiments/DefaultFeatureFlagService.swift @@ -98,7 +98,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService { case .notificationSettings: return true case .allowMerchantAIAPIKey: - return buildConfig == .localDeveloper || buildConfig == .alpha + return false default: return true } diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift index 7752b9ee6a3..294b6ff92dd 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift @@ -112,7 +112,7 @@ final class HubMenuViewModel: ObservableObject { @Published private var isSiteEligibleForBlaze = false @Published private var isSiteEligibleForGoogleAds = false @Published private var isSiteEligibleForInbox = false - + private var shouldShowAISettings: Bool { featureFlagService.isFeatureFlagEnabled(.allowMerchantAIAPIKey) } @@ -350,7 +350,7 @@ private extension HubMenuViewModel { var items: [HubMenuItem] = [ Payments(iconBadge: shouldShowBadgeOnPayments ? .dot : nil) ] - + if shouldShowAISettings { items.append(AISettings()) } From 20c7a0b01565c80b08c6642d9bee37fee84f38c2 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 24 Mar 2025 15:14:51 +0700 Subject: [PATCH 4/8] localization --- .../Experiments/DefaultFeatureFlagService.swift | 2 +- .../ViewRelated/Hub Menu/HubMenuViewModel.swift | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Experiments/Experiments/DefaultFeatureFlagService.swift b/Experiments/Experiments/DefaultFeatureFlagService.swift index 18d4424252d..35ad0fc3586 100644 --- a/Experiments/Experiments/DefaultFeatureFlagService.swift +++ b/Experiments/Experiments/DefaultFeatureFlagService.swift @@ -98,7 +98,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService { case .notificationSettings: return true case .allowMerchantAIAPIKey: - return false + return true default: return true } diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift index 294b6ff92dd..c426775ca5d 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift @@ -558,8 +558,8 @@ extension HubMenuViewModel { struct AISettings: HubMenuItem { static var id = "ai-settings" - let title: String = "AI Settings" - let description: String = "Manage your store's AI-powered features" + let title: String = Localization.aiSettings + let description: String = Localization.aiSettingsDescription let icon: UIImage = .wandAndRaysInverse let iconColor: UIColor = .primary let accessibilityIdentifier: String = "ai-settings" @@ -748,6 +748,16 @@ extension HubMenuViewModel { "Payments", comment: "Title of the hub menu payments button") + static let aiSettings = NSLocalizedString( + "hubMenuViewModel.aiSettings", + value: "AI Settings", + comment: "Title of the hub menu AI settings button") + + static let aiSettingsDescription = NSLocalizedString( + "hubMenuViewModel.aiSettingsDescription", + value: "Manage your store's AI-powered features", + comment: "Description of the hub menu AI settings button") + static let paymentsDescription = NSLocalizedString( "Take payments on the go", comment: "Description of the hub menu payments button") From 6b36448c46ec241a2aba57bc21cd79f0de08d7c7 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 24 Mar 2025 15:16:48 +0700 Subject: [PATCH 5/8] switch flag off (again!) --- Experiments/Experiments/DefaultFeatureFlagService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experiments/Experiments/DefaultFeatureFlagService.swift b/Experiments/Experiments/DefaultFeatureFlagService.swift index 35ad0fc3586..18d4424252d 100644 --- a/Experiments/Experiments/DefaultFeatureFlagService.swift +++ b/Experiments/Experiments/DefaultFeatureFlagService.swift @@ -98,7 +98,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService { case .notificationSettings: return true case .allowMerchantAIAPIKey: - return true + return false default: return true } From 780b9452f21aa324c4dce2513564687f7adb373b Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Tue, 25 Mar 2025 20:40:58 +0700 Subject: [PATCH 6/8] make row visible on dev config --- Experiments/Experiments/DefaultFeatureFlagService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experiments/Experiments/DefaultFeatureFlagService.swift b/Experiments/Experiments/DefaultFeatureFlagService.swift index bf54a4582b4..63880ec9c2e 100644 --- a/Experiments/Experiments/DefaultFeatureFlagService.swift +++ b/Experiments/Experiments/DefaultFeatureFlagService.swift @@ -98,7 +98,7 @@ public struct DefaultFeatureFlagService: FeatureFlagService { case .notificationSettings: return true case .allowMerchantAIAPIKey: - return false + return buildConfig == .localDeveloper || buildConfig == .alpha default: return true } From 89f9f4a9c31008a87ec3e9eee241f864ef8f8956 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Tue, 25 Mar 2025 20:42:52 +0700 Subject: [PATCH 7/8] track tap event as existing with better property description --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 1 - WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift | 2 -- WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index a4daef8aa11..0fccc3acbc8 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -1097,7 +1097,6 @@ enum WooAnalyticsStat: String { case hubMenuSwitchStoreTapped = "hub_menu_switch_store_tapped" case hubMenuOptionTapped = "hub_menu_option_tapped" case hubMenuSettingsTapped = "hub_menu_settings_tapped" - case hubMenuAISettingsTapped = "hub_menu_ai_settings_tapped" // MARK: Coupons case couponsLoaded = "coupons_loaded" diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift index 94ea75c375f..b00445937c1 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenu.swift @@ -70,8 +70,6 @@ struct HubMenu: View { ServiceLocator.analytics.track(event: .Blaze.blazeCampaignListEntryPointSelected(source: .menu)) case HubMenuViewModel.PointOfSaleEntryPoint.id: viewModel.showsPOS = true - case HubMenuViewModel.AISettings.id: - ServiceLocator.analytics.track(.hubMenuAISettingsTapped) default: break } diff --git a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift index be70d2655ee..16deb4181a8 100644 --- a/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewModel.swift @@ -573,7 +573,7 @@ extension HubMenuViewModel { let icon: UIImage = .wandAndRaysInverse let iconColor: UIColor = .primary let accessibilityIdentifier: String = "ai-settings" - let trackingOption: String = "ai" + let trackingOption: String = "ai-settings" let iconBadge: HubMenuBadgeType? let navigationDestination: HubMenuNavigationDestination? = .aiSettings From 6060f22c6c1c1f2375d21dcddcb4c28cf9d95f7b Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 26 Mar 2025 10:08:56 +0700 Subject: [PATCH 8/8] Add flag to mock flag service and fix failing tests --- .../WooCommerceTests/Mocks/MockFeatureFlagService.swift | 7 ++++++- .../ViewRelated/HubMenu/HubMenuViewModelTests.swift | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/WooCommerce/WooCommerceTests/Mocks/MockFeatureFlagService.swift b/WooCommerce/WooCommerceTests/Mocks/MockFeatureFlagService.swift index 1456f157030..e612a1a20e1 100644 --- a/WooCommerce/WooCommerceTests/Mocks/MockFeatureFlagService.swift +++ b/WooCommerce/WooCommerceTests/Mocks/MockFeatureFlagService.swift @@ -24,6 +24,7 @@ final class MockFeatureFlagService: FeatureFlagService { var isProductGlobalUniqueIdentifierSupported: Bool var hideSitesInStorePicker: Bool var notificationSettings: Bool + var allowMerchantAIAPIKey: Bool init(isInboxOn: Bool = false, isShowInboxCTAEnabled: Bool = false, @@ -46,7 +47,8 @@ final class MockFeatureFlagService: FeatureFlagService { favoriteProducts: Bool = false, isProductGlobalUniqueIdentifierSupported: Bool = false, hideSitesInStorePicker: Bool = false, - notificationSettings: Bool = false) { + notificationSettings: Bool = false, + allowMerchantAIAPIKey: Bool = false) { self.isInboxOn = isInboxOn self.isShowInboxCTAEnabled = isShowInboxCTAEnabled self.isUpdateOrderOptimisticallyOn = isUpdateOrderOptimisticallyOn @@ -69,6 +71,7 @@ final class MockFeatureFlagService: FeatureFlagService { self.isProductGlobalUniqueIdentifierSupported = isProductGlobalUniqueIdentifierSupported self.hideSitesInStorePicker = hideSitesInStorePicker self.notificationSettings = notificationSettings + self.allowMerchantAIAPIKey = allowMerchantAIAPIKey } func isFeatureFlagEnabled(_ featureFlag: FeatureFlag) -> Bool { @@ -117,6 +120,8 @@ final class MockFeatureFlagService: FeatureFlagService { return hideSitesInStorePicker case .notificationSettings: return notificationSettings + case .allowMerchantAIAPIKey: + return allowMerchantAIAPIKey default: return false } diff --git a/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift b/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift index 67d08d1dcb7..0c41ee9be98 100644 --- a/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/ViewRelated/HubMenu/HubMenuViewModelTests.swift @@ -206,11 +206,13 @@ final class HubMenuViewModelTests: XCTestCase { stores.updateDefaultStore(storeID: sampleSiteID) stores.updateDefaultStore(.fake().copy(siteID: sampleSiteID)) + let featureFlagService = MockFeatureFlagService(allowMerchantAIAPIKey: false) let blazeEligibilityChecker = MockBlazeEligibilityChecker(isSiteEligible: true) // When let viewModel = HubMenuViewModel(siteID: sampleSiteID, tapToPayBadgePromotionChecker: TapToPayBadgePromotionChecker(), + featureFlagService: featureFlagService, stores: stores, blazeEligibilityChecker: blazeEligibilityChecker) @@ -267,11 +269,13 @@ final class HubMenuViewModelTests: XCTestCase { stores.updateDefaultStore(storeID: sampleSiteID) stores.updateDefaultStore(.fake().copy(siteID: sampleSiteID)) + let featureFlagService = MockFeatureFlagService(allowMerchantAIAPIKey: false) let checker = MockGoogleAdsEligibilityChecker(isEligible: true) // When let viewModel = HubMenuViewModel(siteID: sampleSiteID, tapToPayBadgePromotionChecker: TapToPayBadgePromotionChecker(), + featureFlagService: featureFlagService, stores: stores, googleAdsEligibilityChecker: checker) waitUntil { @@ -568,6 +572,7 @@ final class HubMenuViewModelTests: XCTestCase { let blazeEligibilityChecker = MockBlazeEligibilityChecker(isSiteEligible: true) let googleAdsEligibilityChecker = MockGoogleAdsEligibilityChecker(isEligible: true) let inboxEligibilityChecker = MockInboxEligibilityChecker() + let featureFlagService = MockFeatureFlagService(allowMerchantAIAPIKey: false) inboxEligibilityChecker.isEligible = true let stores = MockStoresManager(sessionManager: .makeForTesting()) @@ -578,6 +583,7 @@ final class HubMenuViewModelTests: XCTestCase { let navigationPath = NavigationPath(["testPath1", "testPath2"]) let viewModel = HubMenuViewModel(siteID: sampleSiteID, tapToPayBadgePromotionChecker: TapToPayBadgePromotionChecker(), + featureFlagService: featureFlagService, stores: stores, generalAppSettings: generalAppSettings, inboxEligibilityChecker: inboxEligibilityChecker,