From ac97f333333018d6e6450ae0ba70fa2798bfdb07 Mon Sep 17 00:00:00 2001 From: Hassaan El-Garem Date: Wed, 30 Nov 2022 04:07:17 +0200 Subject: [PATCH 1/5] Refactor: add the ability to inject remote config store if needed --- .../Utility/BuildInformation/RemoteConfig.swift | 17 ++++++++++++++++- .../RemoteConfigParameter.swift | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift b/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift index 3777cb8ef857..3ca30cce8200 100644 --- a/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift +++ b/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift @@ -2,5 +2,20 @@ import Foundation /// A struct that holds all remote config parameters. struct RemoteConfig { - static let jetpackDeadline = RemoteConfigParameter(key: "jp-deadline", defaultValue: nil) + + // MARK: Private Variables + + private var store: RemoteConfigStore + + // MARK: Initializer + + init(store: RemoteConfigStore = .shared) { + self.store = store + } + + // MARK: Remote Config Parameters + + var jetpackDeadline: RemoteConfigParameter { + RemoteConfigParameter(key: "jp-deadline", defaultValue: nil, store: store) + } } diff --git a/WordPress/Classes/Utility/BuildInformation/RemoteConfigParameter.swift b/WordPress/Classes/Utility/BuildInformation/RemoteConfigParameter.swift index 0b59d6a5f862..6d80e4d123e4 100644 --- a/WordPress/Classes/Utility/BuildInformation/RemoteConfigParameter.swift +++ b/WordPress/Classes/Utility/BuildInformation/RemoteConfigParameter.swift @@ -17,7 +17,7 @@ struct RemoteConfigParameter { // MARK: Initializer - init(key: String, defaultValue: T?, store: RemoteConfigStore = .shared) { + init(key: String, defaultValue: T?, store: RemoteConfigStore) { self.key = key self.defaultValue = defaultValue self.store = store From ee8e5bba6882411ce31e7ace1b2916e41e61e22e Mon Sep 17 00:00:00 2001 From: Hassaan El-Garem Date: Wed, 30 Nov 2022 04:10:30 +0200 Subject: [PATCH 2/5] Add: function for retrieving the removal deadline --- .../Coordinator/JetpackFeaturesRemovalCoordinator.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift b/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift index de26013b738a..e7f54e8391fa 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift @@ -84,6 +84,15 @@ class JetpackFeaturesRemovalCoordinator { return .normal } + static func removalDeadline(remoteConfigStore: RemoteConfigStore = .shared) -> Date? { + guard let dateString = RemoteConfig(store: remoteConfigStore).jetpackDeadline.value else { + return nil + } + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd" + return formatter.date(from: dateString) + } + /// Used to display feature-specific or feature-collection overlays. /// - Parameters: /// - source: The source that triggers the display of the overlay. From 4cf1111f98ddd896c706cafb0e131d38247fb82e Mon Sep 17 00:00:00 2001 From: Hassaan El-Garem Date: Wed, 30 Nov 2022 04:10:55 +0200 Subject: [PATCH 3/5] Add: tests for retrieving the removal deadline --- ...tpackFeaturesRemovalCoordinatorTests.swift | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/WordPress/WordPressTest/JetpackFeaturesRemovalCoordinatorTests.swift b/WordPress/WordPressTest/JetpackFeaturesRemovalCoordinatorTests.swift index beddb81ed734..1d7b0d0c94b2 100644 --- a/WordPress/WordPressTest/JetpackFeaturesRemovalCoordinatorTests.swift +++ b/WordPress/WordPressTest/JetpackFeaturesRemovalCoordinatorTests.swift @@ -245,6 +245,31 @@ final class JetpackFeaturesRemovalCoordinatorTests: XCTestCase { XCTAssertEqual(phase, .two) } + // MARK: Removal Deadline + + func testFetchingRemovalDeadline() { + // Given + let remoteConfigStore = RemoteConfigStore(persistenceStore: mockUserDefaults) + mockUserDefaults.set(["jp-deadline": "2022-10-10"], forKey: RemoteConfigStore.Constants.CachedResponseKey) + + // When + let deadline = JetpackFeaturesRemovalCoordinator.removalDeadline(remoteConfigStore: remoteConfigStore) + + XCTAssertEqual(deadline?.components.year, 2022) + XCTAssertEqual(deadline?.components.month, 10) + XCTAssertEqual(deadline?.components.day, 10) + } + + func testRemovalDeadlineDoesNotExist() { + // Given + let remoteConfigStore = RemoteConfigStore(persistenceStore: mockUserDefaults) + + // When + let deadline = JetpackFeaturesRemovalCoordinator.removalDeadline(remoteConfigStore: remoteConfigStore) + + XCTAssertNil(deadline) + } + // MARK: Helpers private func generateFlags(phaseOne: Bool, @@ -261,3 +286,10 @@ final class JetpackFeaturesRemovalCoordinatorTests: XCTestCase { ] } } + +private extension Date { + var components: DateComponents { + return Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], + from: self) + } +} From e20721a5b62d52aed74d4110e14bd00bbcb71770 Mon Sep 17 00:00:00 2001 From: Hassaan El-Garem Date: Wed, 30 Nov 2022 04:26:51 +0200 Subject: [PATCH 4/5] Refactor: remove the shared instance from `RemoteConfigStore` --- WordPress/Classes/Stores/RemoteConfigStore.swift | 14 ++++++++------ .../Classes/System/WordPressAppDelegate.swift | 3 ++- .../Utility/BuildInformation/RemoteConfig.swift | 2 +- .../JetpackFeaturesRemovalCoordinator.swift | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/WordPress/Classes/Stores/RemoteConfigStore.swift b/WordPress/Classes/Stores/RemoteConfigStore.swift index 42710a41f7a7..c7d183b79d70 100644 --- a/WordPress/Classes/Stores/RemoteConfigStore.swift +++ b/WordPress/Classes/Stores/RemoteConfigStore.swift @@ -1,22 +1,24 @@ import Foundation -class RemoteConfigStore { - - // MARK: Shared Instance +fileprivate extension DispatchQueue { + static let remoteConfigStoreQueue = DispatchQueue(label: "remote-config-store-queue") +} - public static let shared = RemoteConfigStore() +class RemoteConfigStore { // MARK: Private Variables /// Thread Safety Coordinator - private let queue: DispatchQueue = DispatchQueue(label: "remote-config-store-queue") + private let queue: DispatchQueue private let remote: RemoteConfigRemote private let persistenceStore: UserPersistentRepository // MARK: Initializer - init(remote: RemoteConfigRemote = RemoteConfigRemote(wordPressComRestApi: .defaultApi()), + init(queue: DispatchQueue = .remoteConfigStoreQueue, + remote: RemoteConfigRemote = RemoteConfigRemote(wordPressComRestApi: .defaultApi()), persistenceStore: UserPersistentRepository = UserDefaults.standard) { + self.queue = queue self.remote = remote self.persistenceStore = persistenceStore } diff --git a/WordPress/Classes/System/WordPressAppDelegate.swift b/WordPress/Classes/System/WordPressAppDelegate.swift index 167d4ccfa904..4cf853683e3a 100644 --- a/WordPress/Classes/System/WordPressAppDelegate.swift +++ b/WordPress/Classes/System/WordPressAppDelegate.swift @@ -44,6 +44,7 @@ class WordPressAppDelegate: UIResponder, UIApplicationDelegate { private var noticePresenter: NoticePresenter? private var bgTask: UIBackgroundTaskIdentifier? = nil private let remoteFeatureFlagStore = RemoteFeatureFlagStore() + private let remoteConfigStore = RemoteConfigStore() private var mainContext: NSManagedObjectContext { return ContextManager.shared.mainContext @@ -667,7 +668,7 @@ extension WordPressAppDelegate { } func updateRemoteConfig() { - RemoteConfigStore.shared.update() + remoteConfigStore.update() } } diff --git a/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift b/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift index 3ca30cce8200..2bebdfcfc10f 100644 --- a/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift +++ b/WordPress/Classes/Utility/BuildInformation/RemoteConfig.swift @@ -9,7 +9,7 @@ struct RemoteConfig { // MARK: Initializer - init(store: RemoteConfigStore = .shared) { + init(store: RemoteConfigStore = RemoteConfigStore()) { self.store = store } diff --git a/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift b/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift index e7f54e8391fa..25653a97cd24 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift @@ -84,7 +84,7 @@ class JetpackFeaturesRemovalCoordinator { return .normal } - static func removalDeadline(remoteConfigStore: RemoteConfigStore = .shared) -> Date? { + static func removalDeadline(remoteConfigStore: RemoteConfigStore = RemoteConfigStore()) -> Date? { guard let dateString = RemoteConfig(store: remoteConfigStore).jetpackDeadline.value else { return nil } From c2a5c5ffdc1ab280d2eca734b79a4e01ef4ba12e Mon Sep 17 00:00:00 2001 From: Hassaan El-Garem Date: Wed, 30 Nov 2022 04:27:18 +0200 Subject: [PATCH 5/5] Fix: compile warning in a test class --- WordPress/WordPressTest/InMemoryUserDefaults.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/WordPressTest/InMemoryUserDefaults.swift b/WordPress/WordPressTest/InMemoryUserDefaults.swift index 1c120fa1f3fb..b29fede21417 100644 --- a/WordPress/WordPressTest/InMemoryUserDefaults.swift +++ b/WordPress/WordPressTest/InMemoryUserDefaults.swift @@ -43,7 +43,7 @@ class InMemoryUserDefaults: UserPersistentRepository { } func dictionaryRepresentation() -> [String: Any] { - return dictionary + return dictionary as [String: Any] } func set(_ value: Any?, forKey key: String) {