diff --git a/Sources/OpenFeature/EventHandler.swift b/Sources/OpenFeature/EventHandler.swift index f1a5680..28c08ae 100644 --- a/Sources/OpenFeature/EventHandler.swift +++ b/Sources/OpenFeature/EventHandler.swift @@ -4,8 +4,12 @@ import Combine public class EventHandler: EventSender, EventPublisher { private let eventState: CurrentValueSubject + convenience init() { + self.init(.notReady) + } + public init(_ state: ProviderEvent) { - eventState = CurrentValueSubject(ProviderEvent.stale) + eventState = CurrentValueSubject(state) } public func observe() -> AnyPublisher { diff --git a/Sources/OpenFeature/Provider/NoOpProvider.swift b/Sources/OpenFeature/Provider/NoOpProvider.swift index 6f35cbc..7e1c28a 100644 --- a/Sources/OpenFeature/Provider/NoOpProvider.swift +++ b/Sources/OpenFeature/Provider/NoOpProvider.swift @@ -4,7 +4,7 @@ import Combine /// A ``FeatureProvider`` that simply returns the default values passed to it. class NoOpProvider: FeatureProvider { public static let passedInDefault = "Passed in default" - private let eventHandler = EventHandler(.ready) + private let eventHandler = EventHandler() public enum Mode { case normal diff --git a/Sources/OpenFeature/Provider/ProviderEvents.swift b/Sources/OpenFeature/Provider/ProviderEvents.swift index 30f44cf..2f40a44 100644 --- a/Sources/OpenFeature/Provider/ProviderEvents.swift +++ b/Sources/OpenFeature/Provider/ProviderEvents.swift @@ -9,4 +9,5 @@ public enum ProviderEvent: String, CaseIterable { case error = "PROVIDER_ERROR" case configurationChanged = "PROVIDER_CONFIGURATION_CHANGED" case stale = "PROVIDER_STALE" + case notReady = "PROVIDER_NOT_READY" } diff --git a/Tests/OpenFeatureTests/DeveloperExperienceTests.swift b/Tests/OpenFeatureTests/DeveloperExperienceTests.swift index b7685b1..26bdd5c 100644 --- a/Tests/OpenFeatureTests/DeveloperExperienceTests.swift +++ b/Tests/OpenFeatureTests/DeveloperExperienceTests.swift @@ -20,17 +20,14 @@ final class DeveloperExperienceTests: XCTestCase { } func testObserveGlobalEvents() { + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") - let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") var eventState = OpenFeatureAPI.shared.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: - errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") } @@ -50,18 +47,18 @@ final class DeveloperExperienceTests: XCTestCase { } func testSetProviderAndWait() async { + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") withExtendedLifetime( OpenFeatureAPI.shared.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: + case .error: errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") } @@ -69,15 +66,14 @@ final class DeveloperExperienceTests: XCTestCase { { let initCompleteExpectation = XCTestExpectation() - let eventHandler = EventHandler(.stale) + let eventHandler = EventHandler() let provider = InjectableEventHandlerProvider(eventHandler: eventHandler) Task { await OpenFeatureAPI.shared.setProviderAndWait(provider: provider) wait(for: [readyExpectation], timeout: 1) initCompleteExpectation.fulfill() } - - wait(for: [staleExpectation], timeout: 1) + wait(for: [notReadyExpectation], timeout: 1) eventHandler.send(.ready) wait(for: [initCompleteExpectation], timeout: 1) diff --git a/Tests/OpenFeatureTests/FlagEvaluationTests.swift b/Tests/OpenFeatureTests/FlagEvaluationTests.swift index 880330c..f7f7b3f 100644 --- a/Tests/OpenFeatureTests/FlagEvaluationTests.swift +++ b/Tests/OpenFeatureTests/FlagEvaluationTests.swift @@ -53,23 +53,26 @@ final class FlagEvaluationTests: XCTestCase { func testSimpleFlagEvaluation() { let provider = DoSomethingProvider() + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") let errorExpectation = XCTestExpectation(description: "Error") let staleExpectation = XCTestExpectation(description: "Stale") let eventState = provider.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: + case .error: errorExpectation.fulfill() - case ProviderEvent.stale: + case .stale: staleExpectation.fulfill() default: XCTFail("Unexpected event") } } - wait(for: [staleExpectation], timeout: 5) + wait(for: [notReadyExpectation], timeout: 5) OpenFeatureAPI.shared.setProvider(provider: provider) wait(for: [readyExpectation], timeout: 5) let client = OpenFeatureAPI.shared.getClient() @@ -109,17 +112,14 @@ final class FlagEvaluationTests: XCTestCase { func testDetailedFlagEvaluation() async { let provider = DoSomethingProvider() + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") - let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") let eventState = provider.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: - errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") } @@ -170,17 +170,14 @@ final class FlagEvaluationTests: XCTestCase { func testHooksAreFired() async { let provider = NoOpProvider() + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") - let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") let eventState = provider.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: - errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") } @@ -207,16 +204,19 @@ final class FlagEvaluationTests: XCTestCase { func testBrokenProvider() { let provider = AlwaysBrokenProvider() + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") let errorExpectation = XCTestExpectation(description: "Error") let staleExpectation = XCTestExpectation(description: "Stale") let eventState = provider.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: + case .error: errorExpectation.fulfill() - case ProviderEvent.stale: + case .stale: staleExpectation.fulfill() default: XCTFail("Unexpected event") diff --git a/Tests/OpenFeatureTests/Helpers/AlwaysBrokenProvider.swift b/Tests/OpenFeatureTests/Helpers/AlwaysBrokenProvider.swift index f660e7a..cf8a789 100644 --- a/Tests/OpenFeatureTests/Helpers/AlwaysBrokenProvider.swift +++ b/Tests/OpenFeatureTests/Helpers/AlwaysBrokenProvider.swift @@ -6,7 +6,7 @@ import Combine class AlwaysBrokenProvider: FeatureProvider { var metadata: ProviderMetadata = AlwaysBrokenMetadata() var hooks: [any Hook] = [] - private let eventHandler = EventHandler(.stale) + private let eventHandler = EventHandler() func onContextSet(oldContext: OpenFeature.EvaluationContext?, newContext: OpenFeature.EvaluationContext) { eventHandler.send(.error) diff --git a/Tests/OpenFeatureTests/Helpers/DoSomethingProvider.swift b/Tests/OpenFeatureTests/Helpers/DoSomethingProvider.swift index c58a4e2..f2b3945 100644 --- a/Tests/OpenFeatureTests/Helpers/DoSomethingProvider.swift +++ b/Tests/OpenFeatureTests/Helpers/DoSomethingProvider.swift @@ -4,7 +4,7 @@ import Combine class DoSomethingProvider: FeatureProvider { public static let name = "Something" - private let eventHandler = EventHandler(.ready) + private let eventHandler = EventHandler(.notReady) private var holdit: AnyCancellable? func onContextSet(oldContext: OpenFeature.EvaluationContext?, newContext: OpenFeature.EvaluationContext) { diff --git a/Tests/OpenFeatureTests/Helpers/InjectableEventHandlerProvider.swift b/Tests/OpenFeatureTests/Helpers/InjectableEventHandlerProvider.swift index dd435e4..d635ed3 100644 --- a/Tests/OpenFeatureTests/Helpers/InjectableEventHandlerProvider.swift +++ b/Tests/OpenFeatureTests/Helpers/InjectableEventHandlerProvider.swift @@ -11,13 +11,11 @@ class InjectableEventHandlerProvider: FeatureProvider { } func onContextSet(oldContext: OpenFeature.EvaluationContext?, newContext: OpenFeature.EvaluationContext) { - // Emit stale, then let the parent test control events via eventHandler - eventHandler.send(.stale) + // Let the parent test control events via eventHandler } func initialize(initialContext: OpenFeature.EvaluationContext?) { - // Emit stale, then let the parent test control events via eventHandler - eventHandler.send(.stale) + // Let the parent test control events via eventHandler } var hooks: [any OpenFeature.Hook] = [] diff --git a/Tests/OpenFeatureTests/HookSpecTests.swift b/Tests/OpenFeatureTests/HookSpecTests.swift index b39d3e8..67cdf68 100644 --- a/Tests/OpenFeatureTests/HookSpecTests.swift +++ b/Tests/OpenFeatureTests/HookSpecTests.swift @@ -6,17 +6,14 @@ import XCTest final class HookSpecTests: XCTestCase { func testNoErrorHookCalled() { let provider = NoOpProvider() + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") - let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") let eventState = provider.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: - errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") } @@ -42,17 +39,17 @@ final class HookSpecTests: XCTestCase { func testErrorHookButNoAfterCalled() { let provider = AlwaysBrokenProvider() + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") let eventState = provider.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: + case .error: errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") } @@ -84,17 +81,14 @@ final class HookSpecTests: XCTestCase { let providerMock = NoOpProviderMock(hooks: [ BooleanHookMock(prefix: "provider", addEval: addEval) ]) + let notReadyExpectation = XCTestExpectation(description: "NotReady") let readyExpectation = XCTestExpectation(description: "Ready") - let errorExpectation = XCTestExpectation(description: "Error") - let staleExpectation = XCTestExpectation(description: "Stale") let eventState = providerMock.observe().sink { event in switch event { - case ProviderEvent.ready: + case .notReady: + notReadyExpectation.fulfill() + case .ready: readyExpectation.fulfill() - case ProviderEvent.error: - errorExpectation.fulfill() - case ProviderEvent.stale: - staleExpectation.fulfill() default: XCTFail("Unexpected event") }