Skip to content

Commit

Permalink
Fix ending CV engagement
Browse files Browse the repository at this point in the history
Previously if WidgetsSDK is configured one time and then visitor has regular engagement, then CV engagement with screen sharing, if the operator ends CV engagement, bubble and screen sharing state is still displayed. It happened because EngagementViewModel called interator.endSession which set `isEngagementEndedByVisitor` to `true` even in case if engagement is ended by operator. Since CV engagement is started without additional `configure` call, interactor keeps  `isEngagementEndedByVisitor` as `true`, which was broking CV flow.
This commit fixes it.

MOB-2731
  • Loading branch information
Egor Egorov committed Oct 12, 2023
1 parent 11d6a09 commit 200fbf0
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 5 deletions.
2 changes: 1 addition & 1 deletion GliaWidgets/Public/Glia/Glia.swift
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ extension Glia {
case let .videoStreamAdded(stream):
self?.callVisualizer.addVideoStream(stream: stream)
case let .stateChanged(state):
if state == .ended(.byOperator) {
if case .ended = state {
self?.callVisualizer.endSession()
self?.onEvent?(.ended)
} else if case .engaged = state {
Expand Down
2 changes: 1 addition & 1 deletion GliaWidgets/Sources/Interactor/Interactor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class Interactor {
var isConfigurationPerformed: Bool = false

private var observers = [() -> (AnyObject?, EventHandler)]()
private var isEngagementEndedByVisitor = false
private(set) var isEngagementEndedByVisitor = false

var state: InteractorState = .none {
didSet {
Expand Down
9 changes: 6 additions & 3 deletions GliaWidgets/Sources/ViewModel/EngagementViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class EngagementViewModel: CommonEngagementModel {
self.alertConfiguration.operatorEndedEngagement,
accessibilityIdentifier: Self.alertSingleActionAccessibilityIdentifier,
actionTapped: { [weak self] in
self?.endSession()
self?.screenShareHandler.stop(nil)
self?.engagementDelegate?(.finished)
}
)
)
Expand Down Expand Up @@ -144,7 +145,8 @@ class EngagementViewModel: CommonEngagementModel {

guard let self = self else { return }
guard case .success(let survey) = result, survey == nil else {
self.endSession()
self.screenShareHandler.stop(nil)
self.engagementDelegate?(.finished)
return
}

Expand All @@ -153,7 +155,8 @@ class EngagementViewModel: CommonEngagementModel {
self.alertConfiguration.operatorEndedEngagement,
accessibilityIdentifier: Self.alertSingleActionAccessibilityIdentifier,
actionTapped: { [weak self] in
self?.endSession()
self?.screenShareHandler.stop(nil)
self?.engagementDelegate?(.finished)
self?.engagementDelegate?(
.engaged(
operatorImageUrl: nil
Expand Down
84 changes: 84 additions & 0 deletions GliaWidgetsTests/Sources/ChatViewModel/ChatViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,90 @@ class ChatViewModelTests: XCTestCase {
XCTAssertEqual(viewModel.messagesSection.items.count, 0)
XCTAssertEqual(viewModel.receivedMessageIds, [])
}

func test_viewModelDoesNotCallEndSessionWhenEngagementIsEndedByOperatorAndSurveyExists() throws {
enum Call { case finished }
var calls: [Call] = []
var interactorEnv = Interactor.Environment.mock
let data = try JSONSerialization.data(withJSONObject: [
"id": "mock",
"description": "mock",
"name": "mock",
"title": "mock",
"type": "visitor",
"siteId": "mock",
"questions": []
])
let survey = try JSONDecoder().decode(CoreSdkClient.Survey.self, from: data)
let engagement: CoreSdkClient.Engagement = .mock { _, callback in
callback(.success(survey))
}
let interactor: Interactor = .mock(environment: interactorEnv)
interactor.state = .engaged(.mock())
interactor.currentEngagement = engagement
let screenShareHandler: ScreenShareHandler = .mock
screenShareHandler.status().value = .started
let viewModel: ChatViewModel = .mock(
interactor: interactor,
screenShareHandler: screenShareHandler
)
viewModel.engagementDelegate = { event in
switch event {
case .finished:
calls.append(.finished)
default:
XCTFail("There is should not be other events")
}
}

interactor.state = .ended(.byOperator)

XCTAssertEqual(screenShareHandler.status().value, .stopped)
XCTAssertEqual(calls, [.finished])
XCTAssertFalse(interactor.isEngagementEndedByVisitor)
}

func test_viewModelDoesNotCallEndSessionWhenEngagementIsEndedByOperatorAndThereIsNoSurvey() throws {
enum Call: Equatable { case finished, engaged(String?) }
var calls: [Call] = []
var interactorEnv = Interactor.Environment.mock
let engagement: CoreSdkClient.Engagement = .mock { _, callback in callback(.success(nil)) }
let interactor: Interactor = .mock(environment: interactorEnv)
interactor.state = .engaged(.mock())
interactor.currentEngagement = engagement
let screenShareHandler: ScreenShareHandler = .mock
screenShareHandler.status().value = .started
let viewModel: ChatViewModel = .mock(
interactor: interactor,
screenShareHandler: screenShareHandler
)
viewModel.engagementDelegate = { event in
switch event {
case .finished:
calls.append(.finished)
case let .engaged(operatorImage):
// This is called after ending engagement to reset bubble avatar
calls.append(.engaged(operatorImage))
case .back:
XCTFail("There is should be `back` event")
}
}

viewModel.engagementAction = { action in
switch action {
case let .showSingleActionAlert(_, _, actionTapped):
actionTapped?()
default:
XCTFail("There is should be no another action")
}
}

interactor.state = .ended(.byOperator)

XCTAssertEqual(screenShareHandler.status().value, .stopped)
XCTAssertEqual(calls, [.finished, .engaged(nil)])
XCTAssertFalse(interactor.isEngagementEndedByVisitor)
}
}

extension ChatChoiceCardOption {
Expand Down
26 changes: 26 additions & 0 deletions GliaWidgetsTests/Sources/Glia/GliaTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,30 @@ final class GliaTests: XCTestCase {
XCTAssertEqual(delegate.invokedEventCallParameter, .maximized)
XCTAssertEqual(delegate.invokedEventCallParameterList, [.maximized])
}

func test_screenSharingIsStoppedWhenCallVisualizerEngagementIsEnded() throws {
enum Call { case ended }
var calls: [Call] = []
var gliaEnv = Glia.Environment.failing
let screenShareHandler: ScreenShareHandler = .mock
screenShareHandler.status().value = .started
gliaEnv.screenShareHandler = screenShareHandler
gliaEnv.gcd.mainQueue.asyncIfNeeded = { callback in callback() }
let sdk = Glia(environment: gliaEnv)
try sdk.configure(with: .mock())

sdk.environment.coreSdk.getCurrentEngagement = { .mock(source: .callVisualizer) }
sdk.onEvent = { event in
switch event {
case .ended:
calls.append(.ended)
default:
XCTFail("There is should be no another event")
}
}
sdk.interactor?.state = .ended(.byVisitor)

XCTAssertEqual(screenShareHandler.status().value, .stopped)
XCTAssertEqual(calls, [.ended])
}
}

0 comments on commit 200fbf0

Please sign in to comment.