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 3777cb8ef857..2bebdfcfc10f 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 = RemoteConfigStore()) { + 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 diff --git a/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift b/WordPress/Classes/ViewRelated/Jetpack/Branding/Coordinator/JetpackFeaturesRemovalCoordinator.swift index de26013b738a..25653a97cd24 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 = RemoteConfigStore()) -> 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. 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) { 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) + } +}