From 6a52f954f81d0aa7c407c1c0684a3ccabb836dd5 Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 18 Sep 2024 21:45:17 +0300 Subject: [PATCH] [Fix]Pass all available parameters to connect (#528) --- Sources/StreamVideo/Call.swift | 2 - .../Controllers/CallController.swift | 111 +++------- .../Stages/WebRTCCoordinator+Connecting.swift | 62 +++++- .../Stages/WebRTCCoordinator+Migrated.swift | 4 +- .../Stages/WebRTCCoordinator+Rejoining.swift | 5 +- .../WebRTC/v2/WebRTCAuthenticator.swift | 16 +- .../WebRTC/v2/WebRTCCoordinator.swift | 23 +- StreamVideoTests/Call/Call_Tests.swift | 8 - .../Mock/CallController_Mock.swift | 6 +- .../Mock/MockCallAuthenticator.swift | 22 +- .../Mock/MockWebRTCAuthenticator.swift | 17 +- .../Mock/MockWebRTCCoordinatorStack.swift | 2 +- .../WebRTC/SFU/SFUEventAdapter_Tests.swift | 9 +- ...inatorStateMachine_CleanUpStageTests.swift | 13 +- ...torStateMachine_ConnectingStageTests.swift | 206 ++++++++---------- ...rStateMachine_DisconnectedStageTests.swift | 11 +- ...teMachine_FastReconnectingStageTests.swift | 13 +- ...dinatorStateMachine_JoinedStageTests.swift | 14 +- ...inatorStateMachine_JoiningStageTests.swift | 13 +- ...inatorStateMachine_LeavingStageTests.swift | 13 +- ...natorStateMachine_MigratedStageTests.swift | 19 +- ...atorStateMachine_MigratingStageTests.swift | 13 +- ...atorStateMachine_RejoiningStageTests.swift | 15 +- .../WebRTCCoordinator_StateMachineTests.swift | 8 +- .../WebRTC/v2/WebRTCAuthenticator_Tests.swift | 78 ++++++- .../WebRTC/v2/WebRTCCoorindator_Tests.swift | 29 ++- .../v2/WebRTCJoinRequestFactory_Tests.swift | 11 +- .../WebRTC/v2/WebRTCStateAdapter_Tests.swift | 2 + 28 files changed, 492 insertions(+), 253 deletions(-) diff --git a/Sources/StreamVideo/Call.swift b/Sources/StreamVideo/Call.swift index bb16f5500..094515a5d 100644 --- a/Sources/StreamVideo/Call.swift +++ b/Sources/StreamVideo/Call.swift @@ -135,8 +135,6 @@ public class Call: @unchecked Sendable, WSEventsSubscriber { guard let self else { throw ClientError.Unexpected() } let response = try await callController.joinCall( create: create, - callType: callType, - callId: callId, callSettings: callSettings, options: options, ring: ring, diff --git a/Sources/StreamVideo/Controllers/CallController.swift b/Sources/StreamVideo/Controllers/CallController.swift index b18b02af5..abcb256c4 100644 --- a/Sources/StreamVideo/Controllers/CallController.swift +++ b/Sources/StreamVideo/Controllers/CallController.swift @@ -15,12 +15,14 @@ class CallController: @unchecked Sendable { callCid: callCid(from: callId, callType: callType), videoConfig: videoConfig ) { - [weak self, callId] create, ring, migratingFrom in + [weak self, callId] create, ring, migratingFrom, notify, options in if let self { return try await authenticateCall( create: create, ring: ring, - migratingFrom: migratingFrom + migratingFrom: migratingFrom, + notify: notify, + options: options ) } else { throw ClientError("Unable to authenticate callId:\(callId).") @@ -112,18 +114,17 @@ class CallController: @unchecked Sendable { @discardableResult func joinCall( create: Bool = true, - callType: String, - callId: String, callSettings: CallSettings?, options: CreateCallOptions? = nil, - migratingFrom: String? = nil, - sessionID: String? = nil, ring: Bool = false, notify: Bool = false ) async throws -> JoinCallResponse { try await webRTCCoordinator.connect( + create: create, callSettings: callSettings, - ring: ring + options: options, + ring: ring, + notify: notify ) guard let response = try await joinCallResponseSubject @@ -447,42 +448,40 @@ class CallController: @unchecked Sendable { .store(in: disposableBag) } - private func joinCall( + private func authenticateCall( create: Bool, - callType: String, - callId: String, - options: CreateCallOptions? = nil, - migratingFrom: String?, ring: Bool, - notify: Bool + migratingFrom: String?, + notify: Bool, + options: CreateCallOptions? ) async throws -> JoinCallResponse { let location = try await getLocation() - let response = try await joinCall( - callId: callId, - type: callType, - location: location, - options: options, - migratingFrom: migratingFrom, - create: create, - ring: ring, - notify: notify + var membersRequest = [MemberRequest]() + options?.memberIds?.forEach { + membersRequest.append(.init(userId: $0)) + } + options?.members?.forEach { + membersRequest.append($0) + } + let callRequest = CallRequest( + custom: options?.custom, + members: membersRequest, + settingsOverride: options?.settings, + startsAt: options?.startsAt, + team: options?.team ) - return response - } - - private func authenticateCall( - create: Bool, - ring: Bool, - migratingFrom: String? - ) async throws -> JoinCallResponse { - let response = try await joinCall( + let joinCall = JoinCallRequest( create: create, - callType: callType, - callId: callId, - options: nil, + data: callRequest, + location: location, migratingFrom: migratingFrom, - ring: ring, - notify: false + notify: notify, + ring: ring + ) + let response = try await defaultAPI.joinCall( + type: callType, + id: callId, + joinCallRequest: joinCall ) // We allow the CallController to manage its state. @@ -509,46 +508,6 @@ class CallController: @unchecked Sendable { return try await LocationFetcher.getLocation() } - private func joinCall( - callId: String, - type: String, - location: String, - options: CreateCallOptions? = nil, - migratingFrom: String?, - create: Bool, - ring: Bool, - notify: Bool - ) async throws -> JoinCallResponse { - var membersRequest = [MemberRequest]() - options?.memberIds?.forEach { - membersRequest.append(.init(userId: $0)) - } - options?.members?.forEach { - membersRequest.append($0) - } - let callRequest = CallRequest( - custom: options?.custom, - members: membersRequest, - settingsOverride: options?.settings, - startsAt: options?.startsAt, - team: options?.team - ) - let joinCall = JoinCallRequest( - create: create, - data: callRequest, - location: location, - migratingFrom: migratingFrom, - notify: notify, - ring: ring - ) - let joinCallResponse = try await defaultAPI.joinCall( - type: type, - id: callId, - joinCallRequest: joinCall - ) - return joinCallResponse - } - private func didFetch(_ response: JoinCallResponse) async { let sessionId = await webRTCCoordinator.stateAdapter.sessionID currentSFU = response.credentials.server.edgeName diff --git a/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Connecting.swift b/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Connecting.swift index e40b8491a..38287eeda 100644 --- a/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Connecting.swift +++ b/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Connecting.swift @@ -13,13 +13,21 @@ extension WebRTCCoordinator.StateMachine.Stage { /// - ring: A Boolean indicating whether to ring the other participants. /// - Returns: A `ConnectingStage` instance representing the connecting /// state of the WebRTC coordinator. + /// - Important: When transitioning from `.rejoining` values for ``ring``, + /// ``notify`` & ``options`` are nullified as are not relevant to the `rejoining` flow. static func connecting( _ context: Context, - ring: Bool + create: Bool, + options: CreateCallOptions?, + ring: Bool, + notify: Bool ) -> WebRTCCoordinator.StateMachine.Stage { ConnectingStage( context, - ring: ring + create: create, + options: options, + ring: ring, + notify: notify ) } } @@ -31,8 +39,11 @@ extension WebRTCCoordinator.StateMachine.Stage { WebRTCCoordinator.StateMachine.Stage, @unchecked Sendable { + let create: Bool + let options: CreateCallOptions? /// Indicates whether to ring the other participants. let ring: Bool + let notify: Bool /// Initializes a new instance of `ConnectingStage`. /// - Parameters: @@ -40,9 +51,15 @@ extension WebRTCCoordinator.StateMachine.Stage { /// - ring: A Boolean indicating whether to ring other participants. init( _ context: Context, - ring: Bool + create: Bool, + options: CreateCallOptions?, + ring: Bool, + notify: Bool ) { + self.create = create + self.options = options self.ring = ring + self.notify = notify super.init(id: .connecting, context: context) } @@ -52,16 +69,35 @@ extension WebRTCCoordinator.StateMachine.Stage { /// occurring. /// - Returns: This `ConnectingStage` instance if the transition is /// valid, otherwise `nil`. + /// - Important: When transitioning from `.rejoining` values for ``ring``, + /// ``notify`` & ``options`` are nullified as are not relevant to the `rejoining` flow. /// - Note: Valid transition from: `.idle`, `.rejoining` override func transition( from previousStage: WebRTCCoordinator.StateMachine.Stage ) -> Self? { switch previousStage.id { case .idle: - execute(create: true, updateSession: false) + execute( + create: create, + ring: ring, + notify: notify, + options: options, + updateSession: false + ) return self case .rejoining: - execute(create: false, updateSession: true) + if ring || notify || options != nil { + log.assert(ring == false, "Ring cannot be true when rejoining.") + log.assert(notify == false, "Notfiy cannot be true when rejoining.") + log.assert(options == nil, "CreateCallOptions cannot be non-nil when rejoining.") + } + execute( + create: false, + ring: false, + notify: false, + options: nil, + updateSession: true + ) return self default: return nil @@ -71,9 +107,19 @@ extension WebRTCCoordinator.StateMachine.Stage { /// Executes the call connecting process. /// - Parameters: /// - create: A Boolean indicating whether to create a new session. + /// - ring: A Boolean indicating whether to ring other participants. + /// - notify: A Boolean indicating whether to notify other participants. + /// - options: A `CreateCallOptions` instance to provide additional informations when + /// creating a call. /// - updateSession: A Boolean indicating whether to update the /// existing session. - private func execute(create: Bool, updateSession: Bool) { + private func execute( + create: Bool, + ring: Bool, + notify: Bool, + options: CreateCallOptions?, + updateSession: Bool + ) { Task { [weak self] in guard let self else { return } do { @@ -97,7 +143,9 @@ extension WebRTCCoordinator.StateMachine.Stage { coordinator: coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) /// We provide the ``SFUAdapter`` to the authenticator which will ensure diff --git a/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Migrated.swift b/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Migrated.swift index 010dedda0..f3feaae04 100644 --- a/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Migrated.swift +++ b/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Migrated.swift @@ -75,7 +75,9 @@ extension WebRTCCoordinator.StateMachine.Stage { coordinator: coordinator, currentSFU: context.currentSFU, create: false, - ring: false + ring: false, + notify: false, + options: nil ) /// We provide the ``SFUAdapter`` to the authenticator which will ensure diff --git a/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Rejoining.swift b/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Rejoining.swift index b582e14df..8524f8ffc 100644 --- a/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Rejoining.swift +++ b/Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Rejoining.swift @@ -110,7 +110,10 @@ extension WebRTCCoordinator.StateMachine.Stage { try transition?( .connecting( context, - ring: false + create: false, + options: nil, + ring: false, + notify: false ) ) } catch { diff --git a/Sources/StreamVideo/WebRTC/v2/WebRTCAuthenticator.swift b/Sources/StreamVideo/WebRTC/v2/WebRTCAuthenticator.swift index 5f00b7864..272e25733 100644 --- a/Sources/StreamVideo/WebRTC/v2/WebRTCAuthenticator.swift +++ b/Sources/StreamVideo/WebRTC/v2/WebRTCAuthenticator.swift @@ -19,7 +19,9 @@ protocol WebRTCAuthenticating { coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ) async throws -> (sfuAdapter: SFUAdapter, response: JoinCallResponse) /// Awaits the SFU to allow authentication @@ -48,10 +50,18 @@ struct WebRTCAuthenticator: WebRTCAuthenticating { coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ) async throws -> (sfuAdapter: SFUAdapter, response: JoinCallResponse) { let response = try await coordinator - .callAuthentication(create, ring, currentSFU) + .callAuthentication( + create, + ring, + currentSFU, + notify, + options + ) await coordinator.stateAdapter.set( token: response.credentials.token diff --git a/Sources/StreamVideo/WebRTC/v2/WebRTCCoordinator.swift b/Sources/StreamVideo/WebRTC/v2/WebRTCCoordinator.swift index 883389bf5..72dd18927 100644 --- a/Sources/StreamVideo/WebRTC/v2/WebRTCCoordinator.swift +++ b/Sources/StreamVideo/WebRTC/v2/WebRTCCoordinator.swift @@ -16,8 +16,16 @@ final class WebRTCCoordinator: @unchecked Sendable { /// - create: Whether the call should be created on the backend side. /// - ring: Whether the call is a ringing call. /// - migratingFrom: If migrating, where are we migrating from. + /// - notify: + /// - options: /// - Returns: A `JoinCallResponse` wrapped in an async throw. - typealias AuthenticationHandler = (Bool, Bool, String?) async throws -> JoinCallResponse + typealias AuthenticationHandler = ( + Bool, + Bool, + String?, + Bool, + CreateCallOptions? + ) async throws -> JoinCallResponse private static let recordingUserId = "recording-egress" private static let participantsThreshold = 10 @@ -81,12 +89,21 @@ final class WebRTCCoordinator: @unchecked Sendable { /// - callSettings: Optional call settings. /// - ring: Boolean flag indicating if a ring tone should be played. func connect( + create: Bool = true, callSettings: CallSettings?, - ring: Bool + options: CreateCallOptions?, + ring: Bool, + notify: Bool ) async throws { await stateAdapter.set(initialCallSettings: callSettings) try stateMachine.transition( - .connecting(stateMachine.currentStage.context, ring: ring) + .connecting( + stateMachine.currentStage.context, + create: create, + options: options, + ring: ring, + notify: notify + ) ) } diff --git a/StreamVideoTests/Call/Call_Tests.swift b/StreamVideoTests/Call/Call_Tests.swift index 15b224b83..38ee0a779 100644 --- a/StreamVideoTests/Call/Call_Tests.swift +++ b/StreamVideoTests/Call/Call_Tests.swift @@ -422,12 +422,8 @@ private final class MockCallController: CallController, Mockable { override func joinCall( create: Bool = true, - callType: String, - callId: String, callSettings: CallSettings?, options: CreateCallOptions? = nil, - migratingFrom: String? = nil, - sessionID: String? = nil, ring: Bool = false, notify: Bool = false ) async throws -> JoinCallResponse { @@ -439,12 +435,8 @@ private final class MockCallController: CallController, Mockable { } else { return try await super.joinCall( create: create, - callType: callType, - callId: callId, callSettings: callSettings, options: options, - migratingFrom: migratingFrom, - sessionID: sessionID, ring: ring, notify: notify ) diff --git a/StreamVideoTests/Mock/CallController_Mock.swift b/StreamVideoTests/Mock/CallController_Mock.swift index f53b3bc51..cd3a56dbc 100644 --- a/StreamVideoTests/Mock/CallController_Mock.swift +++ b/StreamVideoTests/Mock/CallController_Mock.swift @@ -15,16 +15,12 @@ class CallController_Mock: CallController { override func joinCall( create: Bool = true, - callType: String, - callId: String, callSettings: CallSettings?, options: CreateCallOptions? = nil, - migratingFrom: String? = nil, - sessionID: String? = nil, ring: Bool = false, notify: Bool = false ) async throws -> JoinCallResponse { - mockResponseBuilder.makeJoinCallResponse(cid: "\(callType):\(callId)") + mockResponseBuilder.makeJoinCallResponse(cid: super.call?.cId ?? "default:\(String.unique)") } override func changeAudioState(isEnabled: Bool) async throws { /* no op */ } diff --git a/StreamVideoTests/Mock/MockCallAuthenticator.swift b/StreamVideoTests/Mock/MockCallAuthenticator.swift index 8103f556f..465f8d595 100644 --- a/StreamVideoTests/Mock/MockCallAuthenticator.swift +++ b/StreamVideoTests/Mock/MockCallAuthenticator.swift @@ -8,14 +8,30 @@ final class MockCallAuthenticator { var authenticateResult: Result = .failure(ClientError.Unknown()) - private(set) var authenticateCalledWithInput: [(create: Bool, ring: Bool, migratingFrom: String?)] = [] + private(set) var authenticateCalledWithInput: [( + create: Bool, + ring: Bool, + migratingFrom: String?, + notify: Bool, + options: CreateCallOptions? + )] = [] func authenticate( create: Bool, ring: Bool, - migratingFrom: String? + migratingFrom: String?, + notify: Bool, + options: CreateCallOptions? ) async throws -> JoinCallResponse { - authenticateCalledWithInput.append((create, ring, migratingFrom)) + authenticateCalledWithInput.append( + ( + create, + ring, + migratingFrom, + notify, + options + ) + ) switch authenticateResult { case let .success(result): return result diff --git a/StreamVideoTests/Mock/MockWebRTCAuthenticator.swift b/StreamVideoTests/Mock/MockWebRTCAuthenticator.swift index bd271933c..5b1a3b6b8 100644 --- a/StreamVideoTests/Mock/MockWebRTCAuthenticator.swift +++ b/StreamVideoTests/Mock/MockWebRTCAuthenticator.swift @@ -5,7 +5,6 @@ @testable import StreamVideo final class MockWebRTCAuthenticator: WebRTCAuthenticating, Mockable { - // MARK: - Mockable typealias FunctionKey = MockFunctionKey @@ -16,7 +15,9 @@ final class MockWebRTCAuthenticator: WebRTCAuthenticating, Mockable { coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ) case waitForAuthentication(sfuAdapter: SFUAdapter) @@ -24,8 +25,8 @@ final class MockWebRTCAuthenticator: WebRTCAuthenticating, Mockable { var payload: Any { switch self { - case let .authenticate(coordinator, currentSFU, create, ring): - return (coordinator, currentSFU, create, ring) + case let .authenticate(coordinator, currentSFU, create, ring, notify, options): + return (coordinator, currentSFU, create, ring, notify, options) case let .waitForAuthentication(sfuAdapter): return sfuAdapter case let .waitForConnect(sfuAdapter): @@ -65,7 +66,9 @@ final class MockWebRTCAuthenticator: WebRTCAuthenticating, Mockable { coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ) async throws -> (sfuAdapter: SFUAdapter, response: JoinCallResponse) { stubbedFunctionInput[.authenticate]? .append( @@ -73,7 +76,9 @@ final class MockWebRTCAuthenticator: WebRTCAuthenticating, Mockable { coordinator: coordinator, currentSFU: currentSFU, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) ) diff --git a/StreamVideoTests/Mock/MockWebRTCCoordinatorStack.swift b/StreamVideoTests/Mock/MockWebRTCCoordinatorStack.swift index ed35536c1..4db8d665c 100644 --- a/StreamVideoTests/Mock/MockWebRTCCoordinatorStack.swift +++ b/StreamVideoTests/Mock/MockWebRTCCoordinatorStack.swift @@ -21,7 +21,7 @@ final class MockWebRTCCoordinatorStack { user: User = .dummy(), apiKey: String = .unique, callCid: String = "default:\(String.unique)", - videoConfig: VideoConfig = .dummy(), + videoConfig: VideoConfig, callAuthenticator: MockCallAuthenticator = .init(), webRTCAuthenticator: MockWebRTCAuthenticator = .init(), sfuStack: MockSFUStack = .init(), diff --git a/StreamVideoTests/WebRTC/SFU/SFUEventAdapter_Tests.swift b/StreamVideoTests/WebRTC/SFU/SFUEventAdapter_Tests.swift index bb55d1446..7d8607a08 100644 --- a/StreamVideoTests/WebRTC/SFU/SFUEventAdapter_Tests.swift +++ b/StreamVideoTests/WebRTC/SFU/SFUEventAdapter_Tests.swift @@ -8,6 +8,8 @@ import XCTest final class SFUEventAdapter_Tests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var mockService: MockSignalServer! = .init() private lazy var mockWebSocket: MockWebSocketClient! = .init(webSocketClientType: .sfu) private lazy var sfuAdapter: SFUAdapter! = .init( @@ -19,7 +21,7 @@ final class SFUEventAdapter_Tests: XCTestCase, @unchecked Sendable { user: .dummy(), apiKey: .unique, callCid: .unique, - videoConfig: .dummy(), + videoConfig: Self.videoConfig, rtcPeerConnectionCoordinatorFactory: MockRTCPeerConnectionCoordinatorFactory() ) private lazy var subject: SFUEventAdapter! = .init( @@ -35,6 +37,11 @@ final class SFUEventAdapter_Tests: XCTestCase, @unchecked Sendable { _ = subject } + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { subject = nil stateAdapter = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_CleanUpStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_CleanUpStageTests.swift index 01bf96398..0e5ce23dd 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_CleanUpStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_CleanUpStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_CleanUpStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -23,7 +25,16 @@ final class WebRTCCoordinatorStateMachine_CleanUpStageTests: XCTestCase, @unchec .filter { $0 != .idle && $0 != subject.id } ) private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .cleanUp(.init()) - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) + + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } override func tearDown() { allOtherStages = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_ConnectingStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_ConnectingStageTests.swift index dea6df957..a334429bf 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_ConnectingStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_ConnectingStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -15,8 +17,23 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc .filter { $0 != subject.id } .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.idle, .rejoining] - private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .connecting(.init(), ring: true) - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .connecting( + .init(), + create: true, + options: nil, + ring: true, + notify: false + ) + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) + + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } override func tearDown() { allOtherStages = nil @@ -50,50 +67,54 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .idle, expectedTarget: .disconnected, - subject: .connecting(.init(), ring: true) + subject: subject ) { target in XCTAssertNotNil(target.context.flowError as? ClientError) } } func test_transition_fromIdle_doesNotUpdateSession() async throws { + _ = mockCoordinatorStack.coordinator + await wait(for: 0.5) let expectedSessionId = await mockCoordinatorStack .coordinator .stateAdapter .sessionID + subject.context.coordinator = mockCoordinatorStack.coordinator try await assertTransition( from: .idle, expectedTarget: .disconnected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator - ), - ring: true - ) + subject: subject ) { [mockCoordinatorStack] _ in let actual = await mockCoordinatorStack?.coordinator.stateAdapter.sessionID XCTAssertEqual(actual, expectedSessionId) } } - func test_transition_fromIdleRingTrueAuthenticationFails_transitionsToDisconnected() async throws { + func test_transition_fromIdleAuthenticationFailsCreateFalse_transitionsToDisconnectedWithExpectedInput() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator + let options = CreateCallOptions(team: .unique) + try await assertTransition( from: .idle, expectedTarget: .disconnected, subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true + subject.context, + create: false, + options: options, + ring: true, + notify: true ) ) { [mockCoordinatorStack] target in let callType = ( coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ).self let input = try XCTUnwrap( mockCoordinatorStack?.webRTCAuthenticator.recordedInputPayload( @@ -103,29 +124,37 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc ) XCTAssertTrue(input.coordinator === mockCoordinatorStack?.coordinator) XCTAssertNil(input.currentSFU) - XCTAssertTrue(input.create) + XCTAssertFalse(input.create) XCTAssertTrue(input.ring) + XCTAssertTrue(input.notify) + XCTAssertEqual(input.options?.team, options.team) XCTAssertTrue(target.context.flowError is ClientError) } } - func test_transition_fromIdleRingFalseAuthenticationFails_transitionsToDisconnected() async throws { + func test_transition_fromIdleAuthenticationFails_transitionsToDisconnectedWithExpectedInput() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator + let options = CreateCallOptions(team: .unique) + try await assertTransition( from: .idle, expectedTarget: .disconnected, subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: false + subject.context, + create: true, + options: options, + ring: true, + notify: true ) ) { [mockCoordinatorStack] target in let callType = ( coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ).self let input = try XCTUnwrap( mockCoordinatorStack?.webRTCAuthenticator.recordedInputPayload( @@ -136,12 +165,16 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc XCTAssertTrue(input.coordinator === mockCoordinatorStack?.coordinator) XCTAssertNil(input.currentSFU) XCTAssertTrue(input.create) - XCTAssertFalse(input.ring) + XCTAssertTrue(input.ring) + XCTAssertTrue(input.notify) + XCTAssertEqual(input.options?.team, options.team) XCTAssertTrue(target.context.flowError is ClientError) } } func test_transition_fromIdleSFUConnectFails_transitionsToDisconnected() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator mockCoordinatorStack.webRTCAuthenticator.stub( for: .authenticate, with: Result<(SFUAdapter, JoinCallResponse), Error> @@ -151,13 +184,7 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .idle, expectedTarget: .disconnected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true - ) + subject: subject ) { [mockCoordinatorStack] target in let input = try XCTUnwrap( mockCoordinatorStack? @@ -171,6 +198,8 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc } func test_transition_fromIdleSFUConnectedAndStateAdapterUpdated_transitionsToConnected() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator mockCoordinatorStack.webRTCAuthenticator.stub( for: .authenticate, with: Result<(SFUAdapter, JoinCallResponse), Error> @@ -184,13 +213,7 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .idle, expectedTarget: .connected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true - ) + subject: subject ) { [mockCoordinatorStack] _ in let stateAdapter = try XCTUnwrap(mockCoordinatorStack?.coordinator.stateAdapter) let sfuAdapter = await stateAdapter.sfuAdapter @@ -199,6 +222,8 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc } func test_transition_fromIdleSFUConnectedContextWasUpdated_transitionsToConnected() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator mockCoordinatorStack.webRTCAuthenticator.stub( for: .authenticate, with: Result< @@ -220,13 +245,7 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .idle, expectedTarget: .connected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true - ) + subject: subject ) { target in XCTAssertEqual(target.context.currentSFU, "test-sfu") } @@ -238,13 +257,14 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .rejoining, expectedTarget: .disconnected, - subject: .connecting(.init(), ring: true) + subject: subject ) { target in XCTAssertNotNil(target.context.flowError as? ClientError) } } func test_transition_fromRejoining_updatesSession() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator let expectedSessionId = await mockCoordinatorStack .coordinator .stateAdapter @@ -253,67 +273,35 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .rejoining, expectedTarget: .disconnected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator - ), - ring: true - ) + subject: subject ) { [mockCoordinatorStack] _ in let actual = await mockCoordinatorStack?.coordinator.stateAdapter.sessionID XCTAssertNotEqual(actual, expectedSessionId) } } - func test_transition_fromRejoiningRingTrueAuthenticationFails_transitionsToDisconnected() async throws { + func test_transition_fromRejoiningAuthenticationFails_transitionsToDisconnectedWithExpectedInput() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator + let options = CreateCallOptions(team: .unique) try await assertTransition( from: .rejoining, expectedTarget: .disconnected, subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true + subject.context, + create: true, + options: options, + ring: true, + notify: true ) ) { [mockCoordinatorStack] target in let callType = ( coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool - ).self - let input = try XCTUnwrap( - mockCoordinatorStack?.webRTCAuthenticator.recordedInputPayload( - callType, - for: .authenticate - )?.first - ) - XCTAssertTrue(input.coordinator === mockCoordinatorStack?.coordinator) - XCTAssertNil(input.currentSFU) - XCTAssertFalse(input.create) - XCTAssertTrue(input.ring) - XCTAssertTrue(target.context.flowError is ClientError) - } - } - - func test_transition_fromRejoiningRingFalseAuthenticationFails_transitionsToDisconnected() async throws { - try await assertTransition( - from: .rejoining, - expectedTarget: .disconnected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: false - ) - ) { [mockCoordinatorStack] target in - let callType = ( - coordinator: WebRTCCoordinator, - currentSFU: String?, - create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ).self let input = try XCTUnwrap( mockCoordinatorStack?.webRTCAuthenticator.recordedInputPayload( @@ -325,11 +313,15 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc XCTAssertNil(input.currentSFU) XCTAssertFalse(input.create) XCTAssertFalse(input.ring) + XCTAssertFalse(input.notify) + XCTAssertNil(input.options) XCTAssertTrue(target.context.flowError is ClientError) } } func test_transition_fromRejoiningSFUConnectFails_transitionsToDisconnected() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator mockCoordinatorStack.webRTCAuthenticator.stub( for: .authenticate, with: Result<(SFUAdapter, JoinCallResponse), Error> @@ -339,14 +331,8 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .rejoining, expectedTarget: .disconnected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true - ) - ) { [error, mockCoordinatorStack] target in + subject: subject + ) { [mockCoordinatorStack] target in let input = try XCTUnwrap( mockCoordinatorStack? .webRTCAuthenticator @@ -359,6 +345,8 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc } func test_transition_fromRejoiningSFUConnectedAndStateAdapterUpdated_transitionsToConnected() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator mockCoordinatorStack.webRTCAuthenticator.stub( for: .authenticate, with: Result<(SFUAdapter, JoinCallResponse), Error> @@ -372,13 +360,7 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .rejoining, expectedTarget: .connected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true - ) + subject: subject ) { [mockCoordinatorStack] _ in let stateAdapter = try XCTUnwrap(mockCoordinatorStack?.coordinator.stateAdapter) let sfuAdapter = await stateAdapter.sfuAdapter @@ -387,6 +369,8 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc } func test_transition_fromRejoiningSFUConnectedContextWasUpdated_transitionsToConnected() async throws { + subject.context.coordinator = mockCoordinatorStack.coordinator + subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator mockCoordinatorStack.webRTCAuthenticator.stub( for: .authenticate, with: Result< @@ -408,13 +392,7 @@ final class WebRTCCoordinatorStateMachine_ConnectingStageTests: XCTestCase, @unc try await assertTransition( from: .rejoining, expectedTarget: .connected, - subject: .connecting( - .init( - coordinator: mockCoordinatorStack.coordinator, - authenticator: mockCoordinatorStack.webRTCAuthenticator - ), - ring: true - ) + subject: subject ) { target in XCTAssertEqual(target.context.currentSFU, "test-sfu") } diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_DisconnectedStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_DisconnectedStageTests.swift index ecfb0783c..99530d9e8 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_DisconnectedStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_DisconnectedStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_DisconnectedStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -24,13 +26,20 @@ final class WebRTCCoordinatorStateMachine_DisconnectedStageTests: XCTestCase, @u .migrated ] private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .disconnected(.init()) - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) override func setUp() { super.setUp() mockCoordinatorStack.internetConnection.subject.send(.unknown) } + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { allOtherStages = nil validStages = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_FastReconnectingStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_FastReconnectingStageTests.swift index 66fd65f9b..023fdb808 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_FastReconnectingStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_FastReconnectingStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_FastReconnectingStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -16,7 +18,16 @@ final class WebRTCCoordinatorStateMachine_FastReconnectingStageTests: XCTestCase .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.disconnected] private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .fastReconnecting(.init()) - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) + + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } override func tearDown() { allOtherStages = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoinedStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoinedStageTests.swift index 81ab55bec..7174838e2 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoinedStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoinedStageTests.swift @@ -8,6 +8,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_JoinedStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -16,9 +18,18 @@ final class WebRTCCoordinatorStateMachine_JoinedStageTests: XCTestCase, @uncheck .filter { $0 != subject.id } .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.joining] - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .joined(.init()) + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { allOtherStages = nil mockCoordinatorStack = nil @@ -200,6 +211,7 @@ final class WebRTCCoordinatorStateMachine_JoinedStageTests: XCTestCase, @uncheck sfuAdapter: mockCoordinatorStack.sfuStack.adapter ) + await wait(for: 0.2) let sessionId = await mockCoordinatorStack.coordinator.stateAdapter.sessionID await assertResultAfterTrigger( trigger: { [mockCoordinatorStack] in diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoiningStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoiningStageTests.swift index 5c3bc3da9..713d5a05f 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoiningStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoiningStageTests.swift @@ -8,6 +8,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_JoiningStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -16,14 +18,23 @@ final class WebRTCCoordinatorStateMachine_JoiningStageTests: XCTestCase, @unchec .filter { $0 != subject.id } .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.connected, .fastReconnected, .migrated] - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .joining(.init()) + // MARK: - Lifecycle + override func setUp() { super.setUp() subject.context.authenticator = mockCoordinatorStack.webRTCAuthenticator } + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { allOtherStages = nil mockCoordinatorStack = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_LeavingStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_LeavingStageTests.swift index b64e42aba..7516e01c8 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_LeavingStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_LeavingStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_LeavingStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -16,7 +18,16 @@ final class WebRTCCoordinatorStateMachine_LeavingStageTests: XCTestCase, @unchec .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.joined, .disconnected] private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .leaving(.init()) - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) + + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } override func tearDown() { allOtherStages = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratedStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratedStageTests.swift index 9587a980a..6fef71a29 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratedStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratedStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_MigratedStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -16,7 +18,16 @@ final class WebRTCCoordinatorStateMachine_MigratedStageTests: XCTestCase, @unche .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.migrating] private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .migrated(.init()) - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) + + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } override func tearDown() { allOtherStages = nil @@ -69,7 +80,9 @@ final class WebRTCCoordinatorStateMachine_MigratedStageTests: XCTestCase, @unche coordinator: WebRTCCoordinator, currentSFU: String?, create: Bool, - ring: Bool + ring: Bool, + notify: Bool, + options: CreateCallOptions? ).self let input = try XCTUnwrap( mockCoordinatorStack?.webRTCAuthenticator.recordedInputPayload( @@ -81,6 +94,8 @@ final class WebRTCCoordinatorStateMachine_MigratedStageTests: XCTestCase, @unche XCTAssertEqual(input.currentSFU, currentSFU) XCTAssertFalse(input.create) XCTAssertFalse(input.ring) + XCTAssertFalse(input.notify) + XCTAssertNil(input.options) XCTAssertTrue(target.context.flowError is ClientError) } } diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratingStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratingStageTests.swift index a7de7e5ec..432a3c260 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratingStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_MigratingStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_MigratingStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -15,9 +17,18 @@ final class WebRTCCoordinatorStateMachine_MigratingStageTests: XCTestCase, @unch .filter { $0 != subject.id } .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.disconnected] - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .migrating(.init()) + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { allOtherStages = nil mockCoordinatorStack = nil diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_RejoiningStageTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_RejoiningStageTests.swift index 199d7eccc..c13cfbfd3 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_RejoiningStageTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_RejoiningStageTests.swift @@ -7,6 +7,8 @@ import XCTest final class WebRTCCoordinatorStateMachine_RejoiningStageTests: XCTestCase, @unchecked Sendable { + private static var videoConfig: VideoConfig! = .dummy() + private lazy var allOtherStages: [WebRTCCoordinator.StateMachine.Stage]! = WebRTCCoordinator .StateMachine .Stage @@ -15,9 +17,18 @@ final class WebRTCCoordinatorStateMachine_RejoiningStageTests: XCTestCase, @unch .filter { $0 != subject.id } .map { WebRTCCoordinator.StateMachine.Stage(id: $0, context: .init()) } private lazy var validStages: Set! = [.disconnected] - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) private lazy var subject: WebRTCCoordinator.StateMachine.Stage! = .rejoining(.init()) + // MARK: - Lifecycle + + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { allOtherStages = nil mockCoordinatorStack = nil @@ -68,6 +79,7 @@ final class WebRTCCoordinatorStateMachine_RejoiningStageTests: XCTestCase, @unch func test_transition_sfuAdapterIsConnected_sendLeaveRequestAndDisconnecteWereCalled() async { subject.context.coordinator = mockCoordinatorStack.coordinator + await wait(for: 0.25) let sessionId = await mockCoordinatorStack.coordinator.stateAdapter.sessionID await mockCoordinatorStack .coordinator @@ -94,6 +106,7 @@ final class WebRTCCoordinatorStateMachine_RejoiningStageTests: XCTestCase, @unch func test_transition_isRejoiningFromSessionIDWasSetCorrectly() async { subject.context.coordinator = mockCoordinatorStack.coordinator + await wait(for: 0.5) let sessionId = await mockCoordinatorStack.coordinator.stateAdapter.sessionID await mockCoordinatorStack .coordinator diff --git a/StreamVideoTests/WebRTC/v2/StateMachine/WebRTCCoordinator_StateMachineTests.swift b/StreamVideoTests/WebRTC/v2/StateMachine/WebRTCCoordinator_StateMachineTests.swift index 93e734cbb..ce5e11cb6 100644 --- a/StreamVideoTests/WebRTC/v2/StateMachine/WebRTCCoordinator_StateMachineTests.swift +++ b/StreamVideoTests/WebRTC/v2/StateMachine/WebRTCCoordinator_StateMachineTests.swift @@ -24,7 +24,13 @@ final class WebRTCCoordinator_StateMachineTests: XCTestCase { func testValidTransition() { // Given - let nextState = WebRTCCoordinator.StateMachine.Stage.connecting(.init(), ring: true) + let nextState = WebRTCCoordinator.StateMachine.Stage.connecting( + .init(), + create: false, + options: nil, + ring: false, + notify: false + ) XCTAssertEqual(subject.currentStage.id, .idle) // When diff --git a/StreamVideoTests/WebRTC/v2/WebRTCAuthenticator_Tests.swift b/StreamVideoTests/WebRTC/v2/WebRTCAuthenticator_Tests.swift index 2babe5bf7..ab4f38489 100644 --- a/StreamVideoTests/WebRTC/v2/WebRTCAuthenticator_Tests.swift +++ b/StreamVideoTests/WebRTC/v2/WebRTCAuthenticator_Tests.swift @@ -7,11 +7,20 @@ import XCTest final class WebRTCAuthenticator_Tests: XCTestCase { - private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private static var videoConfig: VideoConfig! = .dummy() + + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) private lazy var subject: WebRTCAuthenticator! = .init() // MARK: - Lifecycle + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { mockCoordinatorStack = nil subject = nil @@ -20,10 +29,37 @@ final class WebRTCAuthenticator_Tests: XCTestCase { // MARK: - authenticate + func test_authenticate_withValidData_callAuthenticationWasCalledWithExpectedInput() async throws { + let currentSFU = String.unique + let create = true + let ring = true + let notify = true + let options = CreateCallOptions(team: .unique) + let expected = JoinCallResponse.dummy() + mockCoordinatorStack.callAuthenticator.authenticateResult = .success(expected) + + _ = try await subject.authenticate( + coordinator: mockCoordinatorStack.coordinator, + currentSFU: currentSFU, + create: create, + ring: ring, + notify: notify, + options: options + ) + + let input = try XCTUnwrap(mockCoordinatorStack.callAuthenticator.authenticateCalledWithInput.first) + XCTAssertTrue(input.create) + XCTAssertTrue(input.ring) + XCTAssertTrue(input.notify) + XCTAssertEqual(input.options?.team, options.team) + } + func test_authenticate_withValidData_shouldReturnSFUAdapterAndJoinCallResponse() async throws { let currentSFU = String.unique let create = true let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy() mockCoordinatorStack.callAuthenticator.authenticateResult = .success(expected) @@ -31,7 +67,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: currentSFU, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) XCTAssertEqual(response, expected) @@ -42,6 +80,8 @@ final class WebRTCAuthenticator_Tests: XCTestCase { func test_authenticate_withNilCurrentSFU_shouldStillReturnSFUAdapterAndJoinCallResponse() async throws { let create = true let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy() mockCoordinatorStack.callAuthenticator.authenticateResult = .success(expected) @@ -49,7 +89,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) XCTAssertEqual(response, expected) @@ -60,6 +102,8 @@ final class WebRTCAuthenticator_Tests: XCTestCase { func test_authenticate_withCreateTrueAndInitialCallSettings_shouldSetInitialCallSettings() async throws { let create = true let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy(call: .dummy(settings: .dummy(audio: .dummy(micDefaultOn: false)))) mockCoordinatorStack.callAuthenticator.authenticateResult = .success(expected) let initialCallSettings = CallSettings( @@ -76,7 +120,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) let callSettings = await mockCoordinatorStack @@ -89,6 +135,8 @@ final class WebRTCAuthenticator_Tests: XCTestCase { func test_authenticate_withCreateTrueWithoutInitialCallSettings_shouldSetCallSettingsFromResponse() async throws { let create = true let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy(call: .dummy(settings: .dummy(audio: .dummy(micDefaultOn: true)))) mockCoordinatorStack.callAuthenticator.authenticateResult = .success(expected) @@ -96,7 +144,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) let callSettings = await mockCoordinatorStack @@ -109,6 +159,8 @@ final class WebRTCAuthenticator_Tests: XCTestCase { func test_authenticate_withCreateFalse_shouldNotSetInitialCallSettings() async throws { let create = false let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy(call: .dummy(settings: .dummy(audio: .dummy(micDefaultOn: false)))) mockCoordinatorStack.callAuthenticator.authenticateResult = .success(expected) await mockCoordinatorStack @@ -120,7 +172,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) let callSettings = await mockCoordinatorStack @@ -134,6 +188,8 @@ final class WebRTCAuthenticator_Tests: XCTestCase { func test_authenticate_updatesVideoOptions() async throws { let create = false let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy( call: .dummy( settings: .dummy( @@ -149,7 +205,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) let videoOptions = await mockCoordinatorStack @@ -163,6 +221,8 @@ final class WebRTCAuthenticator_Tests: XCTestCase { func test_authenticate_updatesIntervalOnStatsReporter() async throws { let create = false let ring = true + let notify = true + let options = CreateCallOptions() let expected = JoinCallResponse.dummy( statsOptions: .init(reportingIntervalMs: 12000) ) @@ -172,7 +232,9 @@ final class WebRTCAuthenticator_Tests: XCTestCase { coordinator: mockCoordinatorStack.coordinator, currentSFU: nil, create: create, - ring: ring + ring: ring, + notify: notify, + options: options ) let statsReporter = await mockCoordinatorStack diff --git a/StreamVideoTests/WebRTC/v2/WebRTCCoorindator_Tests.swift b/StreamVideoTests/WebRTC/v2/WebRTCCoorindator_Tests.swift index f90191e07..d7b6847b8 100644 --- a/StreamVideoTests/WebRTC/v2/WebRTCCoorindator_Tests.swift +++ b/StreamVideoTests/WebRTC/v2/WebRTCCoorindator_Tests.swift @@ -50,17 +50,37 @@ final class WebRTCCoordinator_Tests: XCTestCase { func test_connect_shouldSetInitialCallSettingsAndTransitionStateMachine() async throws { let expectedCallSettings = CallSettings(cameraPosition: .back) + let expectedOptions = CreateCallOptions( + memberIds: [.unique, .unique], + members: [.init(userId: .unique)], + custom: [.unique: .bool(true)], + settings: CallSettingsRequest(audio: .init(defaultDevice: .earpiece)), + startsAt: .init(timeIntervalSince1970: 100), + team: .unique + ) try await assertTransitionToStage( .connecting, operation: { try await self .subject - .connect(callSettings: expectedCallSettings, ring: true) + .connect( + callSettings: expectedCallSettings, + options: expectedOptions, + ring: true, + notify: true + ) } ) { stage in let expectedStage = try XCTUnwrap(stage as? WebRTCCoordinator.StateMachine.Stage.ConnectingStage) + XCTAssertEqual(expectedStage.options?.memberIds, expectedOptions.memberIds) + XCTAssertEqual(expectedStage.options?.members, expectedOptions.members) + XCTAssertEqual(expectedStage.options?.custom, expectedOptions.custom) + XCTAssertEqual(expectedStage.options?.settings?.audio?.defaultDevice, .earpiece) + XCTAssertEqual(expectedStage.options?.startsAt, expectedOptions.startsAt) + XCTAssertEqual(expectedStage.options?.team, expectedOptions.team) XCTAssertTrue(expectedStage.ring) + XCTAssertTrue(expectedStage.notify) await self.assertEqualAsync( await self.subject.stateAdapter.initialCallSettings, expectedCallSettings @@ -112,7 +132,12 @@ final class WebRTCCoordinator_Tests: XCTestCase { mockInternetConnection.subject.send(.unavailable) try await subject - .connect(callSettings: nil, ring: true) + .connect( + callSettings: nil, + options: nil, + ring: true, + notify: false + ) await wait(for: 1) await assertTransitionToStage( diff --git a/StreamVideoTests/WebRTC/v2/WebRTCJoinRequestFactory_Tests.swift b/StreamVideoTests/WebRTC/v2/WebRTCJoinRequestFactory_Tests.swift index 6e05cfecb..b0df70fe3 100644 --- a/StreamVideoTests/WebRTC/v2/WebRTCJoinRequestFactory_Tests.swift +++ b/StreamVideoTests/WebRTC/v2/WebRTCJoinRequestFactory_Tests.swift @@ -8,11 +8,20 @@ import XCTest final class WebRTCJoinRequestFactory_Tests: XCTestCase { - private var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init() + private static var videoConfig: VideoConfig! = .dummy() + + private lazy var mockCoordinatorStack: MockWebRTCCoordinatorStack! = .init( + videoConfig: Self.videoConfig + ) private var subject: WebRTCJoinRequestFactory! = .init() // MARK: - Lifecycle + override class func tearDown() { + Self.videoConfig = nil + super.tearDown() + } + override func tearDown() { subject = nil mockCoordinatorStack = nil diff --git a/StreamVideoTests/WebRTC/v2/WebRTCStateAdapter_Tests.swift b/StreamVideoTests/WebRTC/v2/WebRTCStateAdapter_Tests.swift index de40b6c38..82e271955 100644 --- a/StreamVideoTests/WebRTC/v2/WebRTCStateAdapter_Tests.swift +++ b/StreamVideoTests/WebRTC/v2/WebRTCStateAdapter_Tests.swift @@ -39,6 +39,8 @@ final class WebRTCStateAdapter_Tests: XCTestCase { // MARK: - setSessionID func test_setSessionID_shouldUpdateSessionID() async throws { + _ = subject + await wait(for: 0.5) let expected = String.unique await subject.set(sessionID: expected)