Skip to content

Commit

Permalink
[MBL-658] Replace Real Optimizely Client With Mock (#1810)
Browse files Browse the repository at this point in the history
* set up mock optimizely client to replace existing SDK.

* building - tests will fail that is next. After that come up with testing plan.

* mocked optimizely client being set correctly through input output

* fixed tests, move MockOptimizely client to library and made it public access.

* removed unused conversions api feature flag

* test corrections

* corrected library test
  • Loading branch information
msadoon committed Apr 10, 2023
1 parent e49be00 commit 0c642e4
Show file tree
Hide file tree
Showing 15 changed files with 178 additions and 280 deletions.
49 changes: 9 additions & 40 deletions Kickstarter-iOS/AppDelegate.swift
Expand Up @@ -12,7 +12,6 @@ import Foundation
import AppboySegment
import Kickstarter_Framework
import Library
import Optimizely
import Prelude
import ReactiveExtensions
import ReactiveSwift
Expand Down Expand Up @@ -178,12 +177,6 @@ internal final class AppDelegate: UIResponder, UIApplicationDelegate {
.observeForUI()
.observeValues(UIApplication.shared.unregisterForRemoteNotifications)

self.viewModel.outputs.configureOptimizely
.observeForUI()
.observeValues { [weak self] key, logLevel, dispatchInterval in
self?.configureOptimizely(with: key, logLevel: logLevel, dispatchInterval: dispatchInterval)
}

self.viewModel.outputs.configureAppCenterWithData
.observeForUI()
.observeValues { data in
Expand Down Expand Up @@ -278,6 +271,15 @@ internal final class AppDelegate: UIResponder, UIApplicationDelegate {
AppEnvironment.current.ksrAnalytics.configureSegmentClient(Analytics.shared())
}

self.viewModel.outputs.configureFeatureFlagClient
.observeValues { [weak self] featureFlagClient in
guard let strongSelf = self else { return }

AppEnvironment.updateOptimizelyClient(featureFlagClient)

strongSelf.viewModel.inputs.didUpdateOptimizelyClient(featureFlagClient)
}

self.viewModel.outputs.segmentIsEnabled
.observeValues { enabled in
enabled ? Analytics.shared().enable() : Analytics.shared().disable()
Expand Down Expand Up @@ -391,39 +393,6 @@ internal final class AppDelegate: UIResponder, UIApplicationDelegate {

// MARK: - Functions

private func configureOptimizely(
with key: String,
logLevel: OptimizelyLogLevelType,
dispatchInterval: TimeInterval
) {
let eventDispatcher = DefaultEventDispatcher(timerInterval: dispatchInterval)
let optimizelyClient = OptimizelyClient(
sdkKey: key,
eventDispatcher: eventDispatcher,
defaultLogLevel: logLevel.logLevel
)

optimizelyClient.start(resourceTimeout: 3) { [weak self] result in
guard let self = self else { return }

let optimizelyConfigurationError = self.viewModel.inputs.optimizelyConfigured(with: result)

guard let optimizelyError = optimizelyConfigurationError else {
print("🔮 Optimizely SDK Successfully Configured")
AppEnvironment.updateOptimizelyClient(optimizelyClient)

self.viewModel.inputs.didUpdateOptimizelyClient(optimizelyClient)

return
}

print("🔴 Optimizely SDK Configuration Failed with Error: \(optimizelyError.localizedDescription)")

Crashlytics.crashlytics().record(error: optimizelyError)
self.viewModel.inputs.optimizelyClientConfigurationFailed()
}
}

fileprivate func presentContextualPermissionAlert(_ notification: Notification) {
guard let context = notification.userInfo?.values.first as? PushNotificationDialog.Context else {
return
Expand Down
72 changes: 32 additions & 40 deletions Kickstarter-iOS/AppDelegateViewModel.swift
Expand Up @@ -73,9 +73,6 @@ public protocol AppDelegateViewModelInputs {
/// Call when the redirect URL has been found, see `findRedirectUrl` for more information.
func foundRedirectUrl(_ url: URL)

/// Call when Optimizely has been configured with the given result
func optimizelyConfigured(with result: OptimizelyResultType) -> Error?

/// Call when Optimizely configuration has failed
func optimizelyClientConfigurationFailed()

Expand Down Expand Up @@ -105,12 +102,12 @@ public protocol AppDelegateViewModelOutputs {
/// Emits an app secret that should be used to configure AppCenter.
var configureAppCenterWithData: Signal<AppCenterConfigData, Never> { get }

/// Emits when the application has configured feature flag client.
var configureFeatureFlagClient: Signal<OptimizelyClientType, Never> { get }

/// Emits when the application should configure Firebase
var configureFirebase: Signal<(), Never> { get }

/// Emits when the application should configure Optimizely
var configureOptimizely: Signal<(String, OptimizelyLogLevelType, TimeInterval), Never> { get }

/// Emits when the application should configure Perimeter X
var configurePerimeterX: Signal<(), Never> { get }

Expand Down Expand Up @@ -751,10 +748,6 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi

self.configureFirebase = self.applicationLaunchOptionsProperty.signal.ignoreValues()

self.configureOptimizely = self.applicationLaunchOptionsProperty.signal
.map { _ in AppEnvironment.current }
.map(optimizelyData(for:))

self.configurePerimeterX = self.applicationLaunchOptionsProperty.signal.ignoreValues()

self.configureAppCenterWithData = Signal.merge(
Expand Down Expand Up @@ -790,10 +783,6 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
.filter(isTrue)
.mapConst(0)

self.optimizelyConfigurationReturnValue <~ self.optimizelyConfiguredWithResultProperty.signal
.skipNil()
.map { $0.hasError }

self.goToPerimeterXCaptcha = self.perimeterXCaptchaTriggeredWithUserInfoProperty.signal.skipNil()
.map { userInfo -> PerimeterXBlockResponseType? in
guard let response = userInfo["response"] as? PerimeterXBlockResponseType else { return nil }
Expand Down Expand Up @@ -833,6 +822,11 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi

AppEnvironment.updateAdvertisingIdentifer(advertisingIdentifier)
}

self.configureFeatureFlagClient = self.applicationLaunchOptionsProperty.signal
.map { _ in AppEnvironment.current }
.map(configureOptimizely(for:))
.skipNil()
}

public var inputs: AppDelegateViewModelInputs { return self }
Expand Down Expand Up @@ -963,14 +957,7 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
return self.applicationDidFinishLaunchingReturnValueProperty.value
}

private let optimizelyConfigurationReturnValue = MutableProperty<Error?>(nil)
fileprivate let optimizelyConfiguredWithResultProperty = MutableProperty<OptimizelyResultType?>(nil)
public func optimizelyConfigured(with result: OptimizelyResultType) -> Error? {
self.optimizelyConfiguredWithResultProperty.value = result

return self.optimizelyConfigurationReturnValue.value
}

// FIXME: Currently not used with `MockOptimizelyClient`, but could be when we implement the next real feature flagging client.
fileprivate let optimizelyClientConfigurationFailedProperty = MutableProperty(())
public func optimizelyClientConfigurationFailed() {
self.optimizelyClientConfigurationFailedProperty.value = ()
Expand All @@ -984,7 +971,7 @@ public final class AppDelegateViewModel: AppDelegateViewModelType, AppDelegateVi
public let applicationIconBadgeNumber: Signal<Int, Never>
public let configureAppCenterWithData: Signal<AppCenterConfigData, Never>
public let configureFirebase: Signal<(), Never>
public let configureOptimizely: Signal<(String, OptimizelyLogLevelType, TimeInterval), Never>
public let configureFeatureFlagClient: Signal<OptimizelyClientType, Never>
public let configurePerimeterX: Signal<(), Never>
public let configureSegmentWithBraze: Signal<String, Never>
public let continueUserActivityReturnValue = MutableProperty(false)
Expand Down Expand Up @@ -1288,23 +1275,28 @@ extension ShortcutItem {
}
}

private func optimizelyData(for environment: Environment) -> (String, OptimizelyLogLevelType, TimeInterval) {
let environmentType = environment.environmentType
let logLevel = environment.mainBundle.isDebug ? OptimizelyLogLevelType.debug : OptimizelyLogLevelType.error
let dispatchInterval: TimeInterval = 5

var sdkKey: String

switch environmentType {
case .production:
sdkKey = Secrets.OptimizelySDKKey.production
case .staging:
sdkKey = Secrets.OptimizelySDKKey.staging
case .development, .local, .custom:
sdkKey = Secrets.OptimizelySDKKey.development
}

return (sdkKey, logLevel, dispatchInterval)
private func configureOptimizely(for _: Environment) -> OptimizelyClientType? {
// FIXME: This is until we add a new feature flagging client
let mockOptimizelyClient = MockOptimizelyClient()
|> \.experiments .~ [
OptimizelyExperiment.Key.nativeRiskMessaging.rawValue: OptimizelyExperiment.Variant.control.rawValue,
OptimizelyExperiment.Key.nativeProjectCards.rawValue: OptimizelyExperiment.Variant.control.rawValue,
OptimizelyExperiment.Key.onboardingCategoryPersonalizationFlow.rawValue: OptimizelyExperiment.Variant
.control.rawValue,
OptimizelyExperiment.Key.nativeOnboarding.rawValue: OptimizelyExperiment.Variant.control.rawValue
]
_ = mockOptimizelyClient
|> \.features .~
[
OptimizelyFeature.commentFlaggingEnabled.rawValue: false,
OptimizelyFeature.consentManagementDialogEnabled.rawValue: false,
OptimizelyFeature.facebookLoginDeprecationEnabled.rawValue: false,
OptimizelyFeature.settingsPaymentSheetEnabled.rawValue: true,
OptimizelyFeature.paymentSheetEnabled.rawValue: true,
OptimizelyFeature.projectPageStoryTabEnabled.rawValue: true
]

return mockOptimizelyClient
}

private func visitorCookies() -> [HTTPCookie] {
Expand Down

0 comments on commit 0c642e4

Please sign in to comment.