Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Split/Api/CertificatePinningConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ public class CertificatePinningError: NSObject, LocalizedError, @unchecked Senda
Sets the status handler for certificate pinning.

This method allows you to specify a closure that will be called when a certificate pinning verification occurs.
- Parameter handler: A closure that takes a `CertificatePinningStatusHandler` as its parameter. This closure will be called when a certificate pinning verification happens whether it fails or not.
- Parameter handler: A closure that takes a `CertificatePinningStatusHandler` as its parameter.
This closure will be called when a certificate pinning verification happens whether it fails or not.
- Note: The `handler` closure is marked as `@escaping` because it is stored for later use, rather than being called immediately within the method.
- Warning: This handler is called on a background thread. If you need to perform UI updates, ensure you dispatch them to the main thread.
- Example:
Expand Down
4 changes: 2 additions & 2 deletions Split/Api/DefaultSplitClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public final class DefaultSplitClient: NSObject, SplitClient, TelemetrySplitClie
private var isClientDestroyed = false
private let eventsTracker: EventsTracker
private weak var clientManager: SplitClientManager?
@objc public var listener: SplitClientEventListener?
@objc public var listener: SplitEventListener?

var initStopwatch: Stopwatch?

Expand Down Expand Up @@ -90,7 +90,7 @@ extension DefaultSplitClient {
}

// MARK: Events Listeners with Medatadata
@objc public func addEventsListener(listener: SplitClientEventListener) {
@objc public func addEventListener(listener: SplitEventListener) {
if let l = listener.onSdkReady {
registerEvent(.sdkReady, action: l)
}
Expand Down
4 changes: 2 additions & 2 deletions Split/Api/FailHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class FailedClient: SplitClient {
func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) {}

// MARK: Events Listeners with Medatadata
var listener: (any SplitClientEventListener)?
@objc public func addEventsListener(listener: SplitClientEventListener) {}
var listener: (any SplitEventListener)?
@objc public func addEventListener(listener: SplitEventListener) {}

// MARK: Track
func track(trafficType: String, eventType: String) -> Bool {
Expand Down
4 changes: 2 additions & 2 deletions Split/Api/LocalhostSplitClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public final class LocalhostSplitClient: NSObject, SplitClient {
private var evaluator: Evaluator
private let key: Key
weak var clientManager: SplitClientManager?
@objc public var listener: SplitClientEventListener?
@objc public var listener: SplitEventListener?

init(key: Key, splitsStorage: SplitsStorage, clientManager: SplitClientManager?, eventsManager: SplitEventsManager? = nil, evaluator: Evaluator) {
self.eventsManager = eventsManager
Expand Down Expand Up @@ -144,7 +144,7 @@ public final class LocalhostSplitClient: NSObject, SplitClient {
}

// MARK: Events Listeners with Medatadata
@objc public func addEventsListener(listener: SplitClientEventListener) {
@objc public func addEventListener(listener: SplitEventListener) {
if let l = listener.onSdkReady {
registerEvent(.sdkReady, action: l)
}
Expand Down
8 changes: 4 additions & 4 deletions Split/Api/SplitClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

public typealias SplitAction = () -> Void

@objc public protocol SplitClientEventListener: AnyObject, Sendable {
@objc public protocol SplitEventListener: AnyObject, Sendable {
@objc(onSdkReady:)
optional func onSdkReady(_ metadata: SdkReadyMetadata)
@objc(onSdkReadyFromCache:)
Expand Down Expand Up @@ -47,9 +47,9 @@ public typealias SplitAction = () -> Void
func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction)

// MARK: Events with Metadata
@objc var listener: SplitClientEventListener? { get set }
@objc(addEventsListener:)
func addEventsListener(listener: SplitClientEventListener)
@objc var listener: SplitEventListener? { get set }
@objc(addEventListener:)
func addEventListener(listener: SplitEventListener)

// MARK: Track feature
func track(trafficType: String, eventType: String) -> Bool
Expand Down
2 changes: 1 addition & 1 deletion Split/Events/SplitEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import Foundation
}
}

@objcMembers public final class SplitEventWithMetadata: NSObject, Sendable {
final class SplitEventWithMetadata: NSObject, Sendable {
let type: SplitEvent
let metadata: EventMetadata?

Expand Down
3 changes: 2 additions & 1 deletion Split/Network/HttpClient/HttpRequestManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ extension DefaultHttpRequestManager {
}

// Finally we trigger the complete-status handler (host, success/fail, reason)
notificationHelper?.post(notification: .pinnedCredentialStatus, info: CertificatePinningCompleteStatus(host: challenge.protectionSpace.host, status: finalStatus, reason: checkResult.description) as AnyObject)
notificationHelper?.post(notification: .pinnedCredentialStatus,
info: CertificatePinningCompleteStatus(host: challenge.protectionSpace.host, status: finalStatus, reason: checkResult.description) as AnyObject)
}
}
4 changes: 2 additions & 2 deletions SplitTests/Fake/InternalSplitClientStub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable {
var splitsStorage: SplitsStorage?
var mySegmentsStorage: MySegmentsStorage?
var myLargeSegmentsStorage: MySegmentsStorage?
var listener: SplitClientEventListener?
var listener: SplitEventListener?

init(splitsStorage: SplitsStorage?,
mySegmentsStorage: MySegmentsStorage?,
Expand Down Expand Up @@ -102,7 +102,7 @@ class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable {

func on(event: SplitEvent, execute action: @escaping SplitAction) {}

func addEventsListener(listener: SplitClientEventListener) {}
func addEventListener(listener: SplitEventListener) {}

func track(trafficType: String, eventType: String) -> Bool {
return true
Expand Down
4 changes: 2 additions & 2 deletions SplitTests/Fake/SplitClientStub.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Foundation

class SplitClientStub: SplitClient, @unchecked Sendable {

@objc public var listener: SplitClientEventListener?
@objc public var listener: SplitEventListener?

func getTreatment(_ split: String, attributes: [String : Any]?) -> String {
return SplitConstants.control
Expand Down Expand Up @@ -97,7 +97,7 @@ class SplitClientStub: SplitClient, @unchecked Sendable {
func on(event: SplitEvent, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) {
}

func addEventsListener(listener: SplitClientEventListener) {
func addEventListener(listener: SplitEventListener) {
}

func track(trafficType: String, eventType: String) -> Bool {
Expand Down
78 changes: 78 additions & 0 deletions SplitTests/Init/SplitClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,60 @@ class SplitClientTests: XCTestCase {
XCTAssertNotNil(task.takeQueue())
}
}

func testAddEventListenerRegistersAllMetadataEvents() {
let listener = SplitEventListenerAllEvents()
client.addEventListener(listener: listener)

let types = Set(eventsManager.registeredEvents.keys.map { $0.type })
XCTAssertEqual(types, Set([.sdkReady, .sdkReadyFromCache, .sdkUpdated]))

for event in types {
guard let task = eventsManager.registeredEvents.first(where: { $0.key.type == event })?.value else {
XCTFail("Expected task for \(event)")
continue
}

XCTAssertTrue(task.runInBackground)
XCTAssertNil(task.takeQueue())
}
}

func testAddEventListenerRegistersOnlyImplementedCallbacks() {
let listener = SplitEventListenerReadyOnly()
client.addEventListener(listener: listener)

let types = Set(eventsManager.registeredEvents.keys.map { $0.type })
XCTAssertEqual(types, Set([.sdkReady]))
}

func testAddEventListenerCallsMultipleListenersOnSdkReady() {
let config = SplitClientConfig()
config.logLevel = .verbose
let localEventsManager = DefaultSplitEventsManager(config: config)
localEventsManager.start()

let localClient = DefaultSplitClient(config: config, key: key,
treatmentManager: treatmentManager, apiFacade: apiFacade,
storageContainer: storageContainer,
eventsManager: localEventsManager,
eventsTracker: eventsTracker, clientManager: clientManager)

let exp1 = XCTestExpectation(description: "listener 1 called")
let exp2 = XCTestExpectation(description: "listener 2 called")

let listener1 = SplitEventListenerReadyClosure(onReady: { exp1.fulfill() })
let listener2 = SplitEventListenerReadyClosure(onReady: { exp2.fulfill() })

localClient.addEventListener(listener: listener1)
localClient.addEventListener(listener: listener2)

localEventsManager.notifyInternalEvent(.mySegmentsUpdated)
localEventsManager.notifyInternalEvent(.myLargeSegmentsUpdated)
localEventsManager.notifyInternalEvent(.splitsUpdated)

wait(for: [exp1, exp2], timeout: 2.0)
}

func testGetTreatmentWithEvaluationOptions() {
testEvaluationOptionsPassedCorrectly(
Expand Down Expand Up @@ -276,3 +330,27 @@ class SplitClientTests: XCTestCase {
verifyProperties(in: getEvaluationOptions(mockManager))
}
}

final class SplitEventListenerAllEvents: NSObject, SplitEventListener {
@objc func onSdkReady(_ metadata: SdkReadyMetadata) {}

@objc func onSdkReadyFromCache(_ metadata: SdkReadyFromCacheMetadata) {}

@objc func onSdkUpdate(_ metadata: SdkUpdateMetadata) {}
}

final class SplitEventListenerReadyOnly: NSObject, SplitEventListener {
@objc func onSdkReady(_ metadata: SdkReadyMetadata) {}
}

final class SplitEventListenerReadyClosure: NSObject, SplitEventListener, @unchecked Sendable {
private let onReady: @Sendable () -> Void

init(onReady: @escaping @Sendable () -> Void) {
self.onReady = onReady
}

@objc func onSdkReady(_ metadata: SdkReadyMetadata) {
onReady()
}
}
Loading