From 4dec92ef829e11ba53b34a6833270e2f0438d035 Mon Sep 17 00:00:00 2001 From: alpavanoglu Date: Thu, 6 Jul 2023 13:35:14 +0200 Subject: [PATCH] Add `CompliancePopoverViewModelTests` --- .../CompliancePopoverCoordinator.swift | 22 +++-- .../CompliancePopoverViewModel.swift | 8 +- WordPress/WordPress.xcodeproj/project.pbxproj | 12 +++ WordPress/WordPressTest/AccountBuilder.swift | 6 ++ .../CompliancePopoverViewModelTests.swift | 87 +++++++++++++++++++ 5 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 WordPress/WordPressTest/EUUSCompliance/CompliancePopoverViewModelTests.swift diff --git a/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverCoordinator.swift b/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverCoordinator.swift index c452386ddf31..b15871acd7a3 100644 --- a/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverCoordinator.swift +++ b/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverCoordinator.swift @@ -1,7 +1,12 @@ import UIKit -final class CompliancePopoverCoordinator { +protocol CompliancePopoverCoordinatorProtocol { + func presentIfNeeded() + func navigateToSettings() + func dismiss() +} +final class CompliancePopoverCoordinator: CompliancePopoverCoordinatorProtocol { private let viewController: UIViewController private let complianceService = ComplianceLocationService() private let defaults: UserDefaults @@ -27,11 +32,6 @@ final class CompliancePopoverCoordinator { } } - func shouldShowPrivacyBanner(countryCode: String) -> Bool { - let isCountryInEU = Self.gdprCountryCodes.contains(countryCode) - return isCountryInEU && !defaults.didShowCompliancePopup - } - func navigateToSettings() { viewController.dismiss(animated: true) { RootViewCoordinator.sharedPresenter.navigateToPrivacySettings() @@ -42,8 +42,16 @@ final class CompliancePopoverCoordinator { viewController.dismiss(animated: true) } + private func shouldShowPrivacyBanner(countryCode: String) -> Bool { + let isCountryInEU = Self.gdprCountryCodes.contains(countryCode) + return isCountryInEU && !defaults.didShowCompliancePopup + } + private func presentPopover() { - let complianceViewModel = CompliancePopoverViewModel(defaults: self.defaults) + let complianceViewModel = CompliancePopoverViewModel( + defaults: defaults, + contextManager: ContextManager.shared + ) complianceViewModel.coordinator = self let complianceViewController = CompliancePopoverViewController(viewModel: complianceViewModel) let bottomSheetViewController = BottomSheetViewController(childViewController: complianceViewController, customHeaderSpacing: 0) diff --git a/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverViewModel.swift b/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverViewModel.swift index e87a688e3120..08b024e16435 100644 --- a/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverViewModel.swift +++ b/WordPress/Classes/ViewRelated/EEUUSCompliance/CompliancePopoverViewModel.swift @@ -5,12 +5,14 @@ import WordPressUI final class CompliancePopoverViewModel: ObservableObject { @Published var isAnalyticsEnabled: Bool = !WPAppAnalytics.userHasOptedOut() - var coordinator: CompliancePopoverCoordinator? + var coordinator: CompliancePopoverCoordinatorProtocol? private let defaults: UserDefaults + private let contextManager: ContextManager - init(defaults: UserDefaults) { + init(defaults: UserDefaults, contextManager: ContextManager) { self.defaults = defaults + self.contextManager = contextManager } func didTapSettings() { @@ -22,7 +24,7 @@ final class CompliancePopoverViewModel: ObservableObject { let appAnalytics = WordPressAppDelegate.shared?.analytics appAnalytics?.setUserHasOptedOut(!isAnalyticsEnabled) - let (accountID, restAPI) = ContextManager.shared.performQuery { context -> (NSNumber?, WordPressComRestApi?) in + let (accountID, restAPI) = contextManager.performQuery { context -> (NSNumber?, WordPressComRestApi?) in let account = try? WPAccount.lookupDefaultWordPressComAccount(in: context) return (account?.userID, account?.wordPressComRestApi) } diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 3cb96d66e4e2..afa2b53ffc11 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -266,6 +266,7 @@ 087EBFA81F02313E001F7ACE /* MediaThumbnailService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 087EBFA71F02313E001F7ACE /* MediaThumbnailService.swift */; }; 0880BADC29ED6FF3002D3AB0 /* UIColor+DesignSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0880BADB29ED6FF3002D3AB0 /* UIColor+DesignSystem.swift */; }; 0880BADD29ED6FF3002D3AB0 /* UIColor+DesignSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0880BADB29ED6FF3002D3AB0 /* UIColor+DesignSystem.swift */; }; + 088134FF2A56C5240027C086 /* CompliancePopoverViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 088134FE2A56C5240027C086 /* CompliancePopoverViewModelTests.swift */; }; 0885A3671E837AFE00619B4D /* URLIncrementalFilenameTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0885A3661E837AFE00619B4D /* URLIncrementalFilenameTests.swift */; }; 088B89891DA6F93B000E8DEF /* ReaderPostCardContentLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 088B89881DA6F93B000E8DEF /* ReaderPostCardContentLabel.swift */; }; 088CC594282BEC41007B9421 /* TooltipPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 088CC593282BEC41007B9421 /* TooltipPresenter.swift */; }; @@ -5949,6 +5950,7 @@ 0879FC151E9301DD00E1EFC8 /* MediaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaTests.swift; sourceTree = ""; }; 087EBFA71F02313E001F7ACE /* MediaThumbnailService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaThumbnailService.swift; sourceTree = ""; }; 0880BADB29ED6FF3002D3AB0 /* UIColor+DesignSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+DesignSystem.swift"; sourceTree = ""; }; + 088134FE2A56C5240027C086 /* CompliancePopoverViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompliancePopoverViewModelTests.swift; sourceTree = ""; }; 0885A3661E837AFE00619B4D /* URLIncrementalFilenameTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLIncrementalFilenameTests.swift; sourceTree = ""; }; 088B89881DA6F93B000E8DEF /* ReaderPostCardContentLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReaderPostCardContentLabel.swift; sourceTree = ""; }; 088CC593282BEC41007B9421 /* TooltipPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipPresenter.swift; sourceTree = ""; }; @@ -9887,6 +9889,14 @@ name = Media; sourceTree = ""; }; + 088134FD2A56C5020027C086 /* EUUSCompliance */ = { + isa = PBXGroup; + children = ( + 088134FE2A56C5240027C086 /* CompliancePopoverViewModelTests.swift */, + ); + path = EUUSCompliance; + sourceTree = ""; + }; 089F087F1CE25D30009909F2 /* Controllers */ = { isa = PBXGroup; children = ( @@ -15589,6 +15599,7 @@ BE20F5E11B2F738E0020694C /* ViewRelated */ = { isa = PBXGroup; children = ( + 088134FD2A56C5020027C086 /* EUUSCompliance */, 3F28CEAD2A4ACEA400B79686 /* Me */, 0141929E2983F5D900CAEDB0 /* Support */, F41E4E8F28F1949D001880C6 /* App Icons */, @@ -23400,6 +23411,7 @@ 08F8CD3B1EBD2D020049D0C0 /* MediaURLExporterTests.swift in Sources */, D81C2F6220F89632002AE1F1 /* EditCommentActionTests.swift in Sources */, AEE0828A2681C23C00DCF54B /* GutenbergRefactoredGalleryUploadProcessorTests.swift in Sources */, + 088134FF2A56C5240027C086 /* CompliancePopoverViewModelTests.swift in Sources */, F4426FD9287F02FD00218003 /* SiteSuggestionsServiceMock.swift in Sources */, E66969CD1B9E2EBF00EC9C00 /* SafeReaderTopicToReaderTopic.m in Sources */, DC3B9B2F27739887003F7249 /* TimeZoneSelectorViewModelTests.swift in Sources */, diff --git a/WordPress/WordPressTest/AccountBuilder.swift b/WordPress/WordPressTest/AccountBuilder.swift index d54f14dc6d16..3f9262916b65 100644 --- a/WordPress/WordPressTest/AccountBuilder.swift +++ b/WordPress/WordPressTest/AccountBuilder.swift @@ -49,6 +49,12 @@ class AccountBuilder: NSObject { return self } + @objc + func with(authToken: String) -> AccountBuilder { + account.authToken = authToken + return self + } + @objc @discardableResult func build() -> WPAccount { diff --git a/WordPress/WordPressTest/EUUSCompliance/CompliancePopoverViewModelTests.swift b/WordPress/WordPressTest/EUUSCompliance/CompliancePopoverViewModelTests.swift new file mode 100644 index 000000000000..b22ba697d3a0 --- /dev/null +++ b/WordPress/WordPressTest/EUUSCompliance/CompliancePopoverViewModelTests.swift @@ -0,0 +1,87 @@ +import XCTest +@testable import WordPress + +final class CompliancePopoverViewModelTests: CoreDataTestCase { + let testDefaults = UserDefaults(suiteName: "compliance-popover-view-model-tests") + + override func setUp() { + super.setUp() + testDefaults?.removeObject(forKey: UserDefaults.didShowCompliancePopupKey) + + let windowManager = WindowManager(window: UIWindow()) + WordPressAuthenticationManager( + windowManager: windowManager, + remoteFeaturesStore: RemoteFeatureFlagStore() + ).initializeWordPressAuthenticator() + } + + override func tearDown() { + super.tearDown() + testDefaults?.removeObject(forKey: UserDefaults.didShowCompliancePopupKey) + } + + func testDidTapSettingsUpdatesDefaults() { + guard let defaults = try? XCTUnwrap(testDefaults) else { + return + } + let sut = CompliancePopoverViewModel(defaults: defaults, contextManager: contextManager) + sut.didTapSettings() + XCTAssert(defaults.didShowCompliancePopup) + } + + func testDidTapSettingsInvokesCoordinatorNavigation() { + guard let defaults = try? XCTUnwrap(testDefaults) else { + return + } + let mockCoordinator = MockCompliancePopoverCoordinator() + let sut = CompliancePopoverViewModel(defaults: defaults, contextManager: contextManager) + sut.coordinator = mockCoordinator + sut.didTapSettings() + XCTAssertEqual(mockCoordinator.navigateToSettingsCallCount, 1) + } + + func testDidTapSaveInvokesDismissWhenAccountIDExists() { + guard let defaults = try? XCTUnwrap(testDefaults) else { + return + } + let mockCoordinator = MockCompliancePopoverCoordinator() + let sut = CompliancePopoverViewModel( + defaults: defaults, + contextManager: makeCoreDataStack() + ) + sut.coordinator = mockCoordinator + sut.didTapSave() + XCTAssertEqual(mockCoordinator.dismissCallCount, 1) + XCTAssert(defaults.didShowCompliancePopup) + } + + private func makeCoreDataStack() -> ContextManager { + let contextManager = ContextManager.forTesting() + let account = AccountBuilder(contextManager) + .with(id: 1229) + .with(username: "foobar") + .with(email: "foo@automattic.com") + .with(authToken: "9384rj398t34j98") + .build() + UserSettings.defaultDotComUUID = account.uuid + return contextManager + } +} + +private class MockCompliancePopoverCoordinator: CompliancePopoverCoordinatorProtocol { + var navigateToSettingsCallCount = 0 + var presentIfNeededCallCount = 0 + var dismissCallCount = 0 + + func presentIfNeeded() { + presentIfNeededCallCount += 1 + } + + func navigateToSettings() { + navigateToSettingsCallCount += 1 + } + + func dismiss() { + dismissCallCount += 1 + } +}