From 41cf8e9fdbc704e692bd5019d01e811f95f137ad Mon Sep 17 00:00:00 2001 From: Michal Smaga Date: Mon, 28 Oct 2024 16:20:17 +0100 Subject: [PATCH] Use cookie to share subscription access token on DDG domains (#3488) Task/Issue URL: https://app.asana.com/0/1108686900785972/1208264562025859/f **Description**: Store and keep in sync the subscription access token for the duckduckgo.com domain cookie. For the implementation guidelines please see description of the linked task. --- Core/PixelEvent.swift | 10 ++++ DuckDuckGo.xcodeproj/project.pbxproj | 6 ++- .../xcshareddata/swiftpm/Package.resolved | 8 +-- DuckDuckGo/AppDelegate.swift | 21 +++++++- DuckDuckGo/MainViewController.swift | 8 ++- ...riptionCookieManageEventPixelMapping.swift | 52 +++++++++++++++++++ DuckDuckGo/TabManager.swift | 12 +++-- DuckDuckGo/TabViewController.swift | 14 +++-- ...ViewControllerLongPressMenuExtension.swift | 3 +- DuckDuckGoTests/MockTabDelegate.swift | 5 +- .../OnboardingDaxFavouritesTests.swift | 4 +- .../OnboardingNavigationDelegateTests.swift | 4 +- 12 files changed, 128 insertions(+), 19 deletions(-) create mode 100644 DuckDuckGo/Subscription/SubscriptionCookieManageEventPixelMapping.swift diff --git a/Core/PixelEvent.swift b/Core/PixelEvent.swift index bd35b54b15..0a021242ea 100644 --- a/Core/PixelEvent.swift +++ b/Core/PixelEvent.swift @@ -708,6 +708,11 @@ extension Pixel { case privacyProTransactionProgressNotHiddenAfter60s case privacyProSuccessfulSubscriptionAttribution case privacyProKeychainAccessError + case privacyProSubscriptionCookieMissingTokenOnSignIn + case privacyProSubscriptionCookieMissingCookieOnSignOut + case privacyProSubscriptionCookieRefreshedWithUpdate + case privacyProSubscriptionCookieRefreshedWithDelete + case privacyProSubscriptionCookieFailedToSetSubscriptionCookie // MARK: Pixel Experiment case pixelExperimentEnrollment @@ -1520,6 +1525,11 @@ extension Pixel.Event { case .privacyProTransactionProgressNotHiddenAfter60s: return "m_privacy-pro_progress_not_hidden_after_60s" case .privacyProSuccessfulSubscriptionAttribution: return "m_subscribe" case .privacyProKeychainAccessError: return "m_privacy-pro_keychain_access_error" + case .privacyProSubscriptionCookieMissingTokenOnSignIn: return "m_privacy-pro_subscription-cookie-missing_token_on_sign_in" + case .privacyProSubscriptionCookieMissingCookieOnSignOut: return "m_privacy-pro_subscription-cookie-missing_cookie_on_sign_out" + case .privacyProSubscriptionCookieRefreshedWithUpdate: return "m_privacy-pro_subscription-cookie-refreshed_with_update" + case .privacyProSubscriptionCookieRefreshedWithDelete: return "m_privacy-pro_subscription-cookie-refreshed_with_delete" + case .privacyProSubscriptionCookieFailedToSetSubscriptionCookie: return "m_privacy-pro_subscription-cookie-failed_to_set_subscription_cookie" // MARK: Pixel Experiment case .pixelExperimentEnrollment: return "pixel_experiment_enrollment" diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 73dc71bf7a..00bb90136d 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -63,6 +63,7 @@ 1E1D8B6C29953CE300C96994 /* autoconsent-test-page-banner.html in Resources */ = {isa = PBXBuildFile; fileRef = 1E1D8B6929953CE300C96994 /* autoconsent-test-page-banner.html */; }; 1E24295E293F57FA00584836 /* LottieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E24295D293F57FA00584836 /* LottieView.swift */; }; 1E242960293F585300584836 /* cookie-icon-animated-40-light.json in Resources */ = {isa = PBXBuildFile; fileRef = 1E24295F293F585300584836 /* cookie-icon-animated-40-light.json */; }; + 1E39BEB02CC9477200496FBA /* SubscriptionCookieManageEventPixelMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E39BEAF2CC9477200496FBA /* SubscriptionCookieManageEventPixelMapping.swift */; }; 1E4DCF4627B6A33600961E25 /* DownloadsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4DCF4527B6A33600961E25 /* DownloadsListViewModel.swift */; }; 1E4DCF4827B6A35400961E25 /* DownloadsListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4DCF4727B6A35400961E25 /* DownloadsListModel.swift */; }; 1E4DCF4A27B6A38000961E25 /* DownloadListRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4DCF4927B6A38000961E25 /* DownloadListRepresentable.swift */; }; @@ -1378,6 +1379,7 @@ 1E24295D293F57FA00584836 /* LottieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieView.swift; sourceTree = ""; }; 1E24295F293F585300584836 /* cookie-icon-animated-40-light.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "cookie-icon-animated-40-light.json"; sourceTree = ""; }; 1E25D5312C92126B004400F0 /* SubscriptionFeatureAvailabilityMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionFeatureAvailabilityMock.swift; sourceTree = ""; }; + 1E39BEAF2CC9477200496FBA /* SubscriptionCookieManageEventPixelMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionCookieManageEventPixelMapping.swift; sourceTree = ""; }; 1E4DCF4527B6A33600961E25 /* DownloadsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadsListViewModel.swift; sourceTree = ""; }; 1E4DCF4727B6A35400961E25 /* DownloadsListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadsListModel.swift; sourceTree = ""; }; 1E4DCF4927B6A38000961E25 /* DownloadListRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadListRepresentable.swift; sourceTree = ""; }; @@ -5369,6 +5371,7 @@ D664C7962B289AA000CBFA76 /* Extensions */, D65CEA6F2B6AC6C9008A759B /* Subscription.xcassets */, BDE219E52C406D19005D5884 /* PrivacyProDataReporting.swift */, + 1E39BEAF2CC9477200496FBA /* SubscriptionCookieManageEventPixelMapping.swift */, ); path = Subscription; sourceTree = ""; @@ -7576,6 +7579,7 @@ C1641EAF2BC2F5140012607A /* ImportPasswordsViewController.swift in Sources */, D63FF8982C1B6A45006DE24D /* DuckPlayer.swift in Sources */, 85B9CB8921AEBDD5009001F1 /* FavoriteHomeCell.swift in Sources */, + 1E39BEB02CC9477200496FBA /* SubscriptionCookieManageEventPixelMapping.swift in Sources */, C1935A102C88D131001AD72D /* AutofillSurveyManager.swift in Sources */, 7B1604EE2CB68D2600A44EC6 /* TipKitDebugOptionsUIActionHandling.swift in Sources */, 98999D5922FDA41500CBBE1B /* BasicAuthenticationAlert.swift in Sources */, @@ -11006,7 +11010,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 200.3.0; + version = 201.0.0; }; }; 9F8FE9472BAE50E50071E372 /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index c31d42aab9..21aa8e0ac9 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/DuckDuckGo/BrowserServicesKit", "state" : { - "revision" : "fdf6f75d570a5ef6058efa881e11f9467627fbf4", - "version" : "200.2.1" + "revision" : "e5946eee6af859690cc1cc5e51daef3c8368981b", + "version" : "201.0.0" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/content-scope-scripts", "state" : { - "revision" : "1ed569676555d493c9c5575eaed22aa02569aac9", - "version" : "6.19.0" + "revision" : "b74549bd869fdecc16fad851f2f608b1724764df", + "version" : "6.25.0" } }, { diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index cc09ced6bb..d5f34b1a3c 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -88,6 +88,7 @@ import os.log private var autofillUsageMonitor = AutofillUsageMonitor() private(set) var subscriptionFeatureAvailability: SubscriptionFeatureAvailability! + private var subscriptionCookieManager: SubscriptionCookieManaging! var privacyProDataReporter: PrivacyProDataReporting! // MARK: - Feature specific app event handlers @@ -122,7 +123,7 @@ import os.log } } - // swiftlint:disable:next function_body_length + // swiftlint:disable:next function_body_length cyclomatic_complexity func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { #if targetEnvironment(simulator) @@ -312,6 +313,17 @@ import os.log subscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability( privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, purchasePlatform: .appStore) + + subscriptionCookieManager = SubscriptionCookieManager(subscriptionManager: AppDependencyProvider.shared.subscriptionManager, + currentCookieStore: { [weak self] in + guard self?.mainViewController?.tabManager.model.hasActiveTabs ?? false else { + // We shouldn't interact with WebKit's cookie store unless we have a WebView, + // eventually the subscription cookie will be refreshed on opening the first tab + return nil + } + + return WKWebsiteDataStore.current().httpCookieStore + }, eventMapping: SubscriptionCookieManageEventPixelMapping()) homePageConfiguration = HomePageConfiguration(variantManager: AppDependencyProvider.shared.variantManager, remoteMessagingClient: remoteMessagingClient, @@ -350,7 +362,8 @@ import os.log contextualOnboardingLogic: daxDialogs, contextualOnboardingPixelReporter: onboardingPixelReporter, subscriptionFeatureAvailability: subscriptionFeatureAvailability, - voiceSearchHelper: voiceSearchHelper) + voiceSearchHelper: voiceSearchHelper, + subscriptionCookieManager: subscriptionCookieManager) main.loadViewIfNeeded() syncErrorHandler.alertPresenter = main @@ -574,6 +587,10 @@ import os.log } } + Task { @MainActor in + await subscriptionCookieManager.refreshSubscriptionCookie() + } + let importPasswordsStatusHandler = ImportPasswordsStatusHandler(syncService: syncService) importPasswordsStatusHandler.checkSyncSuccessStatus() diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 78000f9d7b..d1a2fd2e36 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -123,6 +123,7 @@ class MainViewController: UIViewController { private var feedbackCancellable: AnyCancellable? let subscriptionFeatureAvailability: SubscriptionFeatureAvailability + private let subscriptionCookieManager: SubscriptionCookieManaging let privacyProDataReporter: PrivacyProDataReporting private lazy var featureFlagger = AppDependencyProvider.shared.featureFlagger @@ -195,7 +196,8 @@ class MainViewController: UIViewController { tutorialSettings: TutorialSettings = DefaultTutorialSettings(), statisticsStore: StatisticsStore = StatisticsUserDefaults(), subscriptionFeatureAvailability: SubscriptionFeatureAvailability, - voiceSearchHelper: VoiceSearchHelperProtocol + voiceSearchHelper: VoiceSearchHelperProtocol, + subscriptionCookieManager: SubscriptionCookieManaging ) { self.bookmarksDatabase = bookmarksDatabase self.bookmarksDatabaseCleaner = bookmarksDatabaseCleaner @@ -217,7 +219,8 @@ class MainViewController: UIViewController { privacyProDataReporter: privacyProDataReporter, contextualOnboardingPresenter: contextualOnboardingPresenter, contextualOnboardingLogic: contextualOnboardingLogic, - onboardingPixelReporter: contextualOnboardingPixelReporter) + onboardingPixelReporter: contextualOnboardingPixelReporter, + subscriptionCookieManager: subscriptionCookieManager) self.syncPausedStateManager = syncPausedStateManager self.privacyProDataReporter = privacyProDataReporter self.homeTabManager = NewTabPageManager() @@ -228,6 +231,7 @@ class MainViewController: UIViewController { self.statisticsStore = statisticsStore self.subscriptionFeatureAvailability = subscriptionFeatureAvailability self.voiceSearchHelper = voiceSearchHelper + self.subscriptionCookieManager = subscriptionCookieManager super.init(nibName: nil, bundle: nil) diff --git a/DuckDuckGo/Subscription/SubscriptionCookieManageEventPixelMapping.swift b/DuckDuckGo/Subscription/SubscriptionCookieManageEventPixelMapping.swift new file mode 100644 index 0000000000..19efdba9dd --- /dev/null +++ b/DuckDuckGo/Subscription/SubscriptionCookieManageEventPixelMapping.swift @@ -0,0 +1,52 @@ +// +// SubscriptionCookieManageEventPixelMapping.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import Common +import Core +import Subscription + +public final class SubscriptionCookieManageEventPixelMapping: EventMapping { + + public init() { + super.init { event, _, _, _ in + let pixel: Pixel.Event = { + switch event { + case .errorHandlingAccountDidSignInTokenIsMissing: + return .privacyProSubscriptionCookieMissingTokenOnSignIn + case .errorHandlingAccountDidSignOutCookieIsMissing: + return .privacyProSubscriptionCookieMissingCookieOnSignOut + case .subscriptionCookieRefreshedWithUpdate: + return .privacyProSubscriptionCookieRefreshedWithUpdate + case .subscriptionCookieRefreshedWithDelete: + return .privacyProSubscriptionCookieRefreshedWithDelete + case .failedToSetSubscriptionCookie: + return .privacyProSubscriptionCookieFailedToSetSubscriptionCookie + } + }() + + Pixel.fire(pixel: pixel) + + } + } + + override init(mapping: @escaping EventMapping.Mapping) { + fatalError("Use init()") + } +} diff --git a/DuckDuckGo/TabManager.swift b/DuckDuckGo/TabManager.swift index 24077c9454..ba67adae9b 100644 --- a/DuckDuckGo/TabManager.swift +++ b/DuckDuckGo/TabManager.swift @@ -24,6 +24,7 @@ import WebKit import BrowserServicesKit import Persistence import History +import Subscription import os.log class TabManager { @@ -41,6 +42,7 @@ class TabManager { private let contextualOnboardingPresenter: ContextualOnboardingPresenting private let contextualOnboardingLogic: ContextualOnboardingLogic private let onboardingPixelReporter: OnboardingPixelReporting + private let subscriptionCookieManager: SubscriptionCookieManaging weak var delegate: TabDelegate? @@ -57,7 +59,8 @@ class TabManager { privacyProDataReporter: PrivacyProDataReporting, contextualOnboardingPresenter: ContextualOnboardingPresenting, contextualOnboardingLogic: ContextualOnboardingLogic, - onboardingPixelReporter: OnboardingPixelReporting) { + onboardingPixelReporter: OnboardingPixelReporting, + subscriptionCookieManager: SubscriptionCookieManaging) { self.model = model self.previewsSource = previewsSource self.bookmarksDatabase = bookmarksDatabase @@ -68,6 +71,7 @@ class TabManager { self.contextualOnboardingPresenter = contextualOnboardingPresenter self.contextualOnboardingLogic = contextualOnboardingLogic self.onboardingPixelReporter = onboardingPixelReporter + self.subscriptionCookieManager = subscriptionCookieManager registerForNotifications() } @@ -89,7 +93,8 @@ class TabManager { contextualOnboardingPresenter: contextualOnboardingPresenter, contextualOnboardingLogic: contextualOnboardingLogic, onboardingPixelReporter: onboardingPixelReporter, - featureFlagger: AppDependencyProvider.shared.featureFlagger) + featureFlagger: AppDependencyProvider.shared.featureFlagger, + subscriptionCookieManager: subscriptionCookieManager) controller.applyInheritedAttribution(inheritedAttribution) controller.attachWebView(configuration: configuration, andLoadRequest: url == nil ? nil : URLRequest.userInitiated(url!), @@ -167,7 +172,8 @@ class TabManager { contextualOnboardingPresenter: contextualOnboardingPresenter, contextualOnboardingLogic: contextualOnboardingLogic, onboardingPixelReporter: onboardingPixelReporter, - featureFlagger: AppDependencyProvider.shared.featureFlagger) + featureFlagger: AppDependencyProvider.shared.featureFlagger, + subscriptionCookieManager: subscriptionCookieManager) controller.attachWebView(configuration: configCopy, andLoadRequest: request, consumeCookies: !model.hasActiveTabs, diff --git a/DuckDuckGo/TabViewController.swift b/DuckDuckGo/TabViewController.swift index 0cb459b413..7f05eb30ba 100644 --- a/DuckDuckGo/TabViewController.swift +++ b/DuckDuckGo/TabViewController.swift @@ -41,6 +41,7 @@ import NetworkProtection import Onboarding import os.log import Navigation +import Subscription class TabViewController: UIViewController { @@ -92,6 +93,7 @@ class TabViewController: UIViewController { let appSettings: AppSettings var featureFlagger: FeatureFlagger + let subscriptionCookieManager: SubscriptionCookieManaging private lazy var internalUserDecider = AppDependencyProvider.shared.internalUserDecider private lazy var autofillNeverPromptWebsitesManager = AppDependencyProvider.shared.autofillNeverPromptWebsitesManager @@ -321,7 +323,8 @@ class TabViewController: UIViewController { contextualOnboardingLogic: ContextualOnboardingLogic, onboardingPixelReporter: OnboardingCustomInteractionPixelReporting, urlCredentialCreator: URLCredentialCreating = URLCredentialCreator(), - featureFlagger: FeatureFlagger) -> TabViewController { + featureFlagger: FeatureFlagger, + subscriptionCookieManager: SubscriptionCookieManaging) -> TabViewController { let storyboard = UIStoryboard(name: "Tab", bundle: nil) let controller = storyboard.instantiateViewController(identifier: "TabViewController", creator: { coder in TabViewController(coder: coder, @@ -336,7 +339,8 @@ class TabViewController: UIViewController { contextualOnboardingLogic: contextualOnboardingLogic, onboardingPixelReporter: onboardingPixelReporter, urlCredentialCreator: urlCredentialCreator, - featureFlagger: featureFlagger + featureFlagger: featureFlagger, + subscriptionCookieManager: subscriptionCookieManager ) }) return controller @@ -369,7 +373,8 @@ class TabViewController: UIViewController { contextualOnboardingLogic: ContextualOnboardingLogic, onboardingPixelReporter: OnboardingCustomInteractionPixelReporting, urlCredentialCreator: URLCredentialCreating = URLCredentialCreator(), - featureFlagger: FeatureFlagger) { + featureFlagger: FeatureFlagger, + subscriptionCookieManager: SubscriptionCookieManaging) { self.tabModel = tabModel self.appSettings = appSettings self.bookmarksDatabase = bookmarksDatabase @@ -388,6 +393,7 @@ class TabViewController: UIViewController { self.onboardingPixelReporter = onboardingPixelReporter self.urlCredentialCreator = urlCredentialCreator self.featureFlagger = featureFlagger + self.subscriptionCookieManager = subscriptionCookieManager super.init(coder: aDecoder) } @@ -636,6 +642,8 @@ class TabViewController: UIViewController { await webView.configuration.websiteDataStore.dataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) let cookieStore = webView.configuration.websiteDataStore.httpCookieStore await WebCacheManager.shared.consumeCookies(httpCookieStore: cookieStore) + subscriptionCookieManager.resetLastRefreshDate() + await subscriptionCookieManager.refreshSubscriptionCookie() doLoad() } } diff --git a/DuckDuckGo/TabViewControllerLongPressMenuExtension.swift b/DuckDuckGo/TabViewControllerLongPressMenuExtension.swift index 38770be4e7..8de6d3de6c 100644 --- a/DuckDuckGo/TabViewControllerLongPressMenuExtension.swift +++ b/DuckDuckGo/TabViewControllerLongPressMenuExtension.swift @@ -111,7 +111,8 @@ extension TabViewController { contextualOnboardingPresenter: contextualOnboardingPresenter, contextualOnboardingLogic: contextualOnboardingLogic, onboardingPixelReporter: onboardingPixelReporter, - featureFlagger: AppDependencyProvider.shared.featureFlagger) + featureFlagger: AppDependencyProvider.shared.featureFlagger, + subscriptionCookieManager: subscriptionCookieManager) tabController.isLinkPreview = true let configuration = WKWebViewConfiguration.nonPersistent() tabController.attachWebView(configuration: configuration, andLoadRequest: URLRequest.userInitiated(url), consumeCookies: false) diff --git a/DuckDuckGoTests/MockTabDelegate.swift b/DuckDuckGoTests/MockTabDelegate.swift index 3cd9a7c74c..b37a63a332 100644 --- a/DuckDuckGoTests/MockTabDelegate.swift +++ b/DuckDuckGoTests/MockTabDelegate.swift @@ -24,6 +24,8 @@ import BrowserServicesKit import PrivacyDashboard import Core import Persistence +import Subscription +import SubscriptionTestingUtilities @testable import DuckDuckGo final class MockTabDelegate: TabDelegate { @@ -134,7 +136,8 @@ extension TabViewController { contextualOnboardingLogic: contextualOnboardingLogic, onboardingPixelReporter: contextualOnboardingPixelReporter, urlCredentialCreator: MockCredentialCreator(), - featureFlagger: featureFlagger + featureFlagger: featureFlagger, + subscriptionCookieManager: SubscriptionCookieManagerMock() ) tab.attachWebView(configuration: .nonPersistent(), andLoadRequest: nil, consumeCookies: false, customWebView: customWebView) return tab diff --git a/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift b/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift index ad3c3be669..ff93a30198 100644 --- a/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift +++ b/DuckDuckGoTests/OnboardingDaxFavouritesTests.swift @@ -26,6 +26,7 @@ import BrowserServicesKit import RemoteMessaging import Configuration import Core +import SubscriptionTestingUtilities @testable import DuckDuckGo final class OnboardingDaxFavouritesTests: XCTestCase { @@ -78,7 +79,8 @@ final class OnboardingDaxFavouritesTests: XCTestCase { contextualOnboardingPixelReporter: OnboardingPixelReporterMock(), tutorialSettings: tutorialSettingsMock, subscriptionFeatureAvailability: SubscriptionFeatureAvailabilityMock.enabled, - voiceSearchHelper: MockVoiceSearchHelper(isSpeechRecognizerAvailable: true, voiceSearchEnabled: true) + voiceSearchHelper: MockVoiceSearchHelper(isSpeechRecognizerAvailable: true, voiceSearchEnabled: true), + subscriptionCookieManager: SubscriptionCookieManagerMock() ) let window = UIWindow(frame: UIScreen.main.bounds) window.rootViewController = UIViewController() diff --git a/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift b/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift index ca052c5717..7ccd6d49b9 100644 --- a/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift +++ b/DuckDuckGoTests/OnboardingNavigationDelegateTests.swift @@ -26,6 +26,7 @@ import BrowserServicesKit import RemoteMessaging import Configuration import Combine +import SubscriptionTestingUtilities @testable import DuckDuckGo @testable import Core @@ -76,7 +77,8 @@ final class OnboardingNavigationDelegateTests: XCTestCase { contextualOnboardingLogic: ContextualOnboardingLogicMock(), contextualOnboardingPixelReporter: onboardingPixelReporter, subscriptionFeatureAvailability: SubscriptionFeatureAvailabilityMock.enabled, - voiceSearchHelper: MockVoiceSearchHelper(isSpeechRecognizerAvailable: true, voiceSearchEnabled: true)) + voiceSearchHelper: MockVoiceSearchHelper(isSpeechRecognizerAvailable: true, voiceSearchEnabled: true), + subscriptionCookieManager: SubscriptionCookieManagerMock()) let window = UIWindow(frame: UIScreen.main.bounds) window.rootViewController = UIViewController() window.makeKeyAndVisible()