Skip to content

Commit

Permalink
v1.1.0 (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
yakovmanshin authored Dec 25, 2020
2 parents 0efbede + e035868 commit ae71331
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 7 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.DS_Store
/.build
/docs/docsets/
/.swiftpm
/Packages
/*.xcodeproj
Expand Down
30 changes: 30 additions & 0 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
author: Yakov Manshin
author_url: https://yakovmanshin.com/
clean: true
copyright: © 2020 [Yakov Manshin](https://yakovmanshin.com/). Available under [Apache License v2](https://github.com/yakovmanshin/YMFF/blob/main/LICENSE).
custom_categories:
- name: FeatureFlag
children:
- FeatureFlag
- FeatureFlagKey
- name: Resolver
children:
- FeatureFlagResolverProtocol
- FeatureFlagResolver
- FeatureFlagResolverConfigurationProtocol
- FeatureFlagResolverConfiguration
- FeatureFlagResolverError
- name: Stores
children:
- FeatureFlagStoreProtocol
- MutableFeatureFlagStoreProtocol
- FeatureFlagStore
- TransparentFeatureFlagStore
- RuntimeOverridesStore
disable_search: true
github_file_prefix: https://github.com/yakovmanshin/YMFF/tree/master
github_url: https://github.com/yakovmanshin/YMFF
hide_documentation_coverage: true
module: YMFF
title: YMFF Docs
undocumented_text: Documentation Coming Soon…
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,26 @@ if FeatureFlags.promoEnabled {
}
```

### Overriding Values in Runtime

YMFF lets you override feature flag values in runtime. One particular use case for changing values locally is when you need to test a particular feature covered with the feature flag, and you cannot or don’t want to modify the back-end configuration.

**Runtime overrides work within a single session. Once you restart the app, the override values are erased.**

Overriding a feature flag value in runtime is as simple as assigning the new value to the flag.

```swift
FeatureFlags.promoEnabled = true
```

To remove the override and revert to using values from persistent stores, you can restart the app or call the `removeRuntimeOverride()` method on `FeatureFlag`’s *projected value* (i.e. the `FeatureFlag` instance itself, as opposed to its *wrapped value*).

```swift
// Here `FeatureFlags.$promoEnabled` has the type `FeatureFlag<Bool>`,
// while `FeatureFlags.promoEnabled` is of type `Bool`.
FeatureFlags.$promoEnabled.removeRuntimeOverride()
```

You can browse the source files to learn more about the options available to you. An extended documentation is coming later.

## Contributing
Expand Down
28 changes: 22 additions & 6 deletions Sources/YMFF/FeatureFlag/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,26 @@

/// An object that facilitates access to feature flag values.
@propertyWrapper
public struct FeatureFlag<Value> {
final public class FeatureFlag<Value> {

// MARK: Properties

private let key: FeatureFlagKey
private let defaultValue: Value
/// The key used to retrieve feature flag values.
public let key: FeatureFlagKey

/// The fallback value returned when no store is able to provide the real one.
public let defaultValue: Value

private let resolver: FeatureFlagResolverProtocol

// MARK: Initializers

/// Creates a new `FeatureFlag`.
///
/// - Parameters:
/// - key: *Required.* The string used to address feature flag values in both the local and remote stores.
/// - defaultValue: *Required.* The value returned in case both the local and remote stores failed to provide values by the key.
/// - resolver: *Required.* The resolver object used to retrieve values from the stores.
/// - key: *Required.* The key used to address feature flag values in stores.
/// - defaultValue: *Required.* The value returned in case all stores fail to provide a value.
/// - resolver: *Required.* The resolver object used to retrieve values from stores.
public init(
_ key: FeatureFlagKey,
default defaultValue: Value,
Expand All @@ -45,4 +49,16 @@ public struct FeatureFlag<Value> {
}
}

// MARK: Projected Value

/// The object returned when referencing the feature flag with a dollar sign (`$`).
public var projectedValue: FeatureFlag<Value> { self }

// MARK: Runtime Overrides

/// Removes the feature flag value that overrides persistent values in runtime.
public func removeRuntimeOverride() {
resolver.removeRuntimeOverride(for: key)
}

}
38 changes: 38 additions & 0 deletions Tests/YMFFTests/FeatureFlagTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ extension FeatureFlagTests {
overrideFlag = 789

XCTAssertEqual(overrideFlag, 789)

$overrideFlag.removeRuntimeOverride()

XCTAssertEqual(overrideFlag, 456)
}

func testNonexistentWrappedValueOverride() {
Expand All @@ -76,6 +80,40 @@ extension FeatureFlagTests {
nonexistentOverrideFlag = 789

XCTAssertEqual(nonexistentOverrideFlag, 789)

$nonexistentOverrideFlag.removeRuntimeOverride()

XCTAssertEqual(nonexistentOverrideFlag, 999)
}

}

// MARK: - Projected Value Tests

extension FeatureFlagTests {

func testBoolProjectedValue() {
XCTAssertTrue(value($boolFeatureFlag, isOfType: FeatureFlag<Bool>.self))
}

func testIntProjectedValue() {
XCTAssertTrue(value($intFeatureFlag, isOfType: FeatureFlag<Int>.self))
}

func testStringProjectedValue() {
XCTAssertTrue(value($stringFeatureFlag, isOfType: FeatureFlag<String>.self))
}

func testOptionalIntProjectedValue() {
XCTAssertTrue(value($optionalIntFeatureFlag, isOfType: FeatureFlag<Int?>.self))
}

func testNonexistentIntProjectedValue() {
XCTAssertTrue(value($nonexistentIntFeatureFlag, isOfType: FeatureFlag<Int>.self))
}

private func value<T>(_ value: Any, isOfType type: T.Type) -> Bool {
value is T
}

}
5 changes: 5 additions & 0 deletions Tests/YMFFTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ extension FeatureFlagTests {
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__FeatureFlagTests = [
("testBoolProjectedValue", testBoolProjectedValue),
("testBoolWrappedValue", testBoolWrappedValue),
("testIntProjectedValue", testIntProjectedValue),
("testIntWrappedValue", testIntWrappedValue),
("testNonexistentIntProjectedValue", testNonexistentIntProjectedValue),
("testNonexistentIntWrappedValue", testNonexistentIntWrappedValue),
("testNonexistentWrappedValueOverride", testNonexistentWrappedValueOverride),
("testOptionalIntProjectedValue", testOptionalIntProjectedValue),
("testOptionalIntValue", testOptionalIntValue),
("testStringProjectedValue", testStringProjectedValue),
("testStringWrappedValue", testStringWrappedValue),
("testWrappedValueOverride", testWrappedValueOverride),
]
Expand Down

0 comments on commit ae71331

Please sign in to comment.