Skip to content

Commit

Permalink
write test inline view that checks if a fetch is done and message exp…
Browse files Browse the repository at this point in the history
…ires, it dismisses
  • Loading branch information
levibostian committed Jun 4, 2024
1 parent 05efd25 commit 236a9dc
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ generate:
./binny sourcery --sources Sources/MessagingPush --templates Sources/Templates --output Sources/MessagingPush/autogenerated --args imports=CioInternalCommon
./binny sourcery --sources Sources/MessagingPushAPN --templates Sources/Templates --output Sources/MessagingPushAPN/autogenerated --args imports=CioMessagingPush-CioInternalCommon
./binny sourcery --sources Sources/MessagingPushFCM --templates Sources/Templates --output Sources/MessagingPushFCM/autogenerated --args imports=CioMessagingPush-CioInternalCommon
./binny sourcery --sources Sources/MessagingInApp --templates Sources/Templates --output Sources/MessagingInApp/autogenerated --args imports=CioInternalCommon
./binny sourcery --sources Sources/MessagingInApp --templates Sources/Templates --output Sources/MessagingInApp/autogenerated --args imports=CioInternalCommon-UIKit
./binny sourcery --sources Sources/Migration --templates Sources/Templates --output Sources/Migration/autogenerated --args imports=CioInternalCommon


Expand Down
9 changes: 8 additions & 1 deletion Sources/MessagingInApp/Gist/EngineWeb/EngineWeb.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import CioInternalCommon
import Foundation
import UIKit
import WebKit
Expand All @@ -12,7 +13,13 @@ public protocol EngineWebDelegate: AnyObject {
func error()
}

public class EngineWeb: NSObject {
protocol EngineWebInstance: AutoMockable {
var delegate: EngineWebDelegate? { get set }
var view: UIView { get }
func cleanEngineWeb()
}

public class EngineWeb: NSObject, EngineWebInstance {
private var _currentRoute = ""
private var _timeoutTimer: Timer?
private var _elapsedTimer = ElapsedTimer()
Expand Down
14 changes: 14 additions & 0 deletions Sources/MessagingInApp/Gist/EngineWeb/EngineWebProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import CioInternalCommon
import Foundation

// Allows us to mock EngineWeb instances for testing.
protocol EngineWebProvider {
func getEngineWebInstance(configuration: EngineWebConfiguration) -> EngineWebInstance
}

// sourcery: InjectRegisterShared = "EngineWebProvider"
class EngineWebProviderImpl: EngineWebProvider {
func getEngineWebInstance(configuration: EngineWebConfiguration) -> EngineWebInstance {
EngineWeb(configuration: configuration)
}
}
17 changes: 8 additions & 9 deletions Sources/MessagingInApp/Gist/Managers/MessageManager.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import CioInternalCommon
import Foundation
import UIKit

Expand All @@ -15,13 +16,14 @@ public enum GistMessageActions: String {
* Override any of the abstract functions in class to implement custom logic for when certain events happen. Depending on the type of message you are displaying, you may want to handle events differently.
*/
class MessageManager {
private var engine: EngineWeb?
private var engine: EngineWebInstance
private let siteId: String
let currentMessage: Message
var gistView: GistView!
private var currentRoute: String
private var elapsedTimer = ElapsedTimer()
weak var delegate: GistDelegate?
private let engineWebProvider: EngineWebProvider = DIGraphShared.shared.engineWebProvider

init(siteId: String, message: Message) {
self.siteId = siteId
Expand All @@ -41,17 +43,14 @@ 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.messageId)")
self.engine = EngineWeb(configuration: engineWebConfiguration)

if let engine = engine {
engine.delegate = self
self.gistView = GistView(message: currentMessage, engineView: engine.view)
}
self.engine = engineWebProvider.getEngineWebInstance(configuration: engineWebConfiguration)
engine.delegate = self
self.gistView = GistView(message: currentMessage, engineView: engine.view)
}

deinit {
engine?.cleanEngineWeb()
engine = nil
engine.cleanEngineWeb()
}

// MARK: event listeners that subclasses override to handle events.
Expand Down Expand Up @@ -85,7 +84,7 @@ extension MessageManager: EngineWebDelegate {

// Cleaning after engine web is bootstrapped and all assets downloaded.
if currentMessage.messageId == "" {
engine?.cleanEngineWeb()
engine.cleanEngineWeb()
}
}

Expand Down
5 changes: 0 additions & 5 deletions Sources/MessagingInApp/Views/InAppMessageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,6 @@ public class InAppMessageView: UIView {
self?.checkIfMessageAvailableToDisplay()
}
}

DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
print("InAppMessageView: Simulating message expired and is gone now.")
Gist.shared.messageQueueManager.processFetchedMessages([]) // simulate message expired and is gone now.
}
}

private func checkIfMessageAvailableToDisplay() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import CioInternalCommon
import Foundation
import UIKit

/**
######################################################
Expand Down Expand Up @@ -54,6 +55,9 @@ extension DIGraphShared {
func testDependenciesAbleToResolve() -> Int {
var countDependenciesResolved = 0

_ = engineWebProvider
countDependenciesResolved += 1

_ = inAppProvider
countDependenciesResolved += 1

Expand All @@ -64,6 +68,16 @@ extension DIGraphShared {
}

// Handle classes annotated with InjectRegisterShared
// EngineWebProvider
var engineWebProvider: EngineWebProvider {
getOverriddenInstance() ??
newEngineWebProvider
}

private var newEngineWebProvider: EngineWebProvider {
EngineWebProviderImpl()
}

// InAppProvider
var inAppProvider: InAppProvider {
getOverriddenInstance() ??
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import CioInternalCommon
import Foundation
import UIKit

/**
######################################################
Expand Down
177 changes: 177 additions & 0 deletions Sources/MessagingInApp/autogenerated/AutoMockable.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import FoundationNetworking
import UserNotifications
#endif
import CioInternalCommon
import UIKit

/**
######################################################
Expand Down Expand Up @@ -80,6 +81,126 @@ import CioInternalCommon

*/

/**
Class to easily create a mocked version of the `EngineWebInstance` class.
This class is equipped with functions and properties ready for you to mock!

Note: This file is automatically generated. This means the mocks should always be up-to-date and has a consistent API.
See the SDK documentation to learn the basics behind using the mock classes in the SDK.
*/
class EngineWebInstanceMock: EngineWebInstance, Mock {
/// If *any* interactions done on mock. `true` if any method or property getter/setter called.
var mockCalled: Bool = false //

init() {
Mocks.shared.add(mock: self)
}

/**
When setter of the property called, the value given to setter is set here.
When the getter of the property called, the value set here will be returned. Your chance to mock the property.
*/
var underlyingDelegate: EngineWebDelegate? = nil
/// `true` if the getter or setter of property is called at least once.
var delegateCalled: Bool {
delegateGetCalled || delegateSetCalled
}

/// `true` if the getter called on the property at least once.
var delegateGetCalled: Bool {
delegateGetCallsCount > 0
}

var delegateGetCallsCount = 0
/// `true` if the setter called on the property at least once.
var delegateSetCalled: Bool {
delegateSetCallsCount > 0
}

var delegateSetCallsCount = 0
/// The mocked property with a getter and setter.
var delegate: EngineWebDelegate? {
get {
mockCalled = true
delegateGetCallsCount += 1
return underlyingDelegate
}
set(value) {
mockCalled = true
delegateSetCallsCount += 1
underlyingDelegate = value
}
}

/**
When setter of the property called, the value given to setter is set here.
When the getter of the property called, the value set here will be returned. Your chance to mock the property.
*/
var underlyingView: UIView!
/// `true` if the getter or setter of property is called at least once.
var viewCalled: Bool {
viewGetCalled || viewSetCalled
}

/// `true` if the getter called on the property at least once.
var viewGetCalled: Bool {
viewGetCallsCount > 0
}

var viewGetCallsCount = 0
/// `true` if the setter called on the property at least once.
var viewSetCalled: Bool {
viewSetCallsCount > 0
}

var viewSetCallsCount = 0
/// The mocked property with a getter and setter.
var view: UIView {
get {
mockCalled = true
viewGetCallsCount += 1
return underlyingView
}
set(value) {
mockCalled = true
viewSetCallsCount += 1
underlyingView = value
}
}

public func resetMock() {
delegate = nil
delegateGetCallsCount = 0
delegateSetCallsCount = 0
viewGetCallsCount = 0
viewSetCallsCount = 0
cleanEngineWebCallsCount = 0

mockCalled = false // do last as resetting properties above can make this true
}

// MARK: - cleanEngineWeb

/// Number of times the function was called.
@Atomic private(set) var cleanEngineWebCallsCount = 0
/// `true` if the function was ever called.
var cleanEngineWebCalled: Bool {
cleanEngineWebCallsCount > 0
}

/**
Set closure to get called when function gets called. Great way to test logic or return a value for the function.
*/
var cleanEngineWebClosure: (() -> Void)?

/// Mocked function for `cleanEngineWeb()`. Your opportunity to return a mocked value and check result of mock in test code.
func cleanEngineWeb() {
mockCalled = true
cleanEngineWebCallsCount += 1
cleanEngineWebClosure?()
}
}

/**
Class to easily create a mocked version of the `GistInstance` class.
This class is equipped with functions and properties ready for you to mock!
Expand Down Expand Up @@ -499,6 +620,14 @@ class MessageQueueManagerMock: MessageQueueManager, Mock {
}

public func resetMock() {
resetCallsCount = 0

mockCalled = false // do last as resetting properties above can make this true
processFetchedMessagesCallsCount = 0
processFetchedMessagesReceivedArguments = nil
processFetchedMessagesReceivedInvocations = []

mockCalled = false // do last as resetting properties above can make this true
getIntervalCallsCount = 0

mockCalled = false // do last as resetting properties above can make this true
Expand Down Expand Up @@ -530,6 +659,54 @@ class MessageQueueManagerMock: MessageQueueManager, Mock {
mockCalled = false // do last as resetting properties above can make this true
}

// MARK: - reset

/// Number of times the function was called.
@Atomic private(set) var resetCallsCount = 0
/// `true` if the function was ever called.
var resetCalled: Bool {
resetCallsCount > 0
}

/**
Set closure to get called when function gets called. Great way to test logic or return a value for the function.
*/
var resetClosure: (() -> Void)?

/// Mocked function for `reset()`. Your opportunity to return a mocked value and check result of mock in test code.
func reset() {
mockCalled = true
resetCallsCount += 1
resetClosure?()
}

// MARK: - processFetchedMessages

/// Number of times the function was called.
@Atomic private(set) var processFetchedMessagesCallsCount = 0
/// `true` if the function was ever called.
var processFetchedMessagesCalled: Bool {
processFetchedMessagesCallsCount > 0
}

/// The arguments from the *last* time the function was called.
@Atomic private(set) var processFetchedMessagesReceivedArguments: [Message]?
/// Arguments from *all* of the times that the function was called.
@Atomic private(set) var processFetchedMessagesReceivedInvocations: [[Message]] = []
/**
Set closure to get called when function gets called. Great way to test logic or return a value for the function.
*/
var processFetchedMessagesClosure: (([Message]) -> Void)?

/// Mocked function for `processFetchedMessages(_ fetchedMessages: [Message])`. Your opportunity to return a mocked value and check result of mock in test code.
func processFetchedMessages(_ fetchedMessages: [Message]) {
mockCalled = true
processFetchedMessagesCallsCount += 1
processFetchedMessagesReceivedArguments = fetchedMessages
processFetchedMessagesReceivedInvocations.append(fetchedMessages)
processFetchedMessagesClosure?(fetchedMessages)
}

// MARK: - getInterval

/// Number of times the function was called.
Expand Down
14 changes: 14 additions & 0 deletions Tests/MessagingInApp/EngineWeb/EngineWebProviderStub.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@testable import CioMessagingInApp
import Foundation

class EngineWebProviderStub: EngineWebProvider {
let engineWebMock: EngineWebInstance

init(engineWebMock: EngineWebInstance) {
self.engineWebMock = engineWebMock
}

func getEngineWebInstance(configuration: EngineWebConfiguration) -> EngineWebInstance {
engineWebMock
}
}
Loading

0 comments on commit 236a9dc

Please sign in to comment.