From 0f1a9a8b3c466778ae8a86df898f7fba5eb538d1 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Mon, 23 Dec 2024 20:53:20 +0100 Subject: [PATCH 1/2] feat: Openfeature SDK spec 0.8 support Signed-off-by: Thomas Poignant --- Package.resolved | 6 +- Package.swift | 2 +- .../hook/data_collector_bool_hook.swift | 2 +- .../hook/data_collector_double_hook.swift | 2 +- .../hook/data_collector_integer_hook.swift | 2 +- .../hook/data_collector_object_hook.swift | 3 +- .../hook/data_collector_string_hook.swift | 2 +- Sources/GOFeatureFlag/provider.swift | 10 +- Sources/OFREP/ofrep.swift | 77 ++++--- Tests/GOFeatureFlagTests/provider_tests.swift | 12 +- Tests/OFREPTests/provider_tests.swift | 198 ++++++++---------- 11 files changed, 141 insertions(+), 175 deletions(-) diff --git a/Package.resolved b/Package.resolved index c211631..a0ffc8b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,9 +5,9 @@ "package": "OpenFeature", "repositoryURL": "https://github.com/open-feature/swift-sdk.git", "state": { - "branch": null, - "revision": "907567cf9d43aad4c015a8758a7d53d755e76213", - "version": "0.2.0" + "branch": "fatal-state", + "revision": "81c9fa27c9091cca3c32211e627b3811a3e5e059", + "version": null } } ] diff --git a/Package.swift b/Package.swift index b74367d..b059cbc 100644 --- a/Package.swift +++ b/Package.swift @@ -18,7 +18,7 @@ let package = Package( targets: ["OFREP"]) ], dependencies: [ - .package(url: "https://github.com/open-feature/swift-sdk.git", from: "0.2.0") + .package(url: "https://github.com/open-feature/swift-sdk.git", branch: "fatal-state"), ], targets: [ .target( diff --git a/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift index 09a9020..f0a447c 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift @@ -66,7 +66,7 @@ class BooleanHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finallyAfter(ctx: HookContext, hints: [String: Any]) { + func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift index 7f366cf..aa17457 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift @@ -67,7 +67,7 @@ class DoubleHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finallyAfter(ctx: HookContext, hints: [String: Any]) { + func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift index 54b36cb..aea01b0 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift @@ -63,7 +63,7 @@ class IntegerHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finallyAfter(ctx: HookContext, hints: [String: Any]) { + func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift index 5031044..68264ae 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift @@ -65,7 +65,8 @@ class ObjectHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finallyAfter(ctx: HookContext, hints: [String: Any]) { + + func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift index 5c199c1..ef6513e 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift @@ -66,7 +66,7 @@ class StringHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finallyAfter(ctx: HookContext, hints: [String: Any]) { + func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ return } } diff --git a/Sources/GOFeatureFlag/provider.swift b/Sources/GOFeatureFlag/provider.swift index 3d3d7a5..55fcccc 100644 --- a/Sources/GOFeatureFlag/provider.swift +++ b/Sources/GOFeatureFlag/provider.swift @@ -38,9 +38,9 @@ public final class GoFeatureFlagProvider: FeatureProvider { ) } - public func initialize(initialContext: (any OpenFeature.EvaluationContext)?) { + public func initialize(initialContext: OpenFeature.EvaluationContext?) async throws { self.hooks = dataCollectorMngr.getHooks() - self.ofrepProvider.initialize(initialContext: initialContext) + try await self.ofrepProvider.initialize(initialContext: initialContext) if self.options.dataCollectorInterval > 0 { self.hooks.append(BooleanHook(dataCollectorMngr: self.dataCollectorMngr)) @@ -54,8 +54,8 @@ public final class GoFeatureFlagProvider: FeatureProvider { public func onContextSet( oldContext: (any OpenFeature.EvaluationContext)?, - newContext: any OpenFeature.EvaluationContext) { - self.ofrepProvider.onContextSet( + newContext: any OpenFeature.EvaluationContext) async throws { + try await self.ofrepProvider.onContextSet( oldContext: oldContext, newContext: newContext) } @@ -115,7 +115,7 @@ public final class GoFeatureFlagProvider: FeatureProvider { context: context) } - public func observe() -> AnyPublisher { + public func observe() -> AnyPublisher { return self.ofrepProvider.observe() } } diff --git a/Sources/OFREP/ofrep.swift b/Sources/OFREP/ofrep.swift index 2f227e9..6b8622f 100644 --- a/Sources/OFREP/ofrep.swift +++ b/Sources/OFREP/ofrep.swift @@ -7,7 +7,7 @@ struct Metadata: ProviderMetadata { } public class OfrepProvider: FeatureProvider { - private let eventHandler = EventHandler(ProviderEvent.notReady) + private let eventHandler = EventHandler() private var evaluationContext: OpenFeature.EvaluationContext? private var options: OfrepProviderOptions @@ -26,54 +26,53 @@ public class OfrepProvider: FeatureProvider { self.ofrepAPI = OfrepAPI(networkingService: networkService, options: self.options) } - public func observe() -> AnyPublisher { - return eventHandler.observe() - } - public var hooks: [any Hook] = [] public var metadata: ProviderMetadata = Metadata() - public func initialize(initialContext: (any OpenFeature.EvaluationContext)?) { + public func observe() -> AnyPublisher { + return eventHandler.observe() + } + + public func initialize(initialContext: (any OpenFeature.EvaluationContext)?) async throws { self.evaluationContext = initialContext - Task { - do { - let status = try await self.evaluateFlags(context: self.evaluationContext) - if self.options.pollInterval > 0 { - self.startPolling(pollInterval: self.options.pollInterval) - } + do { + let status = try await self.evaluateFlags(context: self.evaluationContext) + if self.options.pollInterval > 0 { + self.startPolling(pollInterval: self.options.pollInterval) + } - if status == .successWithChanges { - self.eventHandler.send(.ready) - return - } - self.eventHandler.send(.error) - } catch { - // TODO: Should be FATAL here - self.eventHandler.send(.error) + if status == .successWithChanges { + return + } + + throw OpenFeatureError.generalError(message: "impossible to initialize the provider, receive unknown status") + } catch { + switch error { + case OfrepError.apiUnauthorizedError, OfrepError.forbiddenError: + throw OpenFeatureError.providerFatalError(message: error.localizedDescription) + default: + throw error } } } public func onContextSet(oldContext: (any OpenFeature.EvaluationContext)?, - newContext: any OpenFeature.EvaluationContext) { - self.eventHandler.send(.stale) + newContext: any OpenFeature.EvaluationContext) async throws { self.evaluationContext = newContext - Task { - do { - let status = try await self.evaluateFlags(context: newContext) - if(status == .successWithChanges || status == .successNoChanges ) { - self.eventHandler.send(.ready) - } - } catch let error as OfrepError { - switch error { - case .apiTooManyRequestsError: - return // we want to stay stale in that case so we ignore the error. - default: - throw error - } - } catch { - self.eventHandler.send(.error) + do { + let status = try await self.evaluateFlags(context: newContext) + if(status == .successWithChanges || status == .successNoChanges ) { + return } + } catch let error as OfrepError { + switch error { + case .apiTooManyRequestsError: + return // we want to stay stale in that case so we ignore the error. + default: + throw error + } + } catch { + throw error } } @@ -282,10 +281,10 @@ public class OfrepProvider: FeatureProvider { weakSelf.eventHandler.send(.stale) throw error default: - weakSelf.eventHandler.send(.error) + throw error } } catch { - weakSelf.eventHandler.send(.error) + throw error } } } diff --git a/Tests/GOFeatureFlagTests/provider_tests.swift b/Tests/GOFeatureFlagTests/provider_tests.swift index 5fb250c..945e3be 100644 --- a/Tests/GOFeatureFlagTests/provider_tests.swift +++ b/Tests/GOFeatureFlagTests/provider_tests.swift @@ -23,19 +23,19 @@ class GoFeatureFlagProviderTests: XCTestCase { let evaluationCtx = MutableContext(targetingKey: "ede04e44-463d-40d1-8fc0-b1d6855578d0") let api = OpenFeatureAPI() await api.setProviderAndWait(provider: provider, initialContext: evaluationCtx) + XCTAssertEqual(api.getProviderStatus(), ProviderStatus.ready) + + let client = api.getClient() - + let expectation = self.expectation(description: "Waiting for delay") _ = client.getBooleanDetails(key: "my-flag", defaultValue: false) _ = client.getBooleanDetails(key: "my-flag", defaultValue: false) _ = client.getIntegerDetails(key: "int-flag", defaultValue: 1) _ = client.getDoubleDetails(key: "double-flag", defaultValue: 1.0) _ = client.getStringDetails(key: "string-flag", defaultValue: "default") _ = client.getObjectDetails(key: "object-flag", defaultValue: Value.null) - - let expectation = self.expectation(description: "Waiting for delay") - - DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) { expectation.fulfill() } - await fulfillment(of: [expectation], timeout: 2.0) + DispatchQueue.global().asyncAfter(deadline: .now() + 1.5) { expectation.fulfill() } + await fulfillment(of: [expectation], timeout: 3.0) XCTAssertEqual(1, mockNetworkService.dataCollectorCallCounter) XCTAssertEqual(6, mockNetworkService.dataCollectorEventCounter) diff --git a/Tests/OFREPTests/provider_tests.swift b/Tests/OFREPTests/provider_tests.swift index 0565330..f26e03d 100644 --- a/Tests/OFREPTests/provider_tests.swift +++ b/Tests/OFREPTests/provider_tests.swift @@ -34,9 +34,6 @@ class ProviderTests: XCTestCase { } func testShouldBeInFATALStatusIf401ErrorDuringInitialise() async { - // TODO: PROVIDER_FATAL event does not exist for now, we will test that the provider is in ERROR - // issue open for the fatal state: https://github.com/open-feature/swift-sdk/issues/40 - let mockResponse = "{}" let mockService = MockNetworkingService(mockData: mockResponse.data(using: .utf8), mockStatus: 401) @@ -48,22 +45,10 @@ class ProviderTests: XCTestCase { let api = OpenFeatureAPI() await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) - let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in - // TODO: Move to FATAL when the event will be handled by the SDK - if(event != ProviderEvent.error){ - XCTFail("If OFREP API returns a 401 we should receive a FATAL event, received: \(event)") - } - expectation.fulfill() - } - - await fulfillment(of: [expectation], timeout: 3.0) + XCTAssertEqual(api.getProviderStatus(), ProviderStatus.fatal) } func testShouldBeInFATALStatusIf403ErrorDuringInitialise() async { - // TODO: PROVIDER_FATAL event does not exist for now, we will test that the provider is in ERROR - // issue open for the fatal state: https://github.com/open-feature/swift-sdk/issues/40 - let mockResponse = "{}" let mockService = MockNetworkingService(mockData: mockResponse.data(using: .utf8), mockStatus: 403) @@ -75,15 +60,7 @@ class ProviderTests: XCTestCase { let api = OpenFeatureAPI() await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) - let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in - // TODO: Move to FATAL when the event will be handled by the SDK - if(event != ProviderEvent.error){ - XCTFail("If OFREP API returns a 403 we should receive a FATAL event, received: \(event)") - } - expectation.fulfill() - } - await fulfillment(of: [expectation], timeout: 3.0) + XCTAssertEqual(api.getProviderStatus(), ProviderStatus.fatal) } func testShouldBeInErrorStatusIf429ErrorDuringInitialise() async { @@ -95,17 +72,18 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) + let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in - if(event != ProviderEvent.error){ + let cancellable = api.observe().sink{ event in + if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OFREP.OfrepError error 3.)")){ XCTFail("If OFREP API returns a 429 we should receive an ERROR event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3.0) + cancellable.cancel() } func testShouldBeInErrorStatusIfErrorTargetingKeyIsMissing() async { @@ -123,17 +101,18 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) + let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in - if(event != ProviderEvent.error){ + let cancellable = api.observe().sink{ event in + if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OpenFeature.OpenFeatureError error 5.)")){ XCTFail("If OFREP API returns a 400 for TARGETING_KEY_MISSING we should receive an ERROR event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) + cancellable.cancel() } func testShouldBeInErrorStatusIfErrorInvalidContext() async { @@ -150,20 +129,19 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - - let expectation = XCTestExpectation(description: "waiting 1st event") - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) - _ = api.observe().sink{ event in - if(event != ProviderEvent.error){ + + let cancellable = api.observe().sink{ event in + if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OpenFeature.OpenFeatureError error 4.)")){ XCTFail("If OFREP API returns a 400 for INVALID_CONTEXT we should receive an ERROR event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) + cancellable.cancel() } func testShouldBeInErrorStatusIfErrorParseError() async { @@ -182,16 +160,18 @@ class ProviderTests: XCTestCase { let provider = OfrepProvider(options: options) let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) + let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in - if(event != ProviderEvent.error){ + let cancellable = api.observe().sink{ event in + if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OpenFeature.OpenFeatureError error 2.)")){ XCTFail("If OFREP API returns a 400 for PARSE_ERROR we should receive an ERROR event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) + cancellable.cancel() } func testShouldReturnAFlagNotFoundErrorIfTheFlagDoesNotExist() async { @@ -204,15 +184,16 @@ class ProviderTests: XCTestCase { let provider = OfrepProvider(options: options) let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) + cancellable.cancel() let client = api.getClient() let details = client.getBooleanDetails(key: "non-existant-flag", defaultValue: false) @@ -220,25 +201,25 @@ class ProviderTests: XCTestCase { } func testShouldReturnEvaluationDetailsIfTheFlagExists() async { - let mockService = MockNetworkingService( mockStatus: 400) + let mockService = MockNetworkingService( mockStatus: 200) let options = OfrepProviderOptions( endpoint: "http://localhost:1031/", networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() + let client = api.getClient() let details = client.getBooleanDetails(key: "my-flag", defaultValue: false) XCTAssertEqual(details.errorCode, nil) @@ -272,25 +253,25 @@ class ProviderTests: XCTestCase { ] } """ - let mockService = MockNetworkingService(mockData: mockResponse.data(using: .utf8), mockStatus: 400) + let mockService = MockNetworkingService(mockData: mockResponse.data(using: .utf8), mockStatus: 200) let options = OfrepProviderOptions( endpoint: "http://localhost:1031/", networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() + let client = api.getClient() let details = client.getBooleanDetails(key: "my-other-flag", defaultValue: false) XCTAssertEqual(details.errorCode, ErrorCode.parseError) @@ -313,18 +294,19 @@ class ProviderTests: XCTestCase { let provider = OfrepProvider(options: options) let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expect = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in switch event{ - case ProviderEvent.ready: + case .ready: expect.fulfill() default: XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") expect.fulfill() } } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expect], timeout: 3) + cancellable.cancel() let client = api.getClient() let details = client.getBooleanDetails(key: "my-flag", defaultValue: false) @@ -341,25 +323,22 @@ class ProviderTests: XCTestCase { let expectation1 = expectation(description: "event 1") let expectation2 = expectation(description: "event 2") - let expectation3 = expectation(description: "event 3") var receivedEvents = [ProviderEvent]() api.observe().sink{ event in - receivedEvents.append(event) + receivedEvents.append(event!) switch receivedEvents.count{ case 1: expectation1.fulfill() case 2: expectation2.fulfill() - case 3: - expectation3.fulfill() default: break } }.store(in: &cancellables) api.setEvaluationContext(evaluationContext: newContext) - await fulfillment(of:[expectation1, expectation2, expectation3], timeout: 5) - let expectedEvents: [ProviderEvent] = [.ready, .stale, .ready] + await fulfillment(of:[expectation1, expectation2], timeout: 5) + let expectedEvents: [ProviderEvent] = [.reconciling, .contextChanged] XCTAssertEqual(receivedEvents, expectedEvents, "The events were not received in the expected order.") let details2 = client.getBooleanDetails(key: "my-flag", defaultValue: false) @@ -385,13 +364,12 @@ class ProviderTests: XCTestCase { let ctx = MutableContext() ctx.setTargetingKey(targetingKey: "429") - await api.setProviderAndWait(provider: provider, initialContext: ctx) - + let expectation1 = expectation(description: "Ready event") let expectation2 = expectation(description: "Stale event") var receivedEvents = [ProviderEvent]() api.observe().sink{ event in - receivedEvents.append(event) + receivedEvents.append(event!) switch receivedEvents.count{ case 1: expectation1.fulfill() @@ -401,6 +379,7 @@ class ProviderTests: XCTestCase { break } }.store(in: &cancellables) + await api.setProviderAndWait(provider: provider, initialContext: ctx) await fulfillment(of:[expectation1, expectation2], timeout: 5) let expectedEvents: [ProviderEvent] = [.ready, .stale] XCTAssertEqual(receivedEvents, expectedEvents, "The events were not received in the expected order.") @@ -448,22 +427,19 @@ class ProviderTests: XCTestCase { XCTAssertEqual(details.reason, "STATIC") XCTAssertEqual(details.variant, "variantA") - let expectation1 = expectation(description: "Ready event") - let expectation2 = expectation(description: "ConfigurationChanged event") + let expectation1 = expectation(description: "ConfigurationChanged event") var receivedEvents = [ProviderEvent]() api.observe().sink{ event in - receivedEvents.append(event) + receivedEvents.append(event!) switch receivedEvents.count{ case 1: expectation1.fulfill() - case 2: - expectation2.fulfill() default: break } }.store(in: &cancellables) - await fulfillment(of:[expectation1, expectation2], timeout: 7) - let expectedEvents: [ProviderEvent] = [.ready, .configurationChanged] + await fulfillment(of:[expectation1], timeout: 5) + let expectedEvents: [ProviderEvent] = [.configurationChanged] XCTAssertEqual(receivedEvents, expectedEvents, "The events were not received in the expected order.") let details2 = client.getBooleanDetails(key: "my-flag", defaultValue: false) @@ -482,18 +458,18 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() + let client = api.getClient() let details = client.getBooleanDetails(key: "bool-flag", defaultValue: false) XCTAssertEqual(details.errorCode, nil) @@ -515,16 +491,15 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) let client = api.getClient() @@ -549,18 +524,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getDoubleDetails(key: "double-flag", defaultValue: 1.1) XCTAssertEqual(details.errorCode, nil) @@ -581,18 +555,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getStringDetails(key: "string-flag", defaultValue: "1") XCTAssertEqual(details.errorCode, nil) @@ -613,18 +586,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getObjectDetails(key: "array-flag", defaultValue: Value.list([Value.string("1")])) XCTAssertEqual(details.errorCode, nil) @@ -645,18 +617,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getObjectDetails(key: "object-flag", defaultValue: Value.list([Value.string("1")])) XCTAssertEqual(details.errorCode, nil) @@ -677,18 +648,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getBooleanDetails(key: "object-flag", defaultValue: false) XCTAssertEqual(details.errorCode, ErrorCode.typeMismatch) @@ -703,18 +673,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getStringDetails(key: "object-flag", defaultValue: "default") XCTAssertEqual(details.errorCode, ErrorCode.typeMismatch) @@ -729,18 +698,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getIntegerDetails(key: "object-flag", defaultValue: 1) XCTAssertEqual(details.errorCode, ErrorCode.typeMismatch) @@ -755,18 +723,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getDoubleDetails(key: "object-flag", defaultValue: 1.1) XCTAssertEqual(details.errorCode, ErrorCode.typeMismatch) @@ -781,18 +748,17 @@ class ProviderTests: XCTestCase { networkService: mockService ) let provider = OfrepProvider(options: options) - let api = OpenFeatureAPI() - await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) let expectation = XCTestExpectation(description: "waiting 1st event") - _ = api.observe().sink{ event in + let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") } expectation.fulfill() } + await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) - + cancellable.cancel() let client = api.getClient() let details = client.getObjectDetails(key: "bool-flag", defaultValue: Value.list([Value.string("1")])) XCTAssertEqual(details.errorCode, ErrorCode.typeMismatch) From aef919ded4a3d98bf6ff7271bdc7f7186bea7783 Mon Sep 17 00:00:00 2001 From: Thomas Poignant Date: Mon, 23 Dec 2024 21:02:11 +0100 Subject: [PATCH 2/2] fix(lint): Fix linting issues Signed-off-by: Thomas Poignant --- .../hook/data_collector_bool_hook.swift | 3 +- .../hook/data_collector_double_hook.swift | 3 +- .../hook/data_collector_integer_hook.swift | 3 +- .../hook/data_collector_object_hook.swift | 4 +- .../hook/data_collector_string_hook.swift | 3 +- Tests/GOFeatureFlagTests/goff_api_tests.swift | 4 +- Tests/GOFeatureFlagTests/provider_tests.swift | 8 ++-- Tests/OFREPTests/provider_tests.swift | 39 ++++++++++--------- 8 files changed, 36 insertions(+), 31 deletions(-) diff --git a/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift index f0a447c..fa79d22 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_bool_hook.swift @@ -66,7 +66,8 @@ class BooleanHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ + func finally( + ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]) { return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift index aa17457..09d76ee 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_double_hook.swift @@ -67,7 +67,8 @@ class DoubleHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ + func finally( + ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]) { return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift index aea01b0..11da32b 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_integer_hook.swift @@ -63,7 +63,8 @@ class IntegerHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ + func finally( + ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]) { return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift index 68264ae..cd0364a 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_object_hook.swift @@ -65,8 +65,8 @@ class ObjectHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - - func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ + func finally( + ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]) { return } } diff --git a/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift b/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift index ef6513e..cbab401 100644 --- a/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift +++ b/Sources/GOFeatureFlag/hook/data_collector_string_hook.swift @@ -66,7 +66,8 @@ class StringHook: Hook { self.dataCollectorMngr.appendFeatureEvent(event: event) } - func finally(ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]){ + func finally( + ctx: HookContext, details: FlagEvaluationDetails, hints: [String: Any]) { return } } diff --git a/Tests/GOFeatureFlagTests/goff_api_tests.swift b/Tests/GOFeatureFlagTests/goff_api_tests.swift index a74f23d..0d7f319 100644 --- a/Tests/GOFeatureFlagTests/goff_api_tests.swift +++ b/Tests/GOFeatureFlagTests/goff_api_tests.swift @@ -30,7 +30,7 @@ class GoffApiTests: XCTestCase { FeatureEvent(kind: "feature", userKey: "981f2662-1fb4-4732-ac6d-8399d9205aa9", creationDate: Int64(Date().timeIntervalSince1970), key: "flag-1", variation: "enabled", value: JSONValue.bool(true), default: false, version: nil, source: "PROVIDER_CACHE") ] do { - let (response, _) = try await goffAPI.postDataCollector(events: events) + _ = try await goffAPI.postDataCollector(events: events) XCTFail("Expected to throw GoFeatureFlagError.apiUnauthorizedError, but no error was thrown.") } catch let error as GoFeatureFlagError { switch error { @@ -52,7 +52,7 @@ class GoffApiTests: XCTestCase { FeatureEvent(kind: "feature", userKey: "981f2662-1fb4-4732-ac6d-8399d9205aa9", creationDate: Int64(Date().timeIntervalSince1970), key: "flag-1", variation: "enabled", value: JSONValue.bool(true), default: false, version: nil, source: "PROVIDER_CACHE") ] do { - let (response, _) = try await goffAPI.postDataCollector(events: events) + _ = try await goffAPI.postDataCollector(events: events) XCTFail("Expected to throw GoFeatureFlagError.forbiddenError, but no error was thrown.") } catch let error as GoFeatureFlagError { switch error { diff --git a/Tests/GOFeatureFlagTests/provider_tests.swift b/Tests/GOFeatureFlagTests/provider_tests.swift index 945e3be..e6fe27d 100644 --- a/Tests/GOFeatureFlagTests/provider_tests.swift +++ b/Tests/GOFeatureFlagTests/provider_tests.swift @@ -60,8 +60,8 @@ class GoFeatureFlagProviderTests: XCTestCase { _ = client.getIntegerDetails(key: "int-flag", defaultValue: 1) let expectation = self.expectation(description: "Waiting for delay") - DispatchQueue.global().asyncAfter(deadline: .now() + 3.0) { expectation.fulfill() } - await fulfillment(of: [expectation], timeout: 4.0) + DispatchQueue.global().asyncAfter(deadline: .now() + 4.0) { expectation.fulfill() } + await fulfillment(of: [expectation], timeout: 5.0) XCTAssertEqual(1, mockNetworkService.dataCollectorCallCounter) XCTAssertEqual(3, mockNetworkService.dataCollectorEventCounter) @@ -71,8 +71,8 @@ class GoFeatureFlagProviderTests: XCTestCase { _ = client.getObjectDetails(key: "object-flag", defaultValue: Value.null) let expectation2 = self.expectation(description: "Waiting for delay") - DispatchQueue.global().asyncAfter(deadline: .now() + 3.0) { expectation2.fulfill() } - await fulfillment(of: [expectation2], timeout: 4.0) + DispatchQueue.global().asyncAfter(deadline: .now() + 4.0) { expectation2.fulfill() } + await fulfillment(of: [expectation2], timeout: 5.0) XCTAssertEqual(2, mockNetworkService.dataCollectorCallCounter) XCTAssertEqual(6, mockNetworkService.dataCollectorEventCounter) diff --git a/Tests/OFREPTests/provider_tests.swift b/Tests/OFREPTests/provider_tests.swift index f26e03d..135f7e2 100644 --- a/Tests/OFREPTests/provider_tests.swift +++ b/Tests/OFREPTests/provider_tests.swift @@ -77,7 +77,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OFREP.OfrepError error 3.)")){ - XCTFail("If OFREP API returns a 429 we should receive an ERROR event, received: \(event)") + XCTFail("If OFREP API returns a 429 we should receive an ERROR event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -106,7 +106,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OpenFeature.OpenFeatureError error 5.)")){ - XCTFail("If OFREP API returns a 400 for TARGETING_KEY_MISSING we should receive an ERROR event, received: \(event)") + XCTFail("If OFREP API returns a 400 for TARGETING_KEY_MISSING we should receive an ERROR event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -134,7 +134,7 @@ class ProviderTests: XCTestCase { let cancellable = api.observe().sink{ event in if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OpenFeature.OpenFeatureError error 4.)")){ - XCTFail("If OFREP API returns a 400 for INVALID_CONTEXT we should receive an ERROR event, received: \(event)") + XCTFail("If OFREP API returns a 400 for INVALID_CONTEXT we should receive an ERROR event, received: \(String(describing: event))") } expectation.fulfill() } @@ -164,7 +164,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.error(errorCode: nil, message: "The operation couldn’t be completed. (OpenFeature.OpenFeatureError error 2.)")){ - XCTFail("If OFREP API returns a 400 for PARSE_ERROR we should receive an ERROR event, received: \(event)") + XCTFail("If OFREP API returns a 400 for PARSE_ERROR we should receive an ERROR event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -187,7 +187,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -212,7 +212,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -264,7 +264,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -300,7 +300,7 @@ class ProviderTests: XCTestCase { case .ready: expect.fulfill() default: - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") expect.fulfill() } } @@ -462,7 +462,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -495,12 +495,13 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } await api.setProviderAndWait(provider: provider, initialContext: defaultEvaluationContext) await fulfillment(of: [expectation], timeout: 3) + cancellable.cancel() let client = api.getClient() let details = client.getIntegerDetails(key: "int-flag", defaultValue: 1) @@ -528,7 +529,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -559,7 +560,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -590,7 +591,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -621,7 +622,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -652,7 +653,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -677,7 +678,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -702,7 +703,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -727,7 +728,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() } @@ -752,7 +753,7 @@ class ProviderTests: XCTestCase { let expectation = XCTestExpectation(description: "waiting 1st event") let cancellable = api.observe().sink{ event in if(event != ProviderEvent.ready){ - XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(event)") + XCTFail("If OFREP API returns a 200 we should receive a ready event, received: \(String(describing: event)))") } expectation.fulfill() }