diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index 0a5d2886ca..2863f90b3c 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -87,6 +87,7 @@ import os.log private var autofillPixelReporter: AutofillPixelReporter? private var autofillUsageMonitor = AutofillUsageMonitor() + private(set) var subscriptionFeatureAvailability: SubscriptionFeatureAvailability! var privacyProDataReporter: PrivacyProDataReporting! // MARK: lifecycle @@ -302,6 +303,10 @@ import os.log ) remoteMessagingClient.registerBackgroundRefreshTaskHandler() + subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability( + privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, + purchasePlatform: .appStore) + homePageConfiguration = HomePageConfiguration(variantManager: AppDependencyProvider.shared.variantManager, remoteMessagingClient: remoteMessagingClient, privacyProDataReporter: privacyProDataReporter) @@ -336,7 +341,8 @@ import os.log variantManager: variantManager, contextualOnboardingPresenter: contextualOnboardingPresenter, contextualOnboardingLogic: daxDialogs, - contextualOnboardingPixelReporter: onboardingPixelReporter) + contextualOnboardingPixelReporter: onboardingPixelReporter, + subscriptionFeatureAvailability: subscriptionFeatureAvailability) main.loadViewIfNeeded() syncErrorHandler.alertPresenter = main diff --git a/DuckDuckGo/AppDependencyProvider.swift b/DuckDuckGo/AppDependencyProvider.swift index c25532703b..196ded5082 100644 --- a/DuckDuckGo/AppDependencyProvider.swift +++ b/DuckDuckGo/AppDependencyProvider.swift @@ -41,7 +41,6 @@ protocol DependencyProvider { var configurationManager: ConfigurationManager { get } var configurationStore: ConfigurationStore { get } var userBehaviorMonitor: UserBehaviorMonitor { get } - var subscriptionFeatureAvailability: SubscriptionFeatureAvailability { get } var subscriptionManager: SubscriptionManager { get } var accountManager: AccountManager { get } var vpnFeatureVisibility: DefaultNetworkProtectionVisibility { get } @@ -75,10 +74,6 @@ final class AppDependencyProvider: DependencyProvider { let userBehaviorMonitor = UserBehaviorMonitor() - let subscriptionFeatureAvailability: SubscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability( - privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, - purchasePlatform: .appStore) - // Subscription let subscriptionManager: SubscriptionManager var accountManager: AccountManager { @@ -125,9 +120,6 @@ final class AppDependencyProvider: DependencyProvider { self.subscriptionManager = subscriptionManager - let subscriptionFeatureAvailability: SubscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability( - privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, - purchasePlatform: .appStore) let accessTokenProvider: () -> String? = { return { accountManager.accessToken } }() diff --git a/DuckDuckGo/MainViewController+Segues.swift b/DuckDuckGo/MainViewController+Segues.swift index cd05ecddb1..6ac0a7cadc 100644 --- a/DuckDuckGo/MainViewController+Segues.swift +++ b/DuckDuckGo/MainViewController+Segues.swift @@ -307,6 +307,7 @@ extension MainViewController { let settingsViewModel = SettingsViewModel(legacyViewProvider: legacyViewProvider, subscriptionManager: AppDependencyProvider.shared.subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, deepLink: deepLinkTarget, historyManager: historyManager, syncPausedStateManager: syncPausedStateManager, diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 7a12ccf70a..a916d8320a 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -125,6 +125,7 @@ class MainViewController: UIViewController { private var vpnCancellables = Set() private var feedbackCancellable: AnyCancellable? + let subscriptionFeatureAvailability: SubscriptionFeatureAvailability let privacyProDataReporter: PrivacyProDataReporting private lazy var featureFlagger = AppDependencyProvider.shared.featureFlagger @@ -195,7 +196,8 @@ class MainViewController: UIViewController { contextualOnboardingLogic: ContextualOnboardingLogic, contextualOnboardingPixelReporter: OnboardingPixelReporting, tutorialSettings: TutorialSettings = DefaultTutorialSettings(), - statisticsStore: StatisticsStore = StatisticsUserDefaults() + statisticsStore: StatisticsStore = StatisticsUserDefaults(), + subscriptionFeatureAvailability: SubscriptionFeatureAvailability ) { self.bookmarksDatabase = bookmarksDatabase self.bookmarksDatabaseCleaner = bookmarksDatabaseCleaner @@ -226,6 +228,7 @@ class MainViewController: UIViewController { self.contextualOnboardingLogic = contextualOnboardingLogic self.contextualOnboardingPixelReporter = contextualOnboardingPixelReporter self.statisticsStore = statisticsStore + self.subscriptionFeatureAvailability = subscriptionFeatureAvailability super.init(nibName: nil, bundle: nil) diff --git a/DuckDuckGo/NetworkProtectionRootView.swift b/DuckDuckGo/NetworkProtectionRootView.swift index 267be495cf..974c03022c 100644 --- a/DuckDuckGo/NetworkProtectionRootView.swift +++ b/DuckDuckGo/NetworkProtectionRootView.swift @@ -28,9 +28,8 @@ struct NetworkProtectionRootView: View { init() { let accountManager = AppDependencyProvider.shared.subscriptionManager.accountManager - let subscriptionFeatureAvailability = AppDependencyProvider.shared.subscriptionFeatureAvailability let locationListRepository = NetworkProtectionLocationListCompositeRepository(accountManager: accountManager) - let usesUnifiedFeedbackForm = accountManager.isUserAuthenticated && subscriptionFeatureAvailability.usesUnifiedFeedbackForm + let usesUnifiedFeedbackForm = accountManager.isUserAuthenticated statusViewModel = NetworkProtectionStatusViewModel(tunnelController: AppDependencyProvider.shared.networkProtectionTunnelController, settings: AppDependencyProvider.shared.vpnSettings, statusObserver: AppDependencyProvider.shared.connectionObserver, diff --git a/DuckDuckGo/SettingsRootView.swift b/DuckDuckGo/SettingsRootView.swift index 7bb093b578..0378363566 100644 --- a/DuckDuckGo/SettingsRootView.swift +++ b/DuckDuckGo/SettingsRootView.swift @@ -116,12 +116,14 @@ struct SettingsRootView: View { SubscriptionContainerViewFactory.makeSubscribeFlow(origin: origin, navigationCoordinator: subscriptionNavigationCoordinator, subscriptionManager: AppDependencyProvider.shared.subscriptionManager, + subscriptionFeatureAvailability: viewModel.subscriptionFeatureAvailability, privacyProDataReporter: viewModel.privacyProDataReporter) .environmentObject(subscriptionNavigationCoordinator) case .restoreFlow: SubscriptionContainerViewFactory.makeEmailFlow(navigationCoordinator: subscriptionNavigationCoordinator, subscriptionManager: AppDependencyProvider.shared.subscriptionManager, + subscriptionFeatureAvailability: viewModel.subscriptionFeatureAvailability, onDisappear: {}) case .duckPlayer: SettingsDuckPlayerView().environmentObject(viewModel) diff --git a/DuckDuckGo/SettingsSubscriptionView.swift b/DuckDuckGo/SettingsSubscriptionView.swift index 67fa9f4faa..6c22e97d9d 100644 --- a/DuckDuckGo/SettingsSubscriptionView.swift +++ b/DuckDuckGo/SettingsSubscriptionView.swift @@ -34,7 +34,7 @@ struct SettingsSubscriptionView: View { static let privacyPolicyURL = URL(string: "https://duckduckgo.com/pro/privacy-terms")! } - @EnvironmentObject var viewModel: SettingsViewModel + @EnvironmentObject var settingsViewModel: SettingsViewModel @EnvironmentObject var subscriptionNavigationCoordinator: SubscriptionNavigationCoordinator @State var isShowingDBP = false @State var isShowingITP = false @@ -46,7 +46,8 @@ struct SettingsSubscriptionView: View { var subscriptionRestoreView: some View { SubscriptionContainerViewFactory.makeRestoreFlow(navigationCoordinator: subscriptionNavigationCoordinator, - subscriptionManager: subscriptionManager) + subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: settingsViewModel.subscriptionFeatureAvailability) } private var manageSubscriptionView: some View { @@ -117,7 +118,7 @@ struct SettingsSubscriptionView: View { // Renew Subscription (Expired) let settingsView = SubscriptionSettingsView(configuration: .expired, - settingsViewModel: viewModel, + settingsViewModel: settingsViewModel, viewPlans: { subscriptionNavigationCoordinator.shouldPushSubscriptionWebView = true }) @@ -138,7 +139,7 @@ struct SettingsSubscriptionView: View { // Renew Subscription (Expired) let settingsView = SubscriptionSettingsView(configuration: .activating, - settingsViewModel: viewModel, + settingsViewModel: settingsViewModel, viewPlans: { subscriptionNavigationCoordinator.shouldPushSubscriptionWebView = true }) @@ -155,17 +156,17 @@ struct SettingsSubscriptionView: View { @ViewBuilder private var subscriptionDetailsView: some View { - if viewModel.state.subscription.entitlements.contains(.networkProtection) { + if settingsViewModel.state.subscription.entitlements.contains(.networkProtection) { NavigationLink(destination: NetworkProtectionRootView(), isActive: $isShowingVPN) { SettingsCellView( label: UserText.settingsPProVPNTitle, image: Image("SettingsPrivacyProVPN"), - statusIndicator: StatusIndicatorView(status: viewModel.state.networkProtectionConnected ? .on : .off) + statusIndicator: StatusIndicatorView(status: settingsViewModel.state.networkProtectionConnected ? .on : .off) ) } } - if viewModel.state.subscription.entitlements.contains(.dataBrokerProtection) { + if settingsViewModel.state.subscription.entitlements.contains(.dataBrokerProtection) { NavigationLink(destination: SubscriptionPIRView(), isActive: $isShowingDBP) { SettingsCellView( label: UserText.settingsPProDBPTitle, @@ -175,7 +176,7 @@ struct SettingsSubscriptionView: View { } } - if viewModel.state.subscription.entitlements.contains(.identityTheftRestoration) { + if settingsViewModel.state.subscription.entitlements.contains(.identityTheftRestoration) { NavigationLink( destination: SubscriptionITPView(), isActive: $isShowingITP) { @@ -187,10 +188,8 @@ struct SettingsSubscriptionView: View { } } - NavigationLink( - destination: SubscriptionSettingsView(configuration: .subscribed, - settingsViewModel: viewModel) - .environmentObject(subscriptionNavigationCoordinator) + NavigationLink(destination: SubscriptionSettingsView(configuration: .subscribed, settingsViewModel: settingsViewModel) + .environmentObject(subscriptionNavigationCoordinator) ) { SettingsCustomCell(content: { manageSubscriptionView }) } @@ -200,9 +199,9 @@ struct SettingsSubscriptionView: View { Group { if isShowingPrivacyPro { - let isSignedIn = viewModel.state.subscription.isSignedIn - let hasActiveSubscription = viewModel.state.subscription.hasActiveSubscription - let hasNoEntitlements = viewModel.state.subscription.entitlements.isEmpty + let isSignedIn = settingsViewModel.state.subscription.isSignedIn + let hasActiveSubscription = settingsViewModel.state.subscription.hasActiveSubscription + let hasNoEntitlements = settingsViewModel.state.subscription.entitlements.isEmpty let footerLink = Link(UserText.settingsPProSectionFooter, destination: ViewConstants.privacyPolicyURL) @@ -239,7 +238,7 @@ struct SettingsSubscriptionView: View { } } } - .onReceive(viewModel.$state) { state in + .onReceive(settingsViewModel.$state) { state in isShowingPrivacyPro = state.subscription.enabled && (state.subscription.isSignedIn || state.subscription.canPurchase) } } diff --git a/DuckDuckGo/SettingsViewModel.swift b/DuckDuckGo/SettingsViewModel.swift index c9deef5f24..eb984187ff 100644 --- a/DuckDuckGo/SettingsViewModel.swift +++ b/DuckDuckGo/SettingsViewModel.swift @@ -39,13 +39,13 @@ final class SettingsViewModel: ObservableObject { private var legacyViewProvider: SettingsLegacyViewProvider private lazy var versionProvider: AppVersion = AppVersion.shared private let voiceSearchHelper: VoiceSearchHelperProtocol - private let subscriptionFeatureAvailability: SubscriptionFeatureAvailability private let syncPausedStateManager: any SyncPausedStateManaging var emailManager: EmailManager { EmailManager() } private let historyManager: HistoryManaging let privacyProDataReporter: PrivacyProDataReporting? // Subscription Dependencies private let subscriptionManager: SubscriptionManager + let subscriptionFeatureAvailability: SubscriptionFeatureAvailability private var subscriptionSignOutObserver: Any? var duckPlayerContingencyHandler: DuckPlayerContingencyHandler { DefaultDuckPlayerContingencyHandler(privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager) @@ -362,7 +362,7 @@ final class SettingsViewModel: ObservableObject { init(state: SettingsState? = nil, legacyViewProvider: SettingsLegacyViewProvider, subscriptionManager: SubscriptionManager, - subscriptionFeatureAvailability: SubscriptionFeatureAvailability = AppDependencyProvider.shared.subscriptionFeatureAvailability, + subscriptionFeatureAvailability: SubscriptionFeatureAvailability, voiceSearchHelper: VoiceSearchHelperProtocol = AppDependencyProvider.shared.voiceSearchHelper, variantManager: VariantManager = AppDependencyProvider.shared.variantManager, deepLink: SettingsDeepLinkSection? = nil, @@ -706,7 +706,7 @@ extension SettingsViewModel { } // Update visibility based on Feature flag - state.subscription.enabled = AppDependencyProvider.shared.subscriptionFeatureAvailability.isFeatureAvailable + state.subscription.enabled = subscriptionFeatureAvailability.isFeatureAvailable // Update if can purchase based on App Store product availability state.subscription.canPurchase = subscriptionManager.canPurchase diff --git a/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift b/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift index 3cc20634b2..69db14249d 100644 --- a/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift +++ b/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift @@ -90,6 +90,7 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature, ObservableObjec private let subscriptionAttributionOrigin: String? private let subscriptionManager: SubscriptionManager + private let subscriptionFeatureAvailability: SubscriptionFeatureAvailability private var accountManager: AccountManager { subscriptionManager.accountManager } private let appStorePurchaseFlow: AppStorePurchaseFlow private let appStoreRestoreFlow: AppStoreRestoreFlow @@ -97,12 +98,14 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature, ObservableObjec private let privacyProDataReporter: PrivacyProDataReporting? init(subscriptionManager: SubscriptionManager, + subscriptionFeatureAvailability: SubscriptionFeatureAvailability, subscriptionAttributionOrigin: String?, appStorePurchaseFlow: AppStorePurchaseFlow, appStoreRestoreFlow: AppStoreRestoreFlow, appStoreAccountManagementFlow: AppStoreAccountManagementFlow, privacyProDataReporter: PrivacyProDataReporting? = nil) { self.subscriptionManager = subscriptionManager + self.subscriptionFeatureAvailability = subscriptionFeatureAvailability self.appStorePurchaseFlow = appStorePurchaseFlow self.appStoreRestoreFlow = appStoreRestoreFlow self.appStoreAccountManagementFlow = appStoreAccountManagementFlow @@ -200,7 +203,7 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature, ObservableObjec func getSubscriptionOptions(params: Any, original: WKScriptMessage) async -> Encodable? { resetSubscriptionFlow() if let subscriptionOptions = await subscriptionManager.storePurchaseManager().subscriptionOptions() { - if AppDependencyProvider.shared.subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed { + if subscriptionFeatureAvailability.isSubscriptionPurchaseAllowed { return subscriptionOptions } else { return SubscriptionOptions.empty diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift index d6773ece49..3d3fafb4cc 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift @@ -69,13 +69,12 @@ final class SubscriptionSettingsViewModel: ObservableObject { public let usesUnifiedFeedbackForm: Bool - init(subscriptionManager: SubscriptionManager = AppDependencyProvider.shared.subscriptionManager, - subscriptionFeatureAvailability: SubscriptionFeatureAvailability = AppDependencyProvider.shared.subscriptionFeatureAvailability) { + init(subscriptionManager: SubscriptionManager = AppDependencyProvider.shared.subscriptionManager) { self.subscriptionManager = subscriptionManager let subscriptionFAQURL = subscriptionManager.url(for: .faq) let learnMoreURL = subscriptionFAQURL.appendingPathComponent("adding-email") self.state = State(faqURL: subscriptionFAQURL, learnMoreURL: learnMoreURL) - self.usesUnifiedFeedbackForm = subscriptionManager.accountManager.isUserAuthenticated && subscriptionFeatureAvailability.usesUnifiedFeedbackForm + self.usesUnifiedFeedbackForm = subscriptionManager.accountManager.isUserAuthenticated setupNotificationObservers() } diff --git a/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift b/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift index 547523b58f..80b1ea8b53 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift @@ -19,12 +19,14 @@ import SwiftUI import Subscription +import BrowserServicesKit enum SubscriptionContainerViewFactory { static func makeSubscribeFlow(origin: String?, navigationCoordinator: SubscriptionNavigationCoordinator, subscriptionManager: SubscriptionManager, + subscriptionFeatureAvailability: SubscriptionFeatureAvailability, privacyProDataReporter: PrivacyProDataReporting?) -> some View { let appStoreRestoreFlow = DefaultAppStoreRestoreFlow(accountManager: subscriptionManager.accountManager, storePurchaseManager: subscriptionManager.storePurchaseManager(), @@ -44,6 +46,7 @@ enum SubscriptionContainerViewFactory { origin: origin, userScript: SubscriptionPagesUserScript(), subFeature: SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: origin, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, @@ -55,7 +58,8 @@ enum SubscriptionContainerViewFactory { } static func makeRestoreFlow(navigationCoordinator: SubscriptionNavigationCoordinator, - subscriptionManager: SubscriptionManager) -> some View { + subscriptionManager: SubscriptionManager, + subscriptionFeatureAvailability: SubscriptionFeatureAvailability) -> some View { let appStoreRestoreFlow = DefaultAppStoreRestoreFlow(accountManager: subscriptionManager.accountManager, storePurchaseManager: subscriptionManager.storePurchaseManager(), subscriptionEndpointService: subscriptionManager.subscriptionEndpointService, @@ -74,6 +78,7 @@ enum SubscriptionContainerViewFactory { origin: nil, userScript: SubscriptionPagesUserScript(), subFeature: SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, @@ -85,6 +90,7 @@ enum SubscriptionContainerViewFactory { static func makeEmailFlow(navigationCoordinator: SubscriptionNavigationCoordinator, subscriptionManager: SubscriptionManager, + subscriptionFeatureAvailability: SubscriptionFeatureAvailability, onDisappear: @escaping () -> Void) -> some View { let appStoreRestoreFlow = DefaultAppStoreRestoreFlow(accountManager: subscriptionManager.accountManager, storePurchaseManager: subscriptionManager.storePurchaseManager(), @@ -103,6 +109,7 @@ enum SubscriptionContainerViewFactory { origin: nil, userScript: SubscriptionPagesUserScript(), subFeature: SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, diff --git a/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift b/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift index 149456cee1..82c7b3f04b 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift @@ -83,8 +83,13 @@ struct SubscriptionSettingsView: View { NavigationLink(destination: SubscriptionContainerViewFactory.makeEmailFlow( navigationCoordinator: subscriptionNavigationCoordinator, subscriptionManager: AppDependencyProvider.shared.subscriptionManager, + subscriptionFeatureAvailability: settingsViewModel.subscriptionFeatureAvailability, onDisappear: { - Task { await viewModel.fetchAndUpdateAccountEmail(cachePolicy: .reloadIgnoringLocalCacheData, loadingIndicator: false) } + Task { + await viewModel.fetchAndUpdateAccountEmail( + cachePolicy: .reloadIgnoringLocalCacheData, + loadingIndicator: false) + } }), isActive: $isShowingEmailView) { if let email = viewModel.state.subscriptionEmail { diff --git a/DuckDuckGoTests/MockDependencyProvider.swift b/DuckDuckGoTests/MockDependencyProvider.swift index a1e7a7e5bd..7d0c316029 100644 --- a/DuckDuckGoTests/MockDependencyProvider.swift +++ b/DuckDuckGoTests/MockDependencyProvider.swift @@ -40,7 +40,6 @@ class MockDependencyProvider: DependencyProvider { var configurationManager: ConfigurationManager var configurationStore: ConfigurationStore var userBehaviorMonitor: UserBehaviorMonitor - var subscriptionFeatureAvailability: SubscriptionFeatureAvailability var subscriptionManager: SubscriptionManager var accountManager: AccountManager var vpnFeatureVisibility: DefaultNetworkProtectionVisibility @@ -64,7 +63,6 @@ class MockDependencyProvider: DependencyProvider { configurationStore = defaultProvider.configurationStore configurationManager = defaultProvider.configurationManager userBehaviorMonitor = defaultProvider.userBehaviorMonitor - subscriptionFeatureAvailability = defaultProvider.subscriptionFeatureAvailability accountManager = AccountManagerMock() diff --git a/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift b/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift index 2d72febe57..548b68f63c 100644 --- a/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift +++ b/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift @@ -76,7 +76,8 @@ final class OnboardingDaxFavouritesTests: XCTestCase { contextualOnboardingPresenter: ContextualOnboardingPresenterMock(), contextualOnboardingLogic: contextualOnboardingLogicMock, contextualOnboardingPixelReporter: OnboardingPixelReporterMock(), - tutorialSettings: tutorialSettingsMock + tutorialSettings: tutorialSettingsMock, + subscriptionFeatureAvailability: SubscriptionFeatureAvailabilityMock.enabled ) let window = UIWindow(frame: UIScreen.main.bounds) window.rootViewController = UIViewController() diff --git a/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift b/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift index aceb3eb7b6..8f0bf70518 100644 --- a/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift +++ b/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift @@ -74,7 +74,8 @@ final class OnboardingNavigationDelegateTests: XCTestCase { variantManager: MockVariantManager(), contextualOnboardingPresenter: ContextualOnboardingPresenterMock(), contextualOnboardingLogic: ContextualOnboardingLogicMock(), - contextualOnboardingPixelReporter: onboardingPixelReporter) + contextualOnboardingPixelReporter: onboardingPixelReporter, + subscriptionFeatureAvailability: SubscriptionFeatureAvailabilityMock.enabled) let window = UIWindow(frame: UIScreen.main.bounds) window.rootViewController = UIViewController() window.makeKeyAndVisible() diff --git a/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift b/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift index a46ab82b20..49d41fd704 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift @@ -25,6 +25,7 @@ import SubscriptionTestingUtilities final class SubscriptionContainerViewModelTests: XCTestCase { var sut: SubscriptionContainerViewModel! let subscriptionManager = MockDependencyProvider().subscriptionManager + let subscriptionFeatureAvailability = SubscriptionFeatureAvailabilityMock.enabled func testWhenInitWithOriginThenSubscriptionFlowPurchaseURLHasOriginSet() { // GIVEN @@ -49,6 +50,7 @@ final class SubscriptionContainerViewModelTests: XCTestCase { origin: origin, userScript: .init(), subFeature: .init(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, @@ -77,6 +79,7 @@ final class SubscriptionContainerViewModelTests: XCTestCase { origin: nil, userScript: .init(), subFeature: .init(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, diff --git a/DuckDuckGoTests/Subscription/SubscriptionFeatureAvailabilityMock.swift b/DuckDuckGoTests/Subscription/SubscriptionFeatureAvailabilityMock.swift index 70d007616f..055df663ca 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionFeatureAvailabilityMock.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionFeatureAvailabilityMock.swift @@ -21,6 +21,10 @@ import Foundation @testable import BrowserServicesKit public final class SubscriptionFeatureAvailabilityMock: SubscriptionFeatureAvailability { + static var enabled: SubscriptionFeatureAvailabilityMock { + return SubscriptionFeatureAvailabilityMock(isFeatureAvailable: true, isSubscriptionPurchaseAllowed: true, usesUnifiedFeedbackForm: true) + } + public var isFeatureAvailable: Bool public var isSubscriptionPurchaseAllowed: Bool public var usesUnifiedFeedbackForm: Bool diff --git a/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift b/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift index 260d06d816..166657aa67 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift @@ -26,6 +26,7 @@ final class SubscriptionFlowViewModelTests: XCTestCase { private var sut: SubscriptionFlowViewModel! let subscriptionManager = MockDependencyProvider().subscriptionManager + let subscriptionFeatureAvailability = SubscriptionFeatureAvailabilityMock.enabled func testWhenInitWithOriginThenSubscriptionFlowPurchaseURLHasOriginSet() { // GIVEN @@ -47,6 +48,7 @@ final class SubscriptionFlowViewModelTests: XCTestCase { // WHEN sut = .init(origin: origin, userScript: .init(), subFeature: .init(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, @@ -73,6 +75,7 @@ final class SubscriptionFlowViewModelTests: XCTestCase { // WHEN sut = .init(origin: nil, userScript: .init(), subFeature: .init(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, diff --git a/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift b/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift index d51d38feca..8636921470 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift @@ -87,6 +87,7 @@ final class SubscriptionPagesUseSubscriptionFeatureTests: XCTestCase { var accountManager: AccountManager! var subscriptionManager: SubscriptionManager! + var subscriptionFeatureAvailability = SubscriptionFeatureAvailabilityMock.enabled var feature: SubscriptionPagesUseSubscriptionFeature! @@ -158,6 +159,7 @@ final class SubscriptionPagesUseSubscriptionFeatureTests: XCTestCase { subscriptionEnvironment: subscriptionEnvironment) feature = SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailability, subscriptionAttributionOrigin: nil, appStorePurchaseFlow: appStorePurchaseFlow, appStoreRestoreFlow: appStoreRestoreFlow, @@ -169,8 +171,6 @@ final class SubscriptionPagesUseSubscriptionFeatureTests: XCTestCase { pixelsFired.removeAll() HTTPStubs.removeAllStubs() - AppDependencyProvider.shared = AppDependencyProvider.makeTestingInstance() - subscriptionService = nil authService = nil storePurchaseManager = nil @@ -308,11 +308,18 @@ final class SubscriptionPagesUseSubscriptionFeatureTests: XCTestCase { func testGetSubscriptionOptionsReturnsEmptyOptionsWhenPurchaseNotAllowed() async throws { // Given - let mockDependencyProvider = MockDependencyProvider() - mockDependencyProvider.subscriptionFeatureAvailability = SubscriptionFeatureAvailabilityMock(isFeatureAvailable: true, - isSubscriptionPurchaseAllowed: false, - usesUnifiedFeedbackForm: true) - AppDependencyProvider.shared = mockDependencyProvider + let subscriptionFeatureAvailabilityWithoutPurchaseAllowed = SubscriptionFeatureAvailabilityMock( + isFeatureAvailable: true, + isSubscriptionPurchaseAllowed: false, + usesUnifiedFeedbackForm: true + ) + + feature = SubscriptionPagesUseSubscriptionFeature(subscriptionManager: subscriptionManager, + subscriptionFeatureAvailability: subscriptionFeatureAvailabilityWithoutPurchaseAllowed, + subscriptionAttributionOrigin: nil, + appStorePurchaseFlow: appStorePurchaseFlow, + appStoreRestoreFlow: appStoreRestoreFlow, + appStoreAccountManagementFlow: appStoreAccountManagementFlow) storePurchaseManager.subscriptionOptionsResult = Constants.subscriptionOptions