Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create PendingInteraction model after configuration #1148

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion GliaWidgets/Public/Glia/Glia+EngagementSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ extension Glia {
) {
let engagementLaunching: EngagementCoordinator.EngagementLaunching

switch (pendingInteraction.hasPendingInteraction, engagementKind) {
switch (pendingInteraction?.hasPendingInteraction ?? false, engagementKind) {
case (false, _):
// if there is no pending Secure Conversation, open regular flow.
engagementLaunching = .direct(kind: engagementKind)
Expand Down
2 changes: 1 addition & 1 deletion GliaWidgets/Public/Glia/Glia+EntryWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extension Glia {
isAuthenticated: environment.isAuthenticated,
hasPendingInteraction: { [weak self] in
guard let self else { return false }
return pendingInteraction.hasPendingInteraction
return pendingInteraction?.hasPendingInteraction ?? false
}
)
)
Expand Down
19 changes: 16 additions & 3 deletions GliaWidgets/Public/Glia/Glia.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
//
// Currently it's used to know if we have to force a visitor to SecureMessaging screen,
// once they try to start an engagement with media type other than `messaging`.
let pendingInteraction: SecureConversations.PendingInteraction
var pendingInteraction: SecureConversations.PendingInteraction?

init(environment: Environment) {
self.environment = environment
Expand Down Expand Up @@ -179,7 +179,6 @@
viewFactory: viewFactory
)
)
pendingInteraction = .init(environment: .init(with: environment.coreSdk))
}

/// Setup SDK using specific engagement configuration without starting the engagement.
Expand All @@ -196,7 +195,7 @@
/// - `GliaError.configuringDuringEngagementIsNotAllowed`
/// - `ConfigurationError`
///
public func configure(

Check warning on line 198 in GliaWidgets/Public/Glia/Glia.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Cyclomatic Complexity Violation: Function should have complexity 10 or less; currently complexity is 11 (cyclomatic_complexity)

Check warning on line 198 in GliaWidgets/Public/Glia/Glia.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Function Body Length Violation: Function body should span 60 lines or less excluding comments and whitespace: currently spans 75 lines (function_body_length)
with configuration: Configuration,
theme: Theme = Theme(),
uiConfig: RemoteConfiguration? = nil,
Expand Down Expand Up @@ -258,7 +257,21 @@

// Configuration completion handler has to be called in any case,
// at the end of the scope, whether there's ongoing engagement or not.
defer { completion(.success(())) }
defer {
// PendingInteraction is essential part of SC flow, so it's not
// valid to consider SDK configured if PI is not created.
do {
pendingInteraction = try .init(environment: .init(with: environment.coreSdk))
completion(.success(()))
} catch let error as SecureConversations.PendingInteraction.Error {
switch error {
case .subscriptionFailure:
completion(.failure(GliaError.internalEventSubscriptionFailure))
}
} catch {
completion(.failure(GliaError.internalError))
}
}

guard let currentEngagement = self.environment.coreSdk.getCurrentEngagement() else { return }

Expand Down
3 changes: 3 additions & 0 deletions GliaWidgets/Public/GliaError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@ public enum GliaError: Error {

/// Internal error.
case internalError

/// Internal event subscription failure.
case internalEventSubscriptionFailure
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,34 @@ extension SecureConversations {
private(set) var pendingStatusCancellationToken: String?
EgorovEI marked this conversation as resolved.
Show resolved Hide resolved
private(set) var unreadMessageCountCancellationToken: String?

init(environment: Environment) {
init(environment: Environment) throws {
self.environment = environment
self.pendingStatusCancellationToken = environment.observePendingSecureConversationsStatus { [weak self] result in
let pendingStatusCancellationToken = environment.observePendingSecureConversationsStatus { [weak self] result in
guard let self else { return }
// At this point it is enough to know if there is a pending conversation,
// so no need to handle error.
pendingStatus = (try? result.get()) ?? false
}
self.unreadMessageCountCancellationToken = environment.observeSecureConversationsUnreadMessageCount { [weak self] result in

guard pendingStatusCancellationToken != nil else {
throw Error.subscriptionFailure(.pendingStatus)
}

self.pendingStatusCancellationToken = pendingStatusCancellationToken

let unreadMessageCountCancellationToken = environment.observeSecureConversationsUnreadMessageCount { [weak self] result in
guard let self else { return }
// At this point it is enough to know if there is an unread message count,
// so no need to handle error.
unreadMessageCount = (try? result.get()) ?? 0
}

guard unreadMessageCountCancellationToken != nil else {
throw Error.subscriptionFailure(.unreadMessageCount)
}

self.unreadMessageCountCancellationToken = unreadMessageCountCancellationToken

$pendingStatus.combineLatest($unreadMessageCount)
.map { hasPending, unreadCount in
hasPending || unreadCount > 0
Expand Down Expand Up @@ -52,6 +65,16 @@ extension SecureConversations.PendingInteraction {
}
}

extension SecureConversations.PendingInteraction {
enum Error: Swift.Error {
enum Subscription {
case unreadMessageCount
case pendingStatus
}
case subscriptionFailure(Subscription)
}
}

extension SecureConversations.PendingInteraction.Environment {
init(with client: CoreSdkClient) {
self.observePendingSecureConversationsStatus = client.observePendingSecureConversationStatus
Expand All @@ -63,17 +86,20 @@ extension SecureConversations.PendingInteraction.Environment {

#if DEBUG
extension SecureConversations.PendingInteraction.Environment {
static let mock = Self(
observePendingSecureConversationsStatus: { _ in nil },
observeSecureConversationsUnreadMessageCount: { _ in nil },
unsubscribeFromUnreadCount: { _ in },
unsubscribeFromPendingStatus: { _ in }
)
static let mock: Self = {
let uuidGen = UUID.incrementing
return Self(
observePendingSecureConversationsStatus: { _ in uuidGen().uuidString },
observeSecureConversationsUnreadMessageCount: { _ in uuidGen().uuidString },
unsubscribeFromUnreadCount: { _ in },
unsubscribeFromPendingStatus: { _ in }
)
}()
}

extension SecureConversations.PendingInteraction {
static func mock(environment: Environment = .mock) -> Self {
.init(environment: environment)
static func mock(environment: Environment = .mock) throws -> Self {
try .init(environment: environment)
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension SecureConversations.PendingInteraction.Environment {
}

extension SecureConversations.PendingInteraction {
static func failing() -> Self {
.init(environment: .failing)
static func failing() throws -> Self {
try .init(environment: .failing)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class SecureConversationsPendingInteractionTests: XCTestCase {
environment.unsubscribeFromPendingStatus = { _ in }
environment.unsubscribeFromUnreadCount = { _ in }

let pendingInteraction = SecureConversations.PendingInteraction(environment: environment)
let pendingInteraction = try SecureConversations.PendingInteraction(environment: environment)
// Assert initial pending interaction is false.
XCTAssertFalse(pendingInteraction.hasPendingInteraction)
// Affect pending secure conversations value by setting it to `true` and assert `hasPendingInteraction`,
Expand All @@ -36,7 +36,7 @@ final class SecureConversationsPendingInteractionTests: XCTestCase {
XCTAssertFalse(pendingInteraction.hasPendingInteraction)
}

func test_unsubscribeIsCalledOnDeinit() {
func test_unsubscribeIsCalledOnDeinit() throws {
enum Call {
case unsubscribeFromPendingStatus
case unsubscribeFromUnreadCount
Expand All @@ -52,8 +52,8 @@ final class SecureConversationsPendingInteractionTests: XCTestCase {
environment.unsubscribeFromUnreadCount = { _ in
calls.append(.unsubscribeFromUnreadCount)
}
var pendingInteraction = SecureConversations.PendingInteraction(environment: environment)
pendingInteraction = .mock()
var pendingInteraction = try SecureConversations.PendingInteraction(environment: environment)
pendingInteraction = try .mock()
_ = pendingInteraction
XCTAssertEqual(calls, [.unsubscribeFromUnreadCount, .unsubscribeFromPendingStatus])
}
Expand Down
50 changes: 42 additions & 8 deletions GliaWidgetsTests/Sources/Glia/GliaTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,12 @@ final class GliaTests: XCTestCase {
XCTAssertEqual(messages, ["Initialize Glia Widgets SDK", "Setting Unified UI Config"])
}

func test_hasPendingInteractionIfPendingSecureConversationExists() {
func test_hasPendingInteractionIfPendingSecureConversationExists() throws {
var gliaEnv = Glia.Environment.failing
var logger = CoreSdkClient.Logger.failing
let uuidGen = UUID.incrementing
logger.infoClosure = { _, _, _, _ in }
logger.prefixedClosure = { _ in logger }
logger.configureLocalLogLevelClosure = { _ in }
logger.configureRemoteLogLevelClosure = { _ in }
gliaEnv.coreSdk.createLogger = { _ in logger }
Expand All @@ -765,18 +767,28 @@ final class GliaTests: XCTestCase {
}
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
gliaEnv.coreSDKConfigurator.configureWithConfiguration = { _, completion in
completion(.success(()))
}
gliaEnv.coreSDKConfigurator.configureWithInteractor = { _ in }

let sdk = Glia(environment: gliaEnv)
try sdk.configure(
with: .mock(),
theme: .mock()
) { _ in }

XCTAssertTrue(sdk.pendingInteraction.hasPendingInteraction)
XCTAssertTrue(try XCTUnwrap(sdk.pendingInteraction).hasPendingInteraction)
}

func test_hasPendingInteractionIfUnreadMessagesExist() {
func test_hasPendingInteractionIfUnreadMessagesExist() throws {
var gliaEnv = Glia.Environment.failing
var logger = CoreSdkClient.Logger.failing
let uuidGen = UUID.incrementing
logger.configureLocalLogLevelClosure = { _ in }
logger.configureRemoteLogLevelClosure = { _ in }
logger.infoClosure = { _, _, _, _ in }
logger.prefixedClosure = { _ in logger }
gliaEnv.coreSdk.createLogger = { _ in logger }
gliaEnv.conditionalCompilation.isDebug = { true }
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { callback in
Expand All @@ -789,28 +801,50 @@ final class GliaTests: XCTestCase {
}
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
gliaEnv.coreSDKConfigurator.configureWithConfiguration = { _, completion in
completion(.success(()))
}
gliaEnv.coreSDKConfigurator.configureWithInteractor = { _ in }

let sdk = Glia(environment: gliaEnv)

XCTAssertTrue(sdk.pendingInteraction.hasPendingInteraction)
try sdk.configure(
with: .mock(),
theme: .mock()
) { _ in }

XCTAssertTrue(try XCTUnwrap(sdk.pendingInteraction).hasPendingInteraction)
}

func test_hasPendingInteractionIfNoUnreadMessageAndPendingSecureConversationExist() {
func test_hasPendingInteractionIfNoUnreadMessageAndPendingSecureConversationExist() throws {
var uuidGen = UUID.incrementing
var gliaEnv = Glia.Environment.failing
var logger = CoreSdkClient.Logger.failing
logger.configureLocalLogLevelClosure = { _ in }
logger.configureRemoteLogLevelClosure = { _ in }
logger.configureRemoteLogLevelClosure = { _ in }
logger.infoClosure = { _, _, _, _ in }
logger.prefixedClosure = { _ in logger }
gliaEnv.coreSdk.createLogger = { _ in logger }
gliaEnv.coreSdk.pendingSecureConversationStatus = { $0(.success(false)) }
gliaEnv.coreSdk.getSecureUnreadMessageCount = { $0(.success(0)) }
gliaEnv.conditionalCompilation.isDebug = { true }
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in uuidGen().uuidString }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in uuidGen().uuidString }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
gliaEnv.coreSDKConfigurator.configureWithConfiguration = { _, completion in
completion(.success(()))
}
gliaEnv.coreSDKConfigurator.configureWithInteractor = { _ in }

let sdk = Glia(environment: gliaEnv)

XCTAssertFalse(sdk.pendingInteraction.hasPendingInteraction)
try sdk.configure(
with: .mock(),
theme: .mock()
) { _ in }

XCTAssertFalse(try XCTUnwrap(sdk.pendingInteraction).hasPendingInteraction)
}
}
Loading