From 32c4222472af0bb5b45514c206420357f95cd786 Mon Sep 17 00:00:00 2001 From: Gerson Noboa Date: Fri, 19 Jan 2024 14:58:48 +0200 Subject: [PATCH] Add unit tests for CallCoordinator Correct actions and creation of view controllers in the coordinator has been covered with unit tests. MOB-2920 --- GliaWidgets.xcodeproj/project.pbxproj | 16 ++ .../Call/CallViewController.swift | 2 +- .../CallCoordinator.Environment.Mock.swift | 31 ++++ .../Call/CallCoordinatorTests.swift | 156 ++++++++++++++++++ 4 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinator.Environment.Mock.swift create mode 100644 GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinatorTests.swift diff --git a/GliaWidgets.xcodeproj/project.pbxproj b/GliaWidgets.xcodeproj/project.pbxproj index 133aa3292..0e4a25ae5 100644 --- a/GliaWidgets.xcodeproj/project.pbxproj +++ b/GliaWidgets.xcodeproj/project.pbxproj @@ -213,6 +213,8 @@ 31E35ABA2A8648E9006EC7FB /* Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31E35AB92A8648E9006EC7FB /* Localization.swift */; }; 31FF0DCB2B5907C600834AFB /* ChatCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31FF0DC92B5907C600834AFB /* ChatCoordinatorTests.swift */; }; 31FF0DCC2B5907C600834AFB /* ChatCoordinator.Environment.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31FF0DCA2B5907C600834AFB /* ChatCoordinator.Environment.Mock.swift */; }; + 31FF0DCF2B5A88F500834AFB /* CallCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31FF0DCE2B5A88F500834AFB /* CallCoordinatorTests.swift */; }; + 31FF0DD12B5A89A600834AFB /* CallCoordinator.Environment.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31FF0DD02B5A89A600834AFB /* CallCoordinator.Environment.Mock.swift */; }; 470A2A18BEAC7BE3FC48E99F /* Pods_TestingApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC2C9ED342FA5228B7E8BCEE /* Pods_TestingApp.framework */; }; 476B3340DAE8B9D71834B216 /* Pods_SnapshotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BF80688D6DD761AADD4A046 /* Pods_SnapshotTests.framework */; }; 540DA2E4F381F57717A466E8 /* Pods_GliaWidgetsTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B97A8A0B9AD30D0AB8666042 /* Pods_GliaWidgetsTests.framework */; }; @@ -1002,6 +1004,8 @@ 31E35AB92A8648E9006EC7FB /* Localization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localization.swift; sourceTree = ""; }; 31FF0DC92B5907C600834AFB /* ChatCoordinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatCoordinatorTests.swift; sourceTree = ""; }; 31FF0DCA2B5907C600834AFB /* ChatCoordinator.Environment.Mock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatCoordinator.Environment.Mock.swift; sourceTree = ""; }; + 31FF0DCE2B5A88F500834AFB /* CallCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallCoordinatorTests.swift; sourceTree = ""; }; + 31FF0DD02B5A89A600834AFB /* CallCoordinator.Environment.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallCoordinator.Environment.Mock.swift; sourceTree = ""; }; 6B2BFCE1274297F100B68506 /* SettingsSwitchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSwitchCell.swift; sourceTree = ""; }; 6B48213D2735873300F2900A /* Feature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feature.swift; sourceTree = ""; }; 6E60DD5527146C9D001422EF /* AlertViewController+SingleAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlertViewController+SingleAction.swift"; sourceTree = ""; }; @@ -2779,6 +2783,7 @@ 31FF0DC72B5907C600834AFB /* Coordinators */ = { isa = PBXGroup; children = ( + 31FF0DCD2B5A88E700834AFB /* Call */, 31FF0DC82B5907C600834AFB /* Chat */, ); name = Coordinators; @@ -2794,6 +2799,15 @@ path = Chat; sourceTree = ""; }; + 31FF0DCD2B5A88E700834AFB /* Call */ = { + isa = PBXGroup; + children = ( + 31FF0DCE2B5A88F500834AFB /* CallCoordinatorTests.swift */, + 31FF0DD02B5A89A600834AFB /* CallCoordinator.Environment.Mock.swift */, + ); + path = Call; + sourceTree = ""; + }; 69BB38CE6B54F4C95ED474B6 /* Pods */ = { isa = PBXGroup; children = ( @@ -5157,6 +5171,7 @@ 7512A57727BE8A6700319DF1 /* InteractorTests.swift in Sources */, AF29811529E6D76A0005BD55 /* FileDownloadTests.swift in Sources */, C096B40B297EBDE400F0C552 /* VisitorCodeTests.swift in Sources */, + 31FF0DD12B5A89A600834AFB /* CallCoordinator.Environment.Mock.swift in Sources */, 9ACC25D427B474E800BC5335 /* Glia.Environment.Failing.swift in Sources */, 9A8130C227D9095200220BBD /* FileDownload.Failing.swift in Sources */, 3189DD9429DEFAC600D68E9F /* SecureConversations.WelcomeViewModelSpec.swift in Sources */, @@ -5181,6 +5196,7 @@ 31D286AF2A00DE2B009192A6 /* SecureConversations.ConfirmationViewModel.Mock.swift in Sources */, 31B278012B55903C0021DEC1 /* SecureConversations.Coordinator.Environment.Mock.swift in Sources */, C0D2F06429A4B1E900803B47 /* VideoCallTests.swift in Sources */, + 31FF0DCF2B5A88F500834AFB /* CallCoordinatorTests.swift in Sources */, C03A8047292BA76D00DDECA6 /* ChatViewControllerTests.swift in Sources */, AF6291152B0818DE00D3D76B /* SwiftBased.Failing.swift in Sources */, EB9ADB552828E66B00FAE8A4 /* CallTests.swift in Sources */, diff --git a/GliaWidgets/Sources/ViewController/Call/CallViewController.swift b/GliaWidgets/Sources/ViewController/Call/CallViewController.swift index 6c6eabe33..5697e064a 100644 --- a/GliaWidgets/Sources/ViewController/Call/CallViewController.swift +++ b/GliaWidgets/Sources/ViewController/Call/CallViewController.swift @@ -1,7 +1,7 @@ import UIKit final class CallViewController: EngagementViewController { - private let viewModel: CallViewModel + let viewModel: CallViewModel private let environment: Environment init( diff --git a/GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinator.Environment.Mock.swift b/GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinator.Environment.Mock.swift new file mode 100644 index 000000000..724f54743 --- /dev/null +++ b/GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinator.Environment.Mock.swift @@ -0,0 +1,31 @@ +import Foundation +@testable import GliaWidgets + +extension CallCoordinator.Environment { + static let mock = Self( + fetchFile: { engagementFile, progress, completion in }, + downloadSecureFile: { file, progress, completion in .mock }, + uploadFileToEngagement: { file, progress, completion in }, + fileManager: .mock, + data: .mock, + date: { .mock }, + gcd: .mock, + createThumbnailGenerator: { .mock }, + createFileDownload: { file, storage, environment in .mock() }, + fromHistory: { false }, + fetchSiteConfigurations: { completion in }, + getCurrentEngagement: { .mock() }, + timerProviding: .mock, + submitSurveyAnswer: { answers, surveyId, engagementId, completion in }, + uuid: { .mock }, + uiApplication: .mock, + uiScreen: .mock, + notificationCenter: .mock, + fetchChatHistory: { completion in }, + createFileUploadListModel: { environment in .mock() }, + createSendMessagePayload: { content, attachment in .mock() }, + proximityManager: .mock, + log: .mock, + snackBar: .mock + ) +} diff --git a/GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinatorTests.swift b/GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinatorTests.swift new file mode 100644 index 000000000..f4a9a0151 --- /dev/null +++ b/GliaWidgetsTests/Sources/Coordinators/Call/CallCoordinatorTests.swift @@ -0,0 +1,156 @@ +import Foundation +import XCTest +@testable import GliaWidgets + +final class CallCoordinatorTests: XCTestCase { + var coordinator: CallCoordinator! + + override func setUpWithError() throws { + let offer = try CoreSdkClient.MediaUpgradeOffer( + type: .audio, + direction: .twoWay + ) + + let startAction = CallViewModel.StartAction.call( + offer: offer, + answer: { _, _ in } + ) + + coordinator = CallCoordinator( + interactor: .mock(), + viewFactory: .mock(), + navigationPresenter: NavigationPresenter(with: NavigationController()), + call: .mock(), + unreadMessages: .init(with: 0), + screenShareHandler: .mock, + startAction: startAction, + environment: .mock + ) + } + + func test_startGeneratesCallViewController() { + let viewController = coordinator.start() + + XCTAssertNotNil(viewController) + } + + // Delegate + + func test_delegateChat() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + coordinator.start().viewModel.delegate?(.chat) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .chat: XCTAssertTrue(true) + default: XCTFail() + } + } + + func test_delegateMinimize() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + coordinator.start().viewModel.delegate?(.minimize) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .minimize: XCTAssertTrue(true) + default: XCTFail() + } + } + + func test_delegateVisitorOnHoldUpdated() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + coordinator.start().viewModel.delegate?(.visitorOnHoldUpdated(isOnHold: true)) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .visitorOnHoldUpdated: XCTAssertTrue(true) + default: XCTFail() + } + } + + // Engagement delegate + + func test_engagementDelegateVisitorOnHoldUpdated() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + coordinator.start().viewModel.engagementDelegate?(.back) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .back: XCTAssertTrue(true) + default: XCTFail() + } + } + + func test_engagementDelegateOpenLink() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + let link: WebViewController.Link = (title: "", url: URL.mock) + coordinator.start().viewModel.engagementDelegate?(.openLink(link)) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .openLink(let openedLink): XCTAssertEqual(link.url, openedLink.url) + default: XCTFail() + } + } + + func test_engagementDelegateEngaged() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + coordinator.start().viewModel.engagementDelegate?( + .engaged(operatorImageUrl: URL.mock.absoluteString) + ) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .engaged(let operatorImageUrl): + XCTAssertEqual(URL.mock.absoluteString, operatorImageUrl) + default: XCTFail() + } + } + + func test_engagementDelegateFinished() throws { + var calledEvents: [CallCoordinator.DelegateEvent] = [] + + coordinator.delegate = { event in + calledEvents.append(event) + } + + coordinator.start().viewModel.engagementDelegate?(.finished) + + XCTAssertEqual(calledEvents.count, 1) + switch try XCTUnwrap(calledEvents.first) { + case .finished: XCTAssertTrue(true) + default: XCTFail() + } + } +}