Skip to content
This repository has been archived by the owner on Jan 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #64 from saniazafar/feature/tweak-throwable-getter…
Browse files Browse the repository at this point in the history
…-function

Tweak getter function made throwable
  • Loading branch information
albertodebortoli authored Jan 10, 2022
2 parents a694e2d + 8ede397 commit 0991e1f
Show file tree
Hide file tree
Showing 22 changed files with 168 additions and 121 deletions.
12 changes: 12 additions & 0 deletions Errors/TweakError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// TweakError.swift
// Copyright (c) 2022 Just Eat Holding Ltd. All rights reserved.
//

import Foundation

public enum TweakError: String, Error {
case notFound = "Feature or variable is not found"
case notSupported = "Variable type is not supported"
case decryptionClosureNotProvided = "Value is encrypted but there's no decryption closure provided"
}
18 changes: 9 additions & 9 deletions Example/JustTweak/Accessors/GeneratedTweakAccessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,47 +15,47 @@ class GeneratedTweakAccessor {
}

var canShowGreenView: Bool {
get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayGreenView)?.boolValue ?? false }
get { (try? tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayGreenView))?.boolValue ?? false }
set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayGreenView) }
}

var canShowRedView: Bool {
get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayRedView)?.boolValue ?? false }
get { (try? tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayRedView))?.boolValue ?? false }
set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayRedView) }
}

var canShowYellowView: Bool {
get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayYellowView)?.boolValue ?? false }
get { (try? tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayYellowView))?.boolValue ?? false }
set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.displayYellowView) }
}

var definitiveAnswerEncrypted: String {
get { tweakManager.tweakWith(feature: Features.general, variable: Variables.encryptedAnswerToTheUniverse)?.stringValue ?? "" }
get { (try? tweakManager.tweakWith(feature: Features.general, variable: Variables.encryptedAnswerToTheUniverse))?.stringValue ?? "" }
set { tweakManager.set(newValue, feature: Features.general, variable: Variables.encryptedAnswerToTheUniverse) }
}

var isTapGestureToChangeColorEnabled: Bool {
get { tweakManager.tweakWith(feature: Features.general, variable: Variables.tapToChangeColorEnabled)?.boolValue ?? false }
get { (try? tweakManager.tweakWith(feature: Features.general, variable: Variables.tapToChangeColorEnabled))?.boolValue ?? false }
set { tweakManager.set(newValue, feature: Features.general, variable: Variables.tapToChangeColorEnabled) }
}

var labelText: String {
get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.labelText)?.stringValue ?? "" }
get { (try? tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.labelText))?.stringValue ?? "" }
set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.labelText) }
}

var meaningOfLife: Int {
get { tweakManager.tweakWith(feature: Features.general, variable: Variables.answerToTheUniverse)?.intValue ?? 0 }
get { (try? tweakManager.tweakWith(feature: Features.general, variable: Variables.answerToTheUniverse))?.intValue ?? 0 }
set { tweakManager.set(newValue, feature: Features.general, variable: Variables.answerToTheUniverse) }
}

var redViewAlpha: Double {
get { tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.redViewAlphaComponent)?.doubleValue ?? 0.0 }
get { (try? tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.redViewAlphaComponent))?.doubleValue ?? 0.0 }
set { tweakManager.set(newValue, feature: Features.uiCustomization, variable: Variables.redViewAlphaComponent) }
}

var shouldShowAlert: Bool {
get { tweakManager.tweakWith(feature: Features.general, variable: Variables.greetOnAppDidBecomeActive)?.boolValue ?? false }
get { (try? tweakManager.tweakWith(feature: Features.general, variable: Variables.greetOnAppDidBecomeActive))?.boolValue ?? false }
set { tweakManager.set(newValue, feature: Features.general, variable: Variables.greetOnAppDidBecomeActive) }
}
}
16 changes: 8 additions & 8 deletions Example/JustTweak/Accessors/TweakAccessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,18 @@ class TweakAccessor {
// MARK: - Via TweakManager

var canShowYellowView: Bool {
return tweakManager.tweakWith(feature: Features.uiCustomization,
variable: Variables.displayYellowView)?.boolValue ?? false
return (try? tweakManager.tweakWith(feature: Features.uiCustomization,
variable: Variables.displayYellowView))?.boolValue ?? false
}

var redViewAlpha: Float {
return tweakManager.tweakWith(feature: Features.uiCustomization,
variable: Variables.redViewAlpha)?.floatValue ?? 0.0
return (try? tweakManager.tweakWith(feature: Features.uiCustomization,
variable: Variables.redViewAlpha))?.floatValue ?? 0.0
}

var isTapGestureToChangeColorEnabled: Bool {
return tweakManager.tweakWith(feature: Features.general,
variable: Variables.tapToChangeViewColor)?.boolValue ?? false
return (try? tweakManager.tweakWith(feature: Features.general,
variable: Variables.tapToChangeViewColor))?.boolValue ?? false
}
}

4 changes: 2 additions & 2 deletions Example/JustTweak/TweakProviders/FirebaseTweakProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public class FirebaseTweakProvider: TweakProvider {
return configValue.boolValue
}

public func tweakWith(feature: String, variable: String) -> Tweak? {
guard configured else { return nil }
public func tweakWith(feature: String, variable: String) throws -> Tweak {
guard configured else { throw TweakError.notFound }
let configValue = remoteConfiguration.configValue(forKey: variable)
guard configValue.source != .static else { return nil }
guard let stringValue = configValue.stringValue else { return nil }
Expand Down
18 changes: 10 additions & 8 deletions Example/JustTweak/TweakProviders/OptimizelyTweakProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,12 @@ public class OptimizelyTweakProvider: TweakProvider {
return optimizelyClient?.isFeatureEnabled(feature, userId: userId, attributes: attributes) ?? false
}

public func tweakWith(feature: String, variable: String) -> Tweak? {
guard let optimizelyClient = optimizelyClient else { return nil }
guard optimizelyClient.isFeatureEnabled(feature, userId: userId, attributes: attributes) == true else { return nil }
public func tweakWith(feature: String, variable: String) throws -> Tweak {
guard let optimizelyClient = optimizelyClient,
optimizelyClient.isFeatureEnabled(feature, userId: userId, attributes: attributes) == true
else {
throw TweakError.notFound
}

let tweakValue: TweakValue? = {
if let boolValue = optimizelyClient.getFeatureVariableBoolean(feature, variableKey: variable, userId: userId, attributes: attributes)?.boolValue {
Expand All @@ -66,11 +69,10 @@ public class OptimizelyTweakProvider: TweakProvider {
}
return nil
}()
if let tweakValue = tweakValue {
return Tweak(feature: feature, variable: variable, value: tweakValue, title: nil, group: nil)

guard let tweakValue = tweakValue else {
throw TweakError.notFound
}

return nil
return Tweak(feature: feature, variable: variable, value: tweakValue, title: nil, group: nil)
}
}
12 changes: 6 additions & 6 deletions Example/Tests/Core/LocalTweakProviderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class LocalTweakProviderTests: XCTestCase {
value: true,
title: "Display Red View",
group: "UI Customization")
XCTAssertEqual(redViewTweak, tweakProvider.tweakWith(feature: Features.uiCustomization,
variable: Variables.displayRedView))
XCTAssertEqual(redViewTweak, try tweakProvider.tweakWith(feature: Features.uiCustomization,
variable: Variables.displayRedView))
}

func testParsesFloatTweak() {
Expand All @@ -42,17 +42,17 @@ class LocalTweakProviderTests: XCTestCase {
value: 1.0,
title: "Red View Alpha Component",
group: "UI Customization")
XCTAssertEqual(redViewAlphaTweak, tweakProvider.tweakWith(feature: Features.uiCustomization,
variable: Variables.redViewAlpha))
XCTAssertEqual(redViewAlphaTweak, try tweakProvider.tweakWith(feature: Features.uiCustomization,
variable: Variables.redViewAlpha))
}

func testParsesStringTweak() {
let buttonLabelTweak = Tweak(feature: Features.uiCustomization,
variable: Variables.labelText,
value: "Test value",
title: "Label Text", group: "UI Customization")
XCTAssertEqual(buttonLabelTweak, tweakProvider.tweakWith(feature: Features.uiCustomization,
variable: Variables.labelText))
XCTAssertEqual(buttonLabelTweak, try tweakProvider.tweakWith(feature: Features.uiCustomization,
variable: Variables.labelText))
}

func testDecryptionClosure() {
Expand Down
26 changes: 15 additions & 11 deletions Example/Tests/Core/TweakManagerCacheTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import XCTest
@testable import JustTweak
@testable import JustTweak_Example

fileprivate struct Constants {
static let featureActiveValue = true
Expand Down Expand Up @@ -55,28 +56,28 @@ class TweakManagerCacheTests: XCTestCase {

// MARK: - tweakWith(feature:variable:)

func testTweakFetch_CacheDisabled() {
tweakFetch(useCache: false)
func testTweakFetch_CacheDisabled() throws {
try tweakFetch(useCache: false)
}

func testTweakFetch_CacheEnabled() {
tweakFetch(useCache: true)
func testTweakFetch_CacheEnabled() throws {
try tweakFetch(useCache: true)
}

private func tweakFetch(useCache: Bool) {
private func tweakFetch(useCache: Bool) throws {
tweakManager.useCache = useCache
XCTAssertEqual(mockTweakProvider.tweakWithFeatureVariableCallsCounter, 0)
let value = true
tweakManager.set(value, feature: Constants.feature, variable: Constants.variable)
XCTAssertEqual(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)!.value as! Bool, value)
XCTAssertEqual(try XCTUnwrap(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)).value as! Bool, value)
XCTAssertEqual(mockTweakProvider.tweakWithFeatureVariableCallsCounter, 1)
XCTAssertEqual(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)!.value as! Bool, value)
XCTAssertEqual(try XCTUnwrap(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)).value as! Bool, value)
XCTAssertEqual(mockTweakProvider.tweakWithFeatureVariableCallsCounter, useCache ? 1 : 2)
tweakManager.set(value, feature: Constants.feature, variable: Constants.variable)
XCTAssertEqual(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)!.value as! Bool, value)
XCTAssertEqual(try XCTUnwrap(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)).value as! Bool, value)
XCTAssertEqual(mockTweakProvider.tweakWithFeatureVariableCallsCounter, useCache ? 2 : 3)
tweakManager.resetCache()
XCTAssertEqual(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)!.value as! Bool, value)
XCTAssertEqual(try XCTUnwrap(tweakManager.tweakWith(feature: Constants.feature, variable: Constants.variable)).value as! Bool, value)
XCTAssertEqual(mockTweakProvider.tweakWithFeatureVariableCallsCounter, useCache ? 3 : 4)
}
}
Expand All @@ -97,9 +98,12 @@ fileprivate class MockTweakProvider: MutableTweakProvider {
return featureBackingStore[feature] ?? false
}

func tweakWith(feature: String, variable: String) -> Tweak? {
func tweakWith(feature: String, variable: String) throws -> Tweak {
tweakWithFeatureVariableCallsCounter += 1
return tweakBackingStore[feature]?[variable]
guard let tweak = tweakBackingStore[feature]?[variable] else {
throw TweakError.notFound
}
return tweak
}

func set(_ value: TweakValue, feature: String, variable: String) {
Expand Down
32 changes: 16 additions & 16 deletions Example/Tests/Core/TweakManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,33 @@ class TweakManagerTests: XCTestCase {
}

func testReturnsNil_ForUndefinedTweak() {
XCTAssertNil(tweakManager.tweakWith(feature: Features.uiCustomization, variable: "some_undefined_tweak"))
XCTAssertNil(try? tweakManager.tweakWith(feature: Features.uiCustomization, variable: "some_undefined_tweak"))
}

func testReturnsRemoteConfigValue_ForDisplayRedViewTweak() {
XCTAssertTrue(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayRedView)!.boolValue)
func testReturnsRemoteConfigValue_ForDisplayRedViewTweak() throws {
XCTAssertTrue(try XCTUnwrap(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayRedView)).boolValue)
}

func testReturnsRemoteConfigValue_ForDisplayYellowViewTweak() {
XCTAssertFalse(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayYellowView)!.boolValue)
func testReturnsRemoteConfigValue_ForDisplayYellowViewTweak() throws {
XCTAssertFalse(try XCTUnwrap(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayYellowView)).boolValue)
}

func testReturnsRemoteConfigValue_ForDisplayGreenViewTweak() {
XCTAssertFalse(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayGreenView)!.boolValue)
func testReturnsRemoteConfigValue_ForDisplayGreenViewTweak() throws {
XCTAssertFalse(try XCTUnwrap(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.displayGreenView)).boolValue)
}

func testReturnsRemoteConfigValue_ForGreetOnAppDidBecomeActiveTweak() {
XCTAssertTrue(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.greetOnAppDidBecomeActive)!.boolValue)
func testReturnsRemoteConfigValue_ForGreetOnAppDidBecomeActiveTweak() throws {
XCTAssertTrue(try XCTUnwrap(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.greetOnAppDidBecomeActive)).boolValue)
}

func testReturnsJSONConfigValue_ForTapToChangeViewColorTweak_AsYetUnkown() {
XCTAssertTrue(tweakManager.tweakWith(feature: Features.general, variable: Variables.tapToChangeViewColor)!.boolValue)
func testReturnsJSONConfigValue_ForTapToChangeViewColorTweak_AsYetUnkown() throws {
XCTAssertTrue(try XCTUnwrap(tweakManager.tweakWith(feature: Features.general, variable: Variables.tapToChangeViewColor)).boolValue)
}

func testReturnsUserSetValue_ForGreetOnAppDidBecomeActiveTweak_AfterUpdatingUserDefaultsTweakProvider() {
func testReturnsUserSetValue_ForGreetOnAppDidBecomeActiveTweak_AfterUpdatingUserDefaultsTweakProvider() throws {
let mutableTweakProvider = tweakManager.mutableTweakProvider!
mutableTweakProvider.set(false, feature: Features.uiCustomization, variable: Variables.greetOnAppDidBecomeActive)
XCTAssertFalse(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.greetOnAppDidBecomeActive)!.boolValue)
XCTAssertFalse(try XCTUnwrap(tweakManager.tweakWith(feature: Features.uiCustomization, variable: Variables.greetOnAppDidBecomeActive)).boolValue)
}

func testCallsClosureForRegisteredObserverWhenAnyConfigurationChanges() {
Expand Down Expand Up @@ -100,7 +100,7 @@ class TweakManagerTests: XCTestCase {

let feature = "general"
let variable = "encrypted_answer_to_the_universe"
let tweak = tweakManager.tweakWith(feature: feature, variable: variable)
let tweak = try? tweakManager.tweakWith(feature: feature, variable: variable)

XCTAssertEqual("Definitely not 42", tweak?.stringValue)
}
Expand Down Expand Up @@ -132,8 +132,8 @@ fileprivate class MockTweakProvider: TweakProvider {
return false
}

func tweakWith(feature: String, variable: String) -> Tweak? {
guard let value = knownValues[variable] else { return nil }
func tweakWith(feature: String, variable: String) throws -> Tweak {
guard let value = knownValues[variable] else { throw TweakError.notFound }
return Tweak(feature: feature, variable: variable, value: value["Value"]!, title: nil, group: nil)
}
}
Loading

0 comments on commit 0991e1f

Please sign in to comment.