From edcd7765e3388ba4d16424a2c798149d09b4b15c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 28 Jun 2024 07:12:41 -0500 Subject: [PATCH] chore: dismiss message when close button pressed (#734) --- .../Gist/Managers/InlineMessageManager.swift | 3 +- .../Gist/Managers/MessageManager.swift | 1 + .../Views/InAppMessageView.swift | 6 +++ .../Views/InAppMessageViewTest.swift | 42 +++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Sources/MessagingInApp/Gist/Managers/InlineMessageManager.swift b/Sources/MessagingInApp/Gist/Managers/InlineMessageManager.swift index 552647189..dd475f4a4 100644 --- a/Sources/MessagingInApp/Gist/Managers/InlineMessageManager.swift +++ b/Sources/MessagingInApp/Gist/Managers/InlineMessageManager.swift @@ -3,6 +3,7 @@ import Foundation // Callbacks specific to inline message events. protocol InlineMessageManagerDelegate: AnyObject { func sizeChanged(width: CGFloat, height: CGFloat) + func onCloseAction() } /** @@ -38,7 +39,7 @@ class InlineMessageManager: MessageManager { } override func onCloseAction() { - // Not yet implemented. Planned in future update. + inlineMessageDelegate?.onCloseAction() } } diff --git a/Sources/MessagingInApp/Gist/Managers/MessageManager.swift b/Sources/MessagingInApp/Gist/Managers/MessageManager.swift index b9a857c7a..94efb698d 100644 --- a/Sources/MessagingInApp/Gist/Managers/MessageManager.swift +++ b/Sources/MessagingInApp/Gist/Managers/MessageManager.swift @@ -43,6 +43,7 @@ class MessageManager { // This means that the message begins the process of loading. // Start a timer that helps us determine how long a message took to load/render. elapsedTimer.start(title: "Loading message with id: \(currentMessage.templateId)") + self.engine = engineWebProvider.getEngineWebInstance(configuration: engineWebConfiguration) engine.delegate = self self.gistView = GistView(message: currentMessage, engineView: engine.view) diff --git a/Sources/MessagingInApp/Views/InAppMessageView.swift b/Sources/MessagingInApp/Views/InAppMessageView.swift index 39efa3eb0..42fa5fc66 100644 --- a/Sources/MessagingInApp/Views/InAppMessageView.swift +++ b/Sources/MessagingInApp/Views/InAppMessageView.swift @@ -175,4 +175,10 @@ extension InAppMessageView: InlineMessageManagerDelegate { self.animateHeight(to: height) } } + + func onCloseAction() { + Task { @MainActor in + self.dismissInAppMessage() + } + } } diff --git a/Tests/MessagingInApp/Views/InAppMessageViewTest.swift b/Tests/MessagingInApp/Views/InAppMessageViewTest.swift index a422b192d..c3f7c0b3e 100644 --- a/Tests/MessagingInApp/Views/InAppMessageViewTest.swift +++ b/Tests/MessagingInApp/Views/InAppMessageViewTest.swift @@ -215,6 +215,39 @@ class InAppMessageViewTest: UnitTest { XCTAssertFalse(isDisplayingInAppMessage(inlineView)) // expect ignore new message, stay dismissed. } + // MARK: close action button + + @MainActor + func test_onCloseAction_givenCloseActionClickedOnInAppMessage_expectDismissInlineView() async { + let givenInlineMessage = Message.randomInline + queueMock.getInlineMessagesReturnValue = [givenInlineMessage] + + let inlineView = InAppMessageView(elementId: givenInlineMessage.elementId!) + await onDoneRenderingInAppMessage(givenInlineMessage) + XCTAssertTrue(isDisplayingInAppMessage(inlineView)) + + await onCloseActionButtonPressed() + + XCTAssertFalse(isDisplayingInAppMessage(inlineView)) + } + + // Once an in-app message has been closed it will not be replaced with another message. + // We plan to change this behavior in the future. Test function can be modified to match the new behavior at that time. + @MainActor + func test_onCloseAction_givenMessageClosed_givenNewMessageFetched_expectIgnoreMessage() async { + let givenMessageThatGetsClosed = Message.randomInline + queueMock.getInlineMessagesReturnValue = [givenMessageThatGetsClosed] + + let inlineView = InAppMessageView(elementId: givenMessageThatGetsClosed.elementId!) + await onDoneRenderingInAppMessage(givenMessageThatGetsClosed) + XCTAssertTrue(isDisplayingInAppMessage(inlineView)) + await onCloseActionButtonPressed() + XCTAssertFalse(isDisplayingInAppMessage(inlineView)) + + await simulateSdkFetchedMessages([Message.randomInline]) // simulate new message fetched + XCTAssertFalse(isDisplayingInAppMessage(inlineView)) // expect ignore new message, stay dismissed. + } + // MARK: height and width constriants // When the View is constructed, the SDK will add a constraint or it will modify the existing height constraint. @@ -291,6 +324,15 @@ extension InAppMessageViewTest { await waitForMainThreadToFinishPendingTasks() } + func onCloseActionButtonPressed() async { + // Triggering the close button from the web engine simulates the user tapping the close button on the in-app WebView. + // This behaves more like an integration test because we are also able to test the message manager, too. + engineWebMock.delegate?.tap(name: "", action: GistMessageActions.close.rawValue, system: false) + + // When onCloseAction() is called on the inline View, it adds a task to the main thread queue. Our test wants to wait until this task is done running. + await waitForMainThreadToFinishPendingTasks() + } + func isDisplayingInAppMessage(_ view: InAppMessageView) -> Bool { guard let viewHeightConstraint = view.heightConstraint else { return false