diff --git a/Examples/Sources/MasterDetailTableViewController.swift b/Examples/Sources/MasterDetailTableViewController.swift index b2be9a4d..6c6667bb 100644 --- a/Examples/Sources/MasterDetailTableViewController.swift +++ b/Examples/Sources/MasterDetailTableViewController.swift @@ -269,12 +269,12 @@ class MasterDetailTableViewController: UITableViewController { switch connectionChange { case .connected: print("Status connected!") - case .connectionError(let error): - print("Error while attempting to initialize connection: \(error)") + case .connectionError: + print("Error while attempting to initialize connection") case .disconnected: print("Status disconnected") - case .disconnectedUnexpectedly(let error): - print("Disconnected unexpectedly: \(error)") + case .disconnectedUnexpectedly: + print("Disconnected unexpectedly") } case let .presenceChanged(presenceChange): print("The channel \(presenceChange.channel) has an updated occupancy of \(presenceChange.occupancy)") diff --git a/PubNub.xcodeproj/project.pbxproj b/PubNub.xcodeproj/project.pbxproj index 494cb711..d93b72a2 100644 --- a/PubNub.xcodeproj/project.pbxproj +++ b/PubNub.xcodeproj/project.pbxproj @@ -3580,6 +3580,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.13; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -3613,6 +3614,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.13; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4307,7 +4309,7 @@ ); HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = PubNub.xcodeproj/PubNubContractTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@loader_path/../Frameworks", @@ -4349,7 +4351,7 @@ ); HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = PubNub.xcodeproj/PubNubContractTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@loader_path/../Frameworks", @@ -4391,7 +4393,7 @@ ); HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = PubNub.xcodeproj/PubNubContractTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@loader_path/../Frameworks", @@ -4434,7 +4436,7 @@ ); HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = PubNub.xcodeproj/PubNubContractTests_Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@loader_path/../Frameworks", @@ -4670,6 +4672,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.13; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; @@ -4704,6 +4707,7 @@ "@loader_path/../Frameworks", "@loader_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.13; OTHER_CFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; diff --git a/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift b/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift index 7f3a4801..d40ad5e8 100644 --- a/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift +++ b/Sources/PubNub/EventEngine/Presence/Helpers/PresenceHeartbeatRequest.swift @@ -53,7 +53,7 @@ class PresenceHeartbeatRequest { func execute(completionBlock: @escaping (Result) -> Void) { request = session.request(with: PresenceRouter( .heartbeat(channels: channels, groups: groups, presenceTimeout: configuration.durationUntilTimeout), - configuration: configuration), requestOperator: nil + configuration: configuration, eventEngineEnabled: true), requestOperator: nil ) request?.validate().response(on: sessionResponseQueue, decoder: GenericServiceResponseDecoder()) { result in switch result { diff --git a/Sources/PubNub/EventEngine/Presence/Helpers/PresenceLeaveRequest.swift b/Sources/PubNub/EventEngine/Presence/Helpers/PresenceLeaveRequest.swift index 90fb2830..81f8ca5c 100644 --- a/Sources/PubNub/EventEngine/Presence/Helpers/PresenceLeaveRequest.swift +++ b/Sources/PubNub/EventEngine/Presence/Helpers/PresenceLeaveRequest.swift @@ -53,7 +53,7 @@ class PresenceLeaveRequest { func execute(completionBlock: @escaping (Result) -> Void) { request = session.request(with: PresenceRouter( .leave(channels: channels, groups: groups), - configuration: configuration), requestOperator: nil + configuration: configuration, eventEngineEnabled: true), requestOperator: nil ) request?.validate().response(on: sessionResponseQueue, decoder: GenericServiceResponseDecoder()) { result in switch result { diff --git a/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift b/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift index ecf2874e..aabb024f 100644 --- a/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift +++ b/Sources/PubNub/EventEngine/Subscribe/Helpers/SubscribeRequest.swift @@ -86,7 +86,8 @@ class SubscribeRequest { timetoken: timetoken, region: region?.description ?? nil, heartbeat: configuration.durationUntilTimeout, - filter: configuration.filterExpression + filter: configuration.filterExpression, + eventEngineEnabled: true ), configuration: configuration ), requestOperator: nil ) diff --git a/Sources/PubNub/Events/Subscription/SubscriptionStream.swift b/Sources/PubNub/Events/Subscription/SubscriptionStream.swift index fb535179..9bf2a987 100644 --- a/Sources/PubNub/Events/Subscription/SubscriptionStream.swift +++ b/Sources/PubNub/Events/Subscription/SubscriptionStream.swift @@ -51,38 +51,8 @@ public enum SubscriptionChangeEvent { } } -/// The header of a PubNub subscribe response for zero or more events -public struct SubscribeResponseHeader { - /// The channels that are actively subscribed - public let channels: [PubNubChannel] - /// The groups that are actively subscribed - public let groups: [PubNubChannel] - /// The most recent successful Timetoken used in subscriptionstatus - public let previous: SubscribeCursor? - /// Timetoken that will be used on the next subscription cycle - public let next: SubscribeCursor? - - public init( - channels: [PubNubChannel], - groups: [PubNubChannel], - previous: SubscribeCursor?, - next: SubscribeCursor? - ) { - self.channels = channels - self.groups = groups - self.previous = previous - self.next = next - } -} - /// Local events emitted from the Subscribe method public enum PubNubSubscribeEvent { - /// A change in the Channel or Group state occured - @available(*, unavailable) - case subscriptionChanged(SubscriptionChangeEvent) - /// A subscribe response was received - @available(*, unavailable) - case responseReceived(SubscribeResponseHeader) /// The connection status of the PubNub subscription was changed case connectionChanged(ConnectionStatus) /// An error was received @@ -100,9 +70,6 @@ public enum PubNubCoreEvent { case signalReceived(PubNubMessage) /// A change in the subscription connection has occurred case connectionStatusChanged(ConnectionStatus) - /// A change in the subscribed channels or groups has occurred - @available(*, unavailable) - case subscriptionChanged(SubscriptionChangeEvent) /// A presence change has been received case presenceChanged(PubNubPresenceChange) /// A User object has been updated @@ -175,9 +142,6 @@ public final class CoreListener: BaseSubscriptionListener { public var didReceiveBatchSubscription: (([SubscriptionEvent]) -> Void)? /// Receiver for all subscription events public var didReceiveSubscription: ((SubscriptionEvent) -> Void)? - /// Receiver for changes in the subscribe/unsubscribe status of channels/groups - @available(*, unavailable) - public var didReceiveSubscriptionChange: ((SubscriptionChangeEvent) -> Void)? /// Receiver for status (Connection & Error) events public var didReceiveStatus: ((StatusEvent) -> Void)? /// Receiver for presence events diff --git a/Sources/PubNub/Networking/HTTPRouter.swift b/Sources/PubNub/Networking/HTTPRouter.swift index 57464ab3..3bfd2bff 100644 --- a/Sources/PubNub/Networking/HTTPRouter.swift +++ b/Sources/PubNub/Networking/HTTPRouter.swift @@ -134,6 +134,7 @@ enum QueryKey: String { case filter case sort case descending = "desc" + case eventEngine = "ee" } /// The PubNub Key requirement for a given Endpoint diff --git a/Sources/PubNub/Networking/Routers/PresenceRouter.swift b/Sources/PubNub/Networking/Routers/PresenceRouter.swift index 24ccebf7..dee39ce6 100644 --- a/Sources/PubNub/Networking/Routers/PresenceRouter.swift +++ b/Sources/PubNub/Networking/Routers/PresenceRouter.swift @@ -95,13 +95,15 @@ struct PresenceRouter: HTTPRouter { } // Init - init(_ endpoint: Endpoint, configuration: RouterConfiguration) { + init(_ endpoint: Endpoint, configuration: RouterConfiguration, eventEngineEnabled: Bool = false) { self.endpoint = endpoint self.configuration = configuration + self.eventEngineEnabled = eventEngineEnabled } var endpoint: Endpoint var configuration: RouterConfiguration + var eventEngineEnabled: Bool // Protocol Properties var service: PubNubService { @@ -143,8 +145,14 @@ struct PresenceRouter: HTTPRouter { case let .heartbeat(_, groups, presenceTimeout): query.appendIfNotEmpty(key: .channelGroup, value: groups) query.appendIfPresent(key: .heartbeat, value: presenceTimeout?.description) + if eventEngineEnabled { + query.append(URLQueryItem(key: .eventEngine, value: nil)) + } case let .leave(_, groups): query.appendIfNotEmpty(key: .channelGroup, value: groups) + if eventEngineEnabled { + query.append(URLQueryItem(key: .eventEngine, value: nil)) + } case let .hereNow(_, groups, includeUUIDs, includeState): query.appendIfNotEmpty(key: .channelGroup, value: groups) query.append(URLQueryItem(key: .disableUUIDs, value: (!includeUUIDs).stringNumber)) diff --git a/Sources/PubNub/Networking/Routers/SubscribeRouter.swift b/Sources/PubNub/Networking/Routers/SubscribeRouter.swift index 51784c20..b07146ac 100644 --- a/Sources/PubNub/Networking/Routers/SubscribeRouter.swift +++ b/Sources/PubNub/Networking/Routers/SubscribeRouter.swift @@ -32,9 +32,11 @@ import Foundation struct SubscribeRouter: HTTPRouter { // Nested Endpoint enum Endpoint: CaseAccessible, CustomStringConvertible { - case subscribe(channels: [String], groups: [String], - timetoken: Timetoken?, region: String?, - heartbeat: UInt?, filter: String?) + case subscribe( + channels: [String], groups: [String], + timetoken: Timetoken?, region: String?, + heartbeat: UInt?, filter: String?, eventEngineEnabled: Bool + ) var description: String { switch self { @@ -66,7 +68,7 @@ struct SubscribeRouter: HTTPRouter { let path: String switch endpoint { - case let .subscribe(channels, _, _, _, _, _): + case let .subscribe(channels, _, _, _, _, _, _): path = "/v2/subscribe/\(subscribeKey)/\(channels.commaOrCSVString.urlEncodeSlash)/0" } @@ -77,12 +79,16 @@ struct SubscribeRouter: HTTPRouter { var query = defaultQueryItems switch endpoint { - case let .subscribe(_, groups, timetoken, region, heartbeat, filter): + case let .subscribe(_, groups, timetoken, region, heartbeat, filter, eventEngineEnabled): query.appendIfNotEmpty(key: .channelGroup, value: groups) query.appendIfPresent(key: .timetokenShort, value: timetoken?.description) query.appendIfPresent(key: .regionShort, value: region?.description) query.appendIfPresent(key: .filterExpr, value: filter) query.appendIfPresent(key: .heartbeat, value: heartbeat?.description) + + if eventEngineEnabled { + query.append(URLQueryItem(key: .eventEngine, value: nil)) + } } return .success(query) @@ -91,7 +97,7 @@ struct SubscribeRouter: HTTPRouter { // Validated var validationErrorDetail: String? { switch endpoint { - case let .subscribe(channels, groups, _, _, _, _): + case let .subscribe(channels, groups, _, _, _, _, _): return isInvalidForReason( (channels.isEmpty && groups.isEmpty, ErrorDescription.missingChannelsAnyGroups)) } diff --git a/Sources/PubNub/PubNubConfiguration.swift b/Sources/PubNub/PubNubConfiguration.swift index 6b237712..fa190202 100644 --- a/Sources/PubNub/PubNubConfiguration.swift +++ b/Sources/PubNub/PubNubConfiguration.swift @@ -104,7 +104,8 @@ public struct PubNubConfiguration: Hashable { heartbeatInterval: UInt = 0, supressLeaveEvents: Bool = false, requestMessageCountThreshold: UInt = 100, - filterExpression: String? = nil + filterExpression: String? = nil, + enableEventEngine: Bool = false ) { guard userId.trimmingCharacters(in: .whitespacesAndNewlines).count > 0 else { preconditionFailure("UserId should not be empty.") @@ -127,6 +128,7 @@ public struct PubNubConfiguration: Hashable { self.supressLeaveEvents = supressLeaveEvents self.requestMessageCountThreshold = requestMessageCountThreshold self.filterExpression = filterExpression + self.enableEventEngine = enableEventEngine } // swiftlint:disable:next line_length @@ -220,7 +222,7 @@ public struct PubNubConfiguration: Hashable { public var useInstanceId: Bool /// Whether a request identifier should be included on outgoing requests public var useRequestId: Bool - /// A flag describing whether to enable new strategy for handling subscription loop + /// A flag describing whether to enable the new strategy for handling subscription loop public var enableEventEngine: Bool = false /// Reconnection policy which will be used if/when a request fails public var automaticRetry: AutomaticRetry? diff --git a/Sources/PubNub/Subscription/ConnectionStatus.swift b/Sources/PubNub/Subscription/ConnectionStatus.swift index 43d94fcc..a6a4f135 100644 --- a/Sources/PubNub/Subscription/ConnectionStatus.swift +++ b/Sources/PubNub/Subscription/ConnectionStatus.swift @@ -29,12 +29,6 @@ import Foundation /// Status of a connection to a remote system public enum ConnectionStatus: Equatable { - /// Attempting to connect to a remote system - @available(*, unavailable) - case connecting - /// Attempting to reconnect to a remote system - @available(*, unavailable) - case reconnecting /// Successfully connected to a remote system case connected /// Explicit disconnect from a remote system @@ -47,7 +41,7 @@ public enum ConnectionStatus: Equatable { /// If the connection is connected or attempting to connect public var isActive: Bool { switch self { - case .connecting, .connected, .reconnecting: + case .connected: return true default: return false @@ -65,27 +59,15 @@ public enum ConnectionStatus: Equatable { func canTransition(to state: ConnectionStatus) -> Bool { switch (self, state) { - case (.connecting, .reconnecting): - return false - case (.connecting, _): + case (.connected, .disconnected): return true - case (.connected, .connecting): - return false - case (.connected, _): + case (.disconnected, .connected): return true - case (.reconnecting, .connecting): - return false - case (.reconnecting, _): + case (.connected, .disconnectedUnexpectedly): return true - case (.disconnected, .connecting): + case (.disconnected, .connectionError): return true - case (.disconnected, _): - return false - case (.disconnectedUnexpectedly, .connecting): - return true - case (.disconnectedUnexpectedly, _): - return false - case (.connectionError, _): + default: return false } } diff --git a/Sources/PubNub/Subscription/Strategy/EventEngineSubscriptionSessionStrategy.swift b/Sources/PubNub/Subscription/Strategy/EventEngineSubscriptionSessionStrategy.swift index 01dbb21e..fe71fc4c 100644 --- a/Sources/PubNub/Subscription/Strategy/EventEngineSubscriptionSessionStrategy.swift +++ b/Sources/PubNub/Subscription/Strategy/EventEngineSubscriptionSessionStrategy.swift @@ -108,9 +108,9 @@ class EventEngineSubscriptionSessionStrategy: SubscriptionSessionStrategy { func subscribe( to channels: [String], - and groups: [String] = [], - at cursor: SubscribeCursor? = nil, - withPresence: Bool = false + and groups: [String], + at cursor: SubscribeCursor?, + withPresence: Bool ) { let newInput = subscribeEngine.state.input + SubscribeInput( channels: channels.map { PubNubChannel(id: $0, withPresence: withPresence) }, @@ -134,7 +134,7 @@ class EventEngineSubscriptionSessionStrategy: SubscriptionSessionStrategy { )) } - func reconnect(at cursor: SubscribeCursor? = nil) { + func reconnect(at cursor: SubscribeCursor?) { let input = subscribeEngine.state.input let channels = input.allSubscribedChannels let groups = input.allSubscribedGroups @@ -153,7 +153,7 @@ class EventEngineSubscriptionSessionStrategy: SubscriptionSessionStrategy { // MARK: - Unsubscribe - func unsubscribe(from channels: [String], and groups: [String] = [], presenceOnly: Bool = false) { + func unsubscribe(from channels: [String], and groups: [String], presenceOnly: Bool) { let newInput = subscribeEngine.state.input - ( channels: channels.map { presenceOnly ? $0.presenceChannelName : $0 }, groups: groups.map { presenceOnly ? $0.presenceChannelName : $0 } diff --git a/Sources/PubNub/Subscription/Strategy/LegacySubscriptionSessionStrategy.swift b/Sources/PubNub/Subscription/Strategy/LegacySubscriptionSessionStrategy.swift index 00c2e352..91f1fd4a 100644 --- a/Sources/PubNub/Subscription/Strategy/LegacySubscriptionSessionStrategy.swift +++ b/Sources/PubNub/Subscription/Strategy/LegacySubscriptionSessionStrategy.swift @@ -99,22 +99,8 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { responseQueue = DispatchQueue(label: "com.pubnub.subscription.response", qos: .default) sessionStream = SessionListener(queue: responseQueue) - // Add listener to session mutableSession.sessionStream = sessionStream longPollingSession = mutableSession - - sessionStream.didRetryRequest = { [weak self] _ in - self?.connectionStatus = .reconnecting - } - - sessionStream.sessionDidReceiveChallenge = { [weak self] _, _ in - if self?.connectionStatus == .reconnecting { - // Delay time for server to process connection after TLS handshake - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.05) { - self?.connectionStatus = .connected - } - } - } } deinit { @@ -129,9 +115,9 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { func subscribe( to channels: [String], - and groups: [String] = [], - at cursor: SubscribeCursor? = nil, - withPresence: Bool = false + and groups: [String], + at cursor: SubscribeCursor?, + withPresence: Bool ) { if channels.isEmpty, groups.isEmpty { return @@ -158,10 +144,8 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { } } - func reconnect(at cursor: SubscribeCursor? = nil) { + func reconnect(at cursor: SubscribeCursor?) { if !connectionStatus.isActive { - connectionStatus = .connecting - // Start subscribe loop performSubscribeLoop(at: cursor) @@ -199,11 +183,13 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { } // Create Endpoing - let router = SubscribeRouter(.subscribe(channels: channels, groups: groups, timetoken: cursor?.timetoken, - region: cursor?.region.description, - heartbeat: configuration.durationUntilTimeout, - filter: filterExpression), - configuration: configuration) + let router = SubscribeRouter( + .subscribe( + channels: channels, groups: groups, timetoken: cursor?.timetoken, + region: cursor?.region.description, heartbeat: configuration.durationUntilTimeout, + filter: filterExpression, eventEngineEnabled: false + ), configuration: configuration + ) // Cancel previous request before starting new one stopSubscribeLoop(.longPollingRestart) @@ -250,15 +236,6 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { pubnubGroups[$0] = PubNubChannel(channel: $0) } } - - listener.emit(subscribe: - .responseReceived(SubscribeResponseHeader( - channels: pubnubChannels.values.map { $0 }, - groups: pubnubGroups.values.map { $0 }, - previous: cursor, - next: response.payload.cursor - )) - ) } // Attempt to detect missed messages due to queue overflow @@ -324,7 +301,7 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { // MARK: - Unsubscribe - func unsubscribe(from channels: [String], and groups: [String] = [], presenceOnly: Bool = false) { + func unsubscribe(from channels: [String], and groups: [String], presenceOnly: Bool) { // Update Channel List let subscribeChange = internalState.lockedWrite { state -> SubscriptionChangeEvent in if presenceOnly { @@ -341,9 +318,6 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { } if subscribeChange.didChange { - notify { - $0.emit(subscribe: .subscriptionChanged(subscribeChange)) - } // Call unsubscribe to cleanup remaining state items unsubscribeCleanup(subscribeChange: subscribeChange) } @@ -364,12 +338,8 @@ class LegacySubscriptionSessionStrategy: SubscriptionSessionStrategy { } if subscribeChange.didChange { - notify { - $0.emit(subscribe: .subscriptionChanged(subscribeChange)) - } // Cancel previous subscribe request. stopSubscribeLoop(.longPollingReset) - // Call unsubscribe to cleanup remaining state items unsubscribeCleanup(subscribeChange: subscribeChange) } diff --git a/Sources/PubNub/Subscription/Strategy/SubscriptionSessionStrategy.swift b/Sources/PubNub/Subscription/Strategy/SubscriptionSessionStrategy.swift index 367a2267..63b642eb 100644 --- a/Sources/PubNub/Subscription/Strategy/SubscriptionSessionStrategy.swift +++ b/Sources/PubNub/Subscription/Strategy/SubscriptionSessionStrategy.swift @@ -36,29 +36,9 @@ protocol SubscriptionSessionStrategy: EventStreamEmitter where ListenerType == B var connectionStatus: ConnectionStatus { get } var previousTokenResponse: SubscribeCursor? { get set } + func subscribe(to channels: [String], and groups: [String], at cursor: SubscribeCursor?, withPresence: Bool) + func unsubscribe(from channels: [String], and groups: [String], presenceOnly: Bool) + func reconnect(at cursor: SubscribeCursor?) func disconnect() func unsubscribeAll() } - -extension SubscriptionSessionStrategy { - func subscribe( - to channels: [String], - and groups: [String] = [], - at cursor: SubscribeCursor? = nil, - withPresence: Bool = false - ) { - - } - - public func unsubscribe( - from channels: [String], - and groups: [String] = [], - presenceOnly: Bool = false - ) { - - } - - public func reconnect(at cursor: SubscribeCursor? = nil) { - - } -} diff --git a/Sources/PubNub/Subscription/SubscribeSessionFactory.swift b/Sources/PubNub/Subscription/SubscribeSessionFactory.swift index 824a2dba..1a9a782b 100644 --- a/Sources/PubNub/Subscription/SubscribeSessionFactory.swift +++ b/Sources/PubNub/Subscription/SubscribeSessionFactory.swift @@ -39,7 +39,7 @@ import Foundation /// /// - Important: Having multiple `SubscriptionSession` instances will result in /// increase network usage and battery drain. -@available(*, deprecated, message: "Use methods on PubNub's instance instead") +@available(*, deprecated) public class SubscribeSessionFactory { private typealias SessionMap = [Int: WeakBox] @@ -87,13 +87,18 @@ public class SubscribeSessionFactory { preconditionFailure("Unexpected configuration that doesn't match PubNubConfiguration") } guard config.enableEventEngine else { - return SubscriptionSession( + let subscriptionSession = SubscriptionSession( strategy: LegacySubscriptionSessionStrategy( configuration: config, network: finalSubscribeSession, presenceSession: finalPresenceSession ) ) + dictionary.updateValue( + WeakBox(subscriptionSession), + forKey: configHash + ) + return subscriptionSession } let subscribeDispatcher = EffectDispatcher( factory: SubscribeEffectFactory(session: finalSubscribeSession) diff --git a/Sources/PubNub/Subscription/SubscriptionSession.swift b/Sources/PubNub/Subscription/SubscriptionSession.swift index fa9195fe..190152b3 100644 --- a/Sources/PubNub/Subscription/SubscriptionSession.swift +++ b/Sources/PubNub/Subscription/SubscriptionSession.swift @@ -27,7 +27,7 @@ import Foundation -@available(*, deprecated, message: "Use methods on PubNub's instance instead") +@available(*, deprecated) public class SubscriptionSession { /// An unique identifier for subscription session public var uuid: UUID { diff --git a/Tests/PubNubContractTest/PubNubContractCucumberTest.m b/Tests/PubNubContractTest/PubNubContractCucumberTest.m index 8e65e2ad..54ce7118 100644 --- a/Tests/PubNubContractTest/PubNubContractCucumberTest.m +++ b/Tests/PubNubContractTest/PubNubContractCucumberTest.m @@ -64,17 +64,42 @@ void CucumberishInit(void) { // TODO: REMOVE AFTER ALL TESTS FOR OBJECTS WILL BE MERGED. excludeTags = nil; - // TODO: REMOVE AFTER ALL TESTS FOR OBJECTS §WILL BE MERGED. + // TODO: REMOVE AFTER ALL TESTS FOR OBJECTS WILL BE MERGED. NSArray *includedTags = @[ - @"contract=presenceJoin", - @"contract=presenceJoinWithAnError", - @"contract=presenceJoinWithConstantFailures", - @"contract=presenceJoinAndLeave" + @"contract=getChannelMetadataOfChat", + @"contract=getChannelMetadataOfDMWithCustom", + @"contract=setChannelMetadataForChat", + @"contract=removeChannelMetadataOfChat", + @"contract=getAllChannelMetadata", + @"contract=getAllChannelMetadataWithCustom", + + @"contract=getUUIDMetadataOfAlice", + @"contract=getUUIDMetadataOfBobWithCustom", + @"contract=setUUIDMetadataForAlice", + @"contract=removeUUIDMetadataOfAlice", + @"contract=getAllUUIDMetadata", + @"contract=getAllUUIDMetadataWithCustom", + + @"contract=getMembersOfChatChannel", + @"contract=getMembersOfVipChatChannelWithCustomAndUuidWithCustom", + @"contract=setMembersForChatChannel", + @"contract=setMembersForChatChannelWithCustomAndUuidWithCustom", + @"contract=removeMembersForChatChannel", + @"contract=manageMembersForChatChannel", + + @"contract=getAliceMemberships", + @"contract=getAliceMemberships", + @"contract=getBobMembershipWithCustomAndChannelCustom", + @"contract=setAliceMembership", + @"contract=removeAliceMembership", + @"contract=manageAliceMemberships" ]; + + NSBundle * bundle = [NSBundle bundleForClass:[PubNubContractTestCase class]]; [Cucumberish executeFeaturesInDirectory:@"Features" fromBundle:bundle includeTags:includedTags - excludeTags:nil]; + excludeTags:excludeTags]; } diff --git a/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift b/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift index d9413f76..40501180 100644 --- a/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift +++ b/Tests/PubNubContractTest/Steps/EventEngine/PubNubPresenceEngineContractTestSteps.swift @@ -110,17 +110,20 @@ class PubNubPresenceEngineContractTestsSteps: PubNubEventEngineContractTestsStep } override func createPubNubClient() -> PubNub { + let factory = EventEngineFactory() let subscriptionSession = SubscriptionSession( - configuration: self.configuration, - subscribeEngine: EventEngineFactory().subscribeEngine( - with: self.configuration, - dispatcher: EmptyDispatcher(), - transition: SubscribeTransition() - ), - presenceEngine: EventEngineFactory().presenceEngine( - with: configuration, - dispatcher: self.dispatcherDecorator, - transition: self.transitionDecorator + strategy: EventEngineSubscriptionSessionStrategy( + configuration: self.configuration, + subscribeEngine: factory.subscribeEngine( + with: self.configuration, + dispatcher: EmptyDispatcher(), + transition: SubscribeTransition() + ), + presenceEngine: factory.presenceEngine( + with: configuration, + dispatcher: self.dispatcherDecorator, + transition: self.transitionDecorator + ) ) ) return PubNub( @@ -131,56 +134,5 @@ class PubNubPresenceEngineContractTestsSteps: PubNubEventEngineContractTestsStep override public func setup() { startCucumberHookEventsListening() - - Given("the demo keyset with Presence Event Engine enabled") { _, _ in - self.replacePubNubConfiguration(with: PubNubConfiguration( - publishKey: defaultPublishKey, - subscribeKey: defaultSubscribeKey, - userId: UUID().uuidString, - useSecureConnections: false, - origin: mockServerAddress, - durationUntilTimeout: 20, - supressLeaveEvents: true - )) - } - When("I join '(.*)', '(.*)', '(.*)' channels") { args, _ in - let firstChannel = args?[0] ?? "" - let secondChannel = args?[1] ?? "" - let thirdChannel = args?[2] ?? "" - - self.subscribeWithPresence(to: [firstChannel, secondChannel, thirdChannel]) - } - Match(["And"], "I leave '(.*)' and '(.*)' channels") { args, _ in - let firstChannel = args?[0] ?? "" - let secondChannel = args?[1] ?? "" - self.unsubscribe(from: [firstChannel, secondChannel]) - } - Then("I observe the following:") { args, value in - let recordedEvents = self.transitionDecorator.recordedEvents.map { $0.contractTestIdentifier } - let recordedInvocations = self.dispatcherDecorator.recordedInvocations.map { $0.contractTestIdentifier } - - XCTAssertTrue(recordedEvents.elementsEqual(self.extractExpectedResults(from: value).events)) - XCTAssertTrue(recordedInvocations.elementsEqual(self.extractExpectedResults(from: value).invocations)) - } - } - - private func subscribeWithPresence(to channels: [String] = [], and groups: [String] = []) { - let expectation = XCTestExpectation() - // Gives some time to proceed asynchronous requests - DispatchQueue.main.asyncAfter(deadline: .now() + 30) { expectation.fulfill() } - self.client.subscribe(to: channels, and: groups, withPresence: true) - self.wait(for: [expectation], timeout: 32.0) - } - - private func unsubscribe(from channels: [String] = [], and groups: [String] = []) { - let expectation = XCTestExpectation() - // Gives some time to proceed asynchronous requests - DispatchQueue.main.asyncAfter(deadline: .now() + 30) { expectation.fulfill() } - self.client.unsubscribe(from: channels, and: groups) - self.wait(for: [expectation], timeout: 32.0) - } - - private func withAsyncDelay() { - // TODO: } } diff --git a/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift b/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift index 135790b7..365420a4 100644 --- a/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift +++ b/Tests/PubNubContractTest/Steps/EventEngine/PubNubSubscribeEngineContractTestsSteps.swift @@ -139,16 +139,18 @@ class PubNubSubscribeEngineContractTestsSteps: PubNubEventEngineContractTestsSte override func createPubNubClient() -> PubNub { let factory = EventEngineFactory() let subscriptionSession = SubscriptionSession( - configuration: self.configuration, - subscribeEngine: factory.subscribeEngine( - with: self.configuration, - dispatcher: self.dispatcherDecorator, - transition: self.transitionDecorator - ), - presenceEngine: factory.presenceEngine( - with: self.configuration, - dispatcher: EmptyDispatcher(), - transition: PresenceTransition() + strategy: EventEngineSubscriptionSessionStrategy( + configuration: self.configuration, + subscribeEngine: factory.subscribeEngine( + with: self.configuration, + dispatcher: self.dispatcherDecorator, + transition: self.transitionDecorator + ), + presenceEngine: factory.presenceEngine( + with: self.configuration, + dispatcher: EmptyDispatcher(), + transition: PresenceTransition() + ) ) ) return PubNub( @@ -168,11 +170,19 @@ class PubNubSubscribeEngineContractTestsSteps: PubNubEventEngineContractTestsSte useSecureConnections: false, origin: mockServerAddress, automaticRetry: AutomaticRetry(retryLimit: 3, policy: .linear(delay: 0.5)), - supressLeaveEvents: true + supressLeaveEvents: true, + enableEventEngine: true )) } Given("the demo keyset with event engine enabled") { _, _ in - debugPrint("Preserves existing configuration, there's no need to replace") + self.replacePubNubConfiguration(with: PubNubConfiguration( + publishKey: defaultPublishKey, + subscribeKey: defaultSubscribeKey, + userId: UUID().uuidString, + useSecureConnections: false, + origin: mockServerAddress, + enableEventEngine: true + )) } When("I subscribe") { _, _ in self.subscribeSynchronously(self.client, to: ["test"]) diff --git a/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift b/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift index 5891a416..d3ff0d38 100644 --- a/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift +++ b/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift @@ -103,7 +103,7 @@ class DelayedHeartbeatEffectTests: XCTestCase { effect.performTask { returnedEvents in XCTAssertTrue(returnedEvents.elementsEqual([.heartbeatSuccess])) - XCTAssertEqual(Int(Date().timeIntervalSince(startDate)), Int(timeout) - 1) + XCTAssertEqual(Int(Date().timeIntervalSince(startDate)), Int(0.5 * Double(timeout)) - 1) expectation.fulfill() } wait(for: [expectation], timeout: 3.5) diff --git a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift index 20f2276b..60d042f2 100644 --- a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift +++ b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeTransitionTests.swift @@ -696,7 +696,7 @@ class SubscribeTransitionTests: XCTestCase { .cancel(.handshakeReconnect), .managed(.emitStatus(change: Subscribe.ConnectionStatusChange( oldStatus: .disconnected, - newStatus: .connectionError(PubNubError(.unknown)), + newStatus: .connectionError, error: SubscribeError(underlying: PubNubError(.unknown)) ))) ] @@ -727,7 +727,7 @@ class SubscribeTransitionTests: XCTestCase { .cancel(.receiveReconnect), .managed(.emitStatus(change: Subscribe.ConnectionStatusChange( oldStatus: .connected, - newStatus: .disconnectedUnexpectedly(PubNubError(.unknown)), + newStatus: .disconnectedUnexpectedly, error: SubscribeError(underlying: PubNubError(.unknown)) ))) ] diff --git a/Tests/PubNubTests/Integration/SubscriptionIntegrationTests.swift b/Tests/PubNubTests/Integration/SubscriptionIntegrationTests.swift index 96f859bd..bf3fdd33 100644 --- a/Tests/PubNubTests/Integration/SubscriptionIntegrationTests.swift +++ b/Tests/PubNubTests/Integration/SubscriptionIntegrationTests.swift @@ -88,26 +88,24 @@ class SubscriptionIntegrationTests: XCTestCase { listener.didReceiveSubscription = { [unowned self] event in switch event { case .messageReceived: -// print("messageReceived: \(message)") pubnub.unsubscribe(from: [self.testChannel]) publishExpect.fulfill() case let .connectionStatusChanged(status): -// print("connectionStatusChanged: \(status)") switch status { case .connected: pubnub.publish(channel: self.testChannel, message: "Test") { _ in } connectedCount += 1 connectedExpect.fulfill() - case .connectionError(let error): - XCTFail("An error was returned: \(error)") + case .connectionError: + XCTFail("An error was returned") case .disconnected: // Stop reconneced after N attempts if connectedCount < totalLoops { pubnub.subscribe(to: [self.testChannel]) } disconnectedExpect.fulfill() - case .disconnectedUnexpectedly(let error): - XCTFail("An error was returned: \(error)") + case .disconnectedUnexpectedly: + XCTFail("An error was returned") } case let .subscribeError(error): XCTFail("An error was returned: \(error)") diff --git a/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift b/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift index e983638b..9419e076 100644 --- a/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift +++ b/Tests/PubNubTests/Networking/Routers/SubscribeRouterTests.swift @@ -29,9 +29,13 @@ import XCTest final class SubscribeRouterTests: XCTestCase { - let config = PubNubConfiguration(publishKey: "FakeTestString", subscribeKey: "FakeTestString", userId: UUID().uuidString) + let config = PubNubConfiguration( + publishKey: "FakeTestString", + subscribeKey: "FakeTestString", + userId: UUID().uuidString, + enableEventEngine: false + ) let testChannel = "TestChannel" - let testAction = PubNubMessageActionBase( actionType: "reaction", actionValue: "winky_face", actionTimetoken: 15_725_459_793_173_220, messageTimetoken: 15_725_459_448_096_144, @@ -41,9 +45,10 @@ final class SubscribeRouterTests: XCTestCase { // MARK: - Endpoint Tests func testSubscribe_Router() { - let router = SubscribeRouter(.subscribe(channels: ["TestChannel"], groups: [], timetoken: 0, - region: nil, heartbeat: nil, filter: nil), - configuration: config) + let router = SubscribeRouter(.subscribe( + channels: ["TestChannel"], groups: [], timetoken: 0, + region: nil, heartbeat: nil, filter: nil, eventEngineEnabled: config.enableEventEngine + ), configuration: config) XCTAssertEqual(router.endpoint.description, "Subscribe") XCTAssertEqual(router.category, "Subscribe") @@ -51,11 +56,15 @@ final class SubscribeRouterTests: XCTestCase { } func testSubscribe_Router_ValidationError() { - let router = SubscribeRouter(.subscribe(channels: [], groups: [], timetoken: 0, - region: nil, heartbeat: nil, filter: nil), - configuration: config) - - XCTAssertNotEqual(router.validationError?.pubNubError, PubNubError(.invalidEndpointType, router: router)) + let router = SubscribeRouter(.subscribe( + channels: [], groups: [], timetoken: 0, + region: nil, heartbeat: nil, filter: nil, eventEngineEnabled: config.enableEventEngine + ), configuration: config) + + XCTAssertNotEqual( + router.validationError?.pubNubError, + PubNubError(.invalidEndpointType, router: router) + ) } } @@ -80,7 +89,6 @@ extension SubscribeRouterTests { XCTAssertEqual(message.payload.stringOptional, "Test Message") subscription.unsubscribeAll() - messageExpect.fulfill() } listener.didReceiveStatus = { status in @@ -89,7 +97,6 @@ extension SubscribeRouterTests { } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -106,9 +113,9 @@ extension SubscribeRouterTests { let presenceExpect = XCTestExpectation(description: "Presence Event") let statusExpect = XCTestExpectation(description: "Status Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_presence_success", - "cancelled"]).session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_presence_success","cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -123,7 +130,6 @@ extension SubscribeRouterTests { ]) subscription.unsubscribeAll() - presenceExpect.fulfill() } listener.didReceiveStatus = { status in @@ -132,7 +138,6 @@ extension SubscribeRouterTests { } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -149,9 +154,9 @@ extension SubscribeRouterTests { let signalExpect = XCTestExpectation(description: "Signal Event") let statusExpect = XCTestExpectation(description: "Status Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_signal_success", - "cancelled"]).session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_signal_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -164,7 +169,6 @@ extension SubscribeRouterTests { XCTAssertEqual(signal.payload.stringOptional, "Test Signal") subscription.unsubscribeAll() - signalExpect.fulfill() } listener.didReceiveStatus = { status in @@ -173,7 +177,6 @@ extension SubscribeRouterTests { } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -217,9 +220,9 @@ extension SubscribeRouterTests { } case let .uuidMetadataSet(changeset): XCTAssertEqual( - try? changeset.apply(to: baseUser).transcode(), patchedObjectUser + try? changeset.apply(to: baseUser).transcode(), + patchedObjectUser ) - objectExpect.fulfill() default: XCTFail("Incorrect Event Received \(event)") @@ -229,16 +232,13 @@ extension SubscribeRouterTests { switch event { case let .setUUID(changeset): XCTAssertEqual(changeset.metadataId, "TestUserID") - subscription.unsubscribeAll() - objectListenerExpect.fulfill() default: XCTFail("Incorrect Event Received") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -253,9 +253,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") let objectListenerExpect = XCTestExpectation(description: "Object Listener Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_uuidRemove_success", - "cancelled"]).session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_uuidRemove_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -279,16 +279,13 @@ extension SubscribeRouterTests { switch event { case let .removedUUID(metadataId): XCTAssertEqual(metadataId, "TestUserID") - subscription.unsubscribeAll() - objectListenerExpect.fulfill() default: XCTFail("Incorrect Event Received") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -303,9 +300,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") let objectListenerExpect = XCTestExpectation(description: "Object Listener Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_channelSet_success", - "cancelled"]).session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_channelSet_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -345,14 +342,12 @@ extension SubscribeRouterTests { XCTAssertEqual(changeset.metadataId, "TestSpaceID") subscription.unsubscribeAll() - objectListenerExpect.fulfill() default: XCTFail("Incorrect Event Received") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -367,9 +362,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") let objectListenerExpect = XCTestExpectation(description: "Object Listener Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_channelRemove_success", - "cancelled"]).session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_channelRemove_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -393,16 +388,13 @@ extension SubscribeRouterTests { switch event { case let .removedChannel(metadataId: metadataId): XCTAssertEqual(metadataId, "TestSpaceID") - subscription.unsubscribeAll() - objectListenerExpect.fulfill() default: XCTFail("Incorrect Event Received") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -417,9 +409,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") let objectListenerExpect = XCTestExpectation(description: "Object Listener Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_membershipSet_success", - "cancelled"]).session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_membershipSet_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -450,16 +442,13 @@ extension SubscribeRouterTests { switch event { case let .setMembership(membership): XCTAssertEqual(try? membership.transcode(), testMembership) - subscription.unsubscribeAll() - objectListenerExpect.fulfill() default: XCTFail("Incorrect Event Received \(event)") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -473,7 +462,9 @@ extension SubscribeRouterTests { let objectExpect = XCTestExpectation(description: "Object Event") let statusExpect = XCTestExpectation(description: "Status Event") let objectListenerExpect = XCTestExpectation(description: "Object Listener Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_membershipRemove_success", "cancelled"]).session else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_membershipRemove_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -504,16 +495,13 @@ extension SubscribeRouterTests { switch event { case let .removedMembership(membership): XCTAssertEqual(try? membership.transcode(), testMembership) - subscription.unsubscribeAll() - objectListenerExpect.fulfill() default: XCTFail("Incorrect Event Received \(event)") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -532,7 +520,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") let actionListenerExpect = XCTestExpectation(description: "Action Listener Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_addMessageAction_success", "cancelled"]).session else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_addMessageAction_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -556,16 +546,13 @@ extension SubscribeRouterTests { switch event { case let .added(action): XCTAssertEqual(try? action.transcode(), self?.testAction) - subscription.unsubscribeAll() - actionListenerExpect.fulfill() default: XCTFail("Incorrect Event Received") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -580,10 +567,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") let actionListenerExpect = XCTestExpectation(description: "Action Listener Event") - guard let session = try? MockURLSession - .mockSession(for: ["subscription_handshake_success", "subscription_removeMessageAction_success", "cancelled"]) - .session - else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_removeMessageAction_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -607,16 +593,13 @@ extension SubscribeRouterTests { switch event { case let .removed(action): XCTAssertEqual(try? action.transcode(), self?.testAction) - subscription.unsubscribeAll() - actionListenerExpect.fulfill() default: XCTFail("Incorrect Event Received") } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -635,7 +618,9 @@ extension SubscribeRouterTests { let signalExpect = XCTestExpectation(description: "Signal Event") let statusExpect = XCTestExpectation(description: "Status Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_mixed_success", "cancelled"]).session else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_mixed_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -670,7 +655,6 @@ extension SubscribeRouterTests { } } subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) @@ -692,7 +676,6 @@ extension SubscribeRouterTests { } let errorExpect = XCTestExpectation(description: "Error Event") - let statusExpect = XCTestExpectation(description: "Status Event") guard let session = try? MockURLSession.mockSession( for: ["cancelled"], @@ -705,29 +688,20 @@ extension SubscribeRouterTests { let listener = SubscriptionListener() listener.didReceiveSubscription = { event in - switch event { - case let .connectionStatusChanged(connection): - if connection == .disconnected { - statusExpect.fulfill() - } - case let .subscribeError(error): + if case let .subscribeError(error) = event { XCTAssertEqual(error.reason, .jsonDataDecodingFailure) - subscription.unsubscribeAll() - errorExpect.fulfill() - default: - XCTFail("Unexpected event received \(event)") } } + subscription.add(listener) - subscription.subscribe(to: [testChannel]) XCTAssertEqual(subscription.subscribedChannels, [testChannel]) defer { listener.cancel() } - wait(for: [errorExpect, statusExpect], timeout: 1.0, enforceOrder: true) + wait(for: [errorExpect], timeout: 1.0) } } @@ -738,7 +712,9 @@ extension SubscribeRouterTests { let statusExpect = XCTestExpectation(description: "Status Event") statusExpect.expectedFulfillmentCount = 2 - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_mixed_success", "cancelled"]).session else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_mixed_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } @@ -754,11 +730,11 @@ extension SubscribeRouterTests { XCTAssertEqual(subscription.subscribedChannels, []) statusExpect.fulfill() - case .connectionError(_): + case .connectionError: statusExpect.fulfill() case .disconnected: statusExpect.fulfill() - case .disconnectedUnexpectedly(_): + case .disconnectedUnexpectedly: statusExpect.fulfill() } default: @@ -777,12 +753,13 @@ extension SubscribeRouterTests { func testUnsubscribeAll() { let statusExpect = XCTestExpectation(description: "Status Event") - guard let session = try? MockURLSession.mockSession(for: ["subscription_handshake_success", "subscription_mixed_success", "cancelled"]).session else { + guard let session = try? MockURLSession.mockSession( + for: ["subscription_handshake_success", "subscription_mixed_success", "cancelled"] + ).session else { return XCTFail("Could not create mock url session") } let subscription = SubscribeSessionFactory.shared.getSession(from: config, with: session) - let otherChannel = "OtherChannel" let listener = SubscriptionListener() @@ -793,13 +770,12 @@ extension SubscribeRouterTests { case .connected: subscription.unsubscribeAll() XCTAssertEqual(subscription.subscribedChannels, []) - statusExpect.fulfill() - case .connectionError(_): + case .connectionError: statusExpect.fulfill() case .disconnected: statusExpect.fulfill() - case .disconnectedUnexpectedly(_): + case .disconnectedUnexpectedly: statusExpect.fulfill() } default: @@ -812,9 +788,6 @@ extension SubscribeRouterTests { XCTAssertTrue(subscription.subscribedChannels.contains(testChannel)) XCTAssertTrue(subscription.subscribedChannels.contains(otherChannel)) - subscription.unsubscribeAll() - XCTAssertEqual(subscription.subscribedChannels, []) - defer { listener.cancel() } wait(for: [statusExpect], timeout: 1.0) }