Skip to content

Commit

Permalink
Add tests for Secure Conversations coordinator
Browse files Browse the repository at this point in the history
Correct actions and creation of view controllers in the coordinator has been
covered with unit tests.

MOB-2914
  • Loading branch information
gersonnoboa authored and rasmustautsglia committed Jan 17, 2024
1 parent 0f193c7 commit 223b1bf
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 4 deletions.
20 changes: 20 additions & 0 deletions GliaWidgets.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
3100EEFD293F757E00D57F71 /* SecureConversations.WelcomeStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3100EEFC293F757E00D57F71 /* SecureConversations.WelcomeStyle.swift */; };
3100EEFF293F7E0900D57F71 /* Theme+SecureConversationsWelcome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3100EEFE293F7E0900D57F71 /* Theme+SecureConversationsWelcome.swift */; };
3115D45C29A4FD3F00D99561 /* SecureConversations.Availability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3115D45B29A4FD3F00D99561 /* SecureConversations.Availability.swift */; };
311C03352B5588C0002E4FF8 /* SecureConversations.CoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 311C03342B5588C0002E4FF8 /* SecureConversations.CoordinatorTests.swift */; };
311CAFCD29F8FAE20067B59F /* SecureConversations.TranscriptModel+CustomCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 311CAFCC29F8FAE20067B59F /* SecureConversations.TranscriptModel+CustomCard.swift */; };
313EBD552943116E008E9597 /* SecureConversations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 313EBD542943116E008E9597 /* SecureConversations.swift */; };
3142696A29FFB712003DF62E /* Interactor.Failing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3142696929FFB712003DF62E /* Interactor.Failing.swift */; };
Expand All @@ -199,6 +200,8 @@
3197F7B629F7C2E5008EE9F7 /* SecureConversations.SecureChatModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3197F7B529F7C2E5008EE9F7 /* SecureConversations.SecureChatModel.swift */; };
3197F7B829F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3197F7B729F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift */; };
31B1F8A92AB093ED009EC5AD /* StringProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B1F8A82AB093ED009EC5AD /* StringProviding.swift */; };
31B278012B55903C0021DEC1 /* SecureConversations.Coordinator.Environment.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B278002B55903C0021DEC1 /* SecureConversations.Coordinator.Environment.Mock.swift */; };
31B278032B55BE670021DEC1 /* SecureConversations.WelcomeViewController.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31B278022B55BE670021DEC1 /* SecureConversations.WelcomeViewController.Mock.swift */; };
31CA0F6A2AE6947500A55685 /* CallVisualizer.Environment.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75940978298D38C2008B173A /* CallVisualizer.Environment.Mock.swift */; };
31CA0F6B2AE6947800A55685 /* CallVisualizer.VisitorCodeViewModel.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75940979298D38C2008B173A /* CallVisualizer.VisitorCodeViewModel.Mock.swift */; };
31CA0F6C2AE6947D00A55685 /* ScreenSharingViewModel.mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62802AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift */; };
Expand Down Expand Up @@ -967,6 +970,7 @@
3100EEFC293F757E00D57F71 /* SecureConversations.WelcomeStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.WelcomeStyle.swift; sourceTree = "<group>"; };
3100EEFE293F7E0900D57F71 /* Theme+SecureConversationsWelcome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Theme+SecureConversationsWelcome.swift"; sourceTree = "<group>"; };
3115D45B29A4FD3F00D99561 /* SecureConversations.Availability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.Availability.swift; sourceTree = "<group>"; };
311C03342B5588C0002E4FF8 /* SecureConversations.CoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.CoordinatorTests.swift; sourceTree = "<group>"; };
311CAFCC29F8FAE20067B59F /* SecureConversations.TranscriptModel+CustomCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SecureConversations.TranscriptModel+CustomCard.swift"; sourceTree = "<group>"; };
313EBD542943116E008E9597 /* SecureConversations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.swift; sourceTree = "<group>"; };
3142696929FFB712003DF62E /* Interactor.Failing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interactor.Failing.swift; sourceTree = "<group>"; };
Expand All @@ -985,6 +989,8 @@
3197F7B529F7C2E5008EE9F7 /* SecureConversations.SecureChatModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.SecureChatModel.swift; sourceTree = "<group>"; };
3197F7B729F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.CommonEngagementModel.swift; sourceTree = "<group>"; };
31B1F8A82AB093ED009EC5AD /* StringProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringProviding.swift; sourceTree = "<group>"; };
31B278002B55903C0021DEC1 /* SecureConversations.Coordinator.Environment.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.Coordinator.Environment.Mock.swift; sourceTree = "<group>"; };
31B278022B55BE670021DEC1 /* SecureConversations.WelcomeViewController.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.WelcomeViewController.Mock.swift; sourceTree = "<group>"; };
31D286AC2A00DD2C009192A6 /* SecureConversations.ConfirmationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.ConfirmationViewModelTests.swift; sourceTree = "<group>"; };
31D286AE2A00DE2B009192A6 /* SecureConversations.ConfirmationViewModel.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.ConfirmationViewModel.Mock.swift; sourceTree = "<group>"; };
31DB0C00287C2EFC00FB288E /* StaticValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticValues.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2724,6 +2730,7 @@
children = (
3189DD9329DEFAC600D68E9F /* SecureConversations.WelcomeViewModelSpec.swift */,
3189DD9529E4331200D68E9F /* SecureConversations.WelcomeViewModel.Mock.swift */,
31B278022B55BE670021DEC1 /* SecureConversations.WelcomeViewController.Mock.swift */,
);
path = Welcome;
sourceTree = "<group>";
Expand All @@ -2744,6 +2751,15 @@
path = ChatTranscript;
sourceTree = "<group>";
};
31B277FF2B558F010021DEC1 /* Coordinator */ = {
isa = PBXGroup;
children = (
311C03342B5588C0002E4FF8 /* SecureConversations.CoordinatorTests.swift */,
31B278002B55903C0021DEC1 /* SecureConversations.Coordinator.Environment.Mock.swift */,
);
path = Coordinator;
sourceTree = "<group>";
};
31D286AB2A00DA5F009192A6 /* Confirmation */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -3687,6 +3703,7 @@
AFEF5C7229929A73005C3D8D /* SecureConversations */ = {
isa = PBXGroup;
children = (
31B277FF2B558F010021DEC1 /* Coordinator */,
31D286AB2A00DA5F009192A6 /* Confirmation */,
3142696829FFB4ED003DF62E /* ChatTranscript */,
3189DD9229DEF62600D68E9F /* Welcome */,
Expand Down Expand Up @@ -5095,8 +5112,10 @@
84D5B9662A15204400807F92 /* QuickLookBased.Failing.swift in Sources */,
84602A772AEA5BEA0031E606 /* ProximityManager.Failing.swift in Sources */,
753B05F82AFC1D750084611E /* SerialQueueTests.swift in Sources */,
31B278032B55BE670021DEC1 /* SecureConversations.WelcomeViewController.Mock.swift in Sources */,
84681A982A61853300DD7406 /* GvaOption.Mock.swift in Sources */,
AF6AB34B2989517100003645 /* FileUploader.Failing.swift in Sources */,
311C03352B5588C0002E4FF8 /* SecureConversations.CoordinatorTests.swift in Sources */,
EB03B00E27FFF6DD0058F6B1 /* CallViewTests.swift in Sources */,
8491AF552AA0934A00CC3E72 /* GVA.Mock.swift in Sources */,
3197F7AD29E6A5C8008EE9F7 /* SecureConversations.FileUploadListView.Mock.swift in Sources */,
Expand Down Expand Up @@ -5126,6 +5145,7 @@
9A1992E127D6313500161AAE /* ImageView.Cache.Failing.swift in Sources */,
3189DD9629E4331200D68E9F /* SecureConversations.WelcomeViewModel.Mock.swift in Sources */,
31D286AF2A00DE2B009192A6 /* SecureConversations.ConfirmationViewModel.Mock.swift in Sources */,
31B278012B55903C0021DEC1 /* SecureConversations.Coordinator.Environment.Mock.swift in Sources */,
C0D2F06429A4B1E900803B47 /* VideoCallTests.swift in Sources */,
C03A8047292BA76D00DDECA6 /* ChatViewControllerTests.swift in Sources */,
AF6291152B0818DE00D3D76B /* SwiftBased.Failing.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ extension SecureConversations {
private let viewFactory: ViewFactory
private let navigationPresenter: NavigationPresenter
private let environment: Environment
private var viewModel: SecureConversations.WelcomeViewModel?
private var selectedPickerController: SelectedPickerController?
private(set) var viewModel: SecureConversations.WelcomeViewModel?
private(set) var selectedPickerController: SelectedPickerController?
private var messagingInitialScreen: SecureConversations.InitialScreen

init(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ final class FilePickerController: NSObject {
documentPicker.modalPresentationStyle = .fullScreen
viewModel.environment.log.prefixed(Self.self).info(
"Create File Preview screen",
function: "\(\Self.viewController)"
function: "\(\FilePickerController.viewController)"
)
return documentPicker
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import UIKit
import AVFoundation

final class MediaPickerController: NSObject {
private let viewModel: MediaPickerViewModel
let viewModel: MediaPickerViewModel

private var viewController: UIImagePickerController {
let source = UIImagePickerController.SourceType(with: viewModel.source)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Foundation
@testable import GliaWidgets

extension SecureConversations.Coordinator.Environment {
static let mock = Self(
queueIds: [],
listQueues: { completion in },
sendSecureMessagePayload: { secureMessagePayload, queueIds, completion in .mock },
createFileUploader: { maximumUploads, environment in .mock() },
uploadSecureFile: { file, progress, completion in .mock },
fileManager: .mock,
data: .mock,
date: { .mock },
gcd: .mock,
createThumbnailGenerator: { .mock },
uuid: { .mock },
uiApplication: .mock,
uiScreen: .mock,
notificationCenter: .mock,
createFileUploadListModel: { environment in .mock() },
viewFactory: .mock(),
fetchFile: { engagementFile, progress, completion in },
createFileDownload: { file, storage, environment in .mock() },
loadChatMessagesFromHistory: { true },
fetchChatHistory: { completion in },
fetchSiteConfigurations: { completion in },
chatCall: .init(with: .mock()),
unreadMessages: .init(with: 0),
showsCallBubble: true,
screenShareHandler: .mock,
isWindowVisible: .init(with: true),
uploadFileToEngagement: { file, progress, completion in },
getCurrentEngagement: { .mock() },
submitSurveyAnswer: { answers, surveyId, engagementId, completion in },
interactor: .mock(),
getSecureUnreadMessageCount: { callback in },
messagesWithUnreadCountLoaderScheduler: CoreSdkClient.reactiveSwiftDateSchedulerMock,
secureMarkMessagesAsRead: { callback in .mock },
downloadSecureFile: { file, progress, completion in .mock },
isAuthenticated: { true },
startSocketObservation: { },
stopSocketObservation: { },
createSendMessagePayload: { content, attachment in .mock() },
orientationManager: .mock(),
proximityManager: .mock,
log: .mock,
timerProviding: .mock,
snackBar: SnackBar(
present: { text, style, viewController, bottomOffset, timerProviding, gcd, notificationCenter in
}
)
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import Foundation
import XCTest
@testable import GliaWidgets

final class SecureConversationsCoordinatorTests: XCTestCase {
var navigationPresenter = NavigationPresenter(with: NavigationController())
var coordinator: SecureConversations.Coordinator!

override func setUp() {
coordinator = createCoordinator()
}

func createCoordinator(
initialScreen: SecureConversations.InitialScreen = .welcome
) -> SecureConversations.Coordinator {
return SecureConversations.Coordinator(
messagingInitialScreen: initialScreen,
viewFactory: .mock(),
navigationPresenter: navigationPresenter,
environment: .mock
)
}

// Start
func test_startGeneratesWelcomeViewController() {
let viewController = coordinator.start() as? SecureConversations.WelcomeViewController

XCTAssertNotNil(viewController)
}

func test_startGeneratesChatViewController() {
let coordinator = createCoordinator(initialScreen: .chatTranscript)
let viewController = coordinator.start() as? ChatViewController

XCTAssertNotNil(viewController)
}

// Delegate
func test_backTapped() {
coordinator.delegate = { event in
switch event {
case .backTapped: XCTAssertTrue(true)
default: XCTFail()
}
}

coordinator.viewModel?.delegate?(.backTapped)
}

func test_closeTapped() {
coordinator.delegate = { event in
switch event {
case .closeTapped(let presentation):
XCTAssertEqual(presentation, .doNotPresentSurvey)
default: XCTFail()
}
}

coordinator.viewModel?.delegate?(.backTapped)
}

func test_renderProps() throws {
let welcomeViewController = try XCTUnwrap(coordinator.start() as? SecureConversations.WelcomeViewController)
coordinator.viewModel?.delegate?(.renderProps(.mock))

XCTAssertEqual(.mock, welcomeViewController.props)
}

func test_confirmationScreenRequested() {
_ = coordinator.start()
coordinator.viewModel?.delegate?(.confirmationScreenRequested)
let confirmationViewController = navigationPresenter.viewControllers
.last as? SecureConversations.ConfirmationViewController

XCTAssertNotNil(confirmationViewController)
}

func test_mediaPickerRequested() throws {
let welcomeViewController = try XCTUnwrap(coordinator.start() as? SecureConversations.WelcomeViewController)
let scene = try XCTUnwrap(UIApplication.shared.connectedScenes.first as? UIWindowScene)
let window = scene.windows.first
let oldRootViewController = window?.rootViewController
window?.rootViewController = welcomeViewController
defer { window?.rootViewController = oldRootViewController }
coordinator.viewModel?.delegate?(
.mediaPickerRequested(
from: welcomeViewController.view,
callback: { _ in }
)
)
let presentedViewController = welcomeViewController.presentedViewController as? PopoverViewController

XCTAssertNotNil(presentedViewController)
}

// Take media is not tested because this triggers the native
// "App would like to access the camera" dialog, which could
// bring unintended consequences.
func test_pickMedia() {
_ = coordinator.start()

XCTAssertNil(coordinator.selectedPickerController)

coordinator.viewModel?.delegate?(.pickMedia(.nop))
XCTAssertNotNil(coordinator.selectedPickerController)

switch coordinator.selectedPickerController {
case .mediaPickerController(let controller):
XCTAssertEqual(controller.viewModel.source, .library)
default: XCTFail()
}
}

func test_pickFile() {
_ = coordinator.start()

XCTAssertNil(coordinator.selectedPickerController)

coordinator.viewModel?.delegate?(.pickFile(.nop))
XCTAssertNotNil(coordinator.selectedPickerController)

switch coordinator.selectedPickerController {
case .filePickerController: XCTAssertTrue(true)
default: XCTFail()
}
}

func test_showAlert() throws {
let welcomeViewController = try XCTUnwrap(coordinator.start() as? SecureConversations.WelcomeViewController)
let scene = try XCTUnwrap(UIApplication.shared.connectedScenes.first as? UIWindowScene)
let window = scene.windows.first
let oldRootViewController = window?.rootViewController
window?.rootViewController = welcomeViewController
defer { window?.rootViewController = oldRootViewController }

let configuration = MessageAlertConfiguration(
title: "",
message: ""
)
coordinator.viewModel?.delegate?(
.showAlert(
configuration,
accessibilityIdentifier: nil,
dismissed: nil
)
)

let presentedViewController = welcomeViewController.presentedViewController as? AlertViewController

XCTAssertNotNil(presentedViewController)
}

func test_showAlertAsView() throws {
let welcomeViewController = try XCTUnwrap(coordinator.start() as? SecureConversations.WelcomeViewController)
let scene = try XCTUnwrap(UIApplication.shared.connectedScenes.first as? UIWindowScene)
let window = scene.windows.first
let oldRootViewController = window?.rootViewController
window?.rootViewController = welcomeViewController
defer { window?.rootViewController = oldRootViewController }

let configuration = MessageAlertConfiguration(
title: "",
message: ""
)
coordinator.viewModel?.delegate?(
.showAlertAsView(
configuration,
accessibilityIdentifier: nil,
dismissed: nil
)
)

let presentedViewController = welcomeViewController.children.first { $0 is AlertViewController }

XCTAssertNotNil(presentedViewController)
}

func test_showSettingsAlert() throws {
let welcomeViewController = try XCTUnwrap(coordinator.start() as? SecureConversations.WelcomeViewController)
let scene = try XCTUnwrap(UIApplication.shared.connectedScenes.first as? UIWindowScene)
let window = scene.windows.first
let oldRootViewController = window?.rootViewController
window?.rootViewController = welcomeViewController
defer { window?.rootViewController = oldRootViewController }

let configuration = SettingsAlertConfiguration(
title: "",
message: "",
settingsTitle: "",
cancelTitle: ""
)
coordinator.viewModel?.delegate?(
.showSettingsAlert(
configuration,
cancelled: { }
)
)

let presentedViewController = welcomeViewController.presentedViewController as? UIAlertController

XCTAssertNotNil(presentedViewController)
}

func test_transcriptRequested() {
_ = coordinator.start()
coordinator.viewModel?.delegate?(.transcriptRequested)
let transcriptViewController = navigationPresenter.viewControllers
.last as? ChatViewController

XCTAssertNotNil(transcriptViewController)
}
}
Loading

0 comments on commit 223b1bf

Please sign in to comment.