Skip to content

Commit

Permalink
feat: in-app feature no longer requires orgId (customerio#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
levibostian committed Jan 30, 2023
1 parent 737d43b commit acd12da
Show file tree
Hide file tree
Showing 31 changed files with 244 additions and 127 deletions.
6 changes: 3 additions & 3 deletions Package.resolved
Expand Up @@ -3,11 +3,11 @@
"pins": [
{
"package": "Gist",
"repositoryURL": "https://gitlab.com/bourbonltd/gist-apple.git",
"repositoryURL": "https://github.com/customerio/gist-apple.git",
"state": {
"branch": null,
"revision": "408077c633807dc00fbce263cf513f69ab40a75b",
"version": "2.2.2"
"revision": "667cc2942eb94ccd8d2e3706605c8b81eaaa39e6",
"version": "3.0.2"
}
}
]
Expand Down
5 changes: 4 additions & 1 deletion Package.swift
Expand Up @@ -24,7 +24,10 @@ let package = Package(
dependencies: [
// Help for the format of declaring SPM dependencies:
// https://web.archive.org/web/20220525200227/https://www.timc.dev/posts/understanding-swift-packages/
.package(name: "Gist", url: "https://gitlab.com/bourbonltd/gist-apple.git", from: "2.2.1"),
//
// Note: using `.exact("")` instead of `from: ""` because 3.0.3 will not compile.
// Using 3.0.2 for now to not allow upgrading.
.package(name: "Gist", url: "https://github.com/customerio/gist-apple.git", .exact("3.0.2"))
],
targets: [
// Common - Code used by multiple modules in the SDK project.
Expand Down
4 changes: 4 additions & 0 deletions Sources/Common/Store/SdkConfig.swift
Expand Up @@ -19,6 +19,7 @@ public struct SdkConfig {
public enum Factory {
public static func create(region: Region) -> SdkConfig {
SdkConfig(
region: region,
trackingApiUrl: region.productionTrackingUrl,
autoTrackPushEvents: true,
backgroundQueueMinNumberOfTasks: 10,
Expand Down Expand Up @@ -91,6 +92,9 @@ public struct SdkConfig {
case sourceVersion = "version"
}

/// Immutable property to store the workspace Region set during SDK initialization.
public let region: Region

/**
Base URL to use for the Customer.io track API. You will more then likely not modify this value.
Expand Down
@@ -1,4 +1,4 @@
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all

Expand Down
2 changes: 1 addition & 1 deletion Sources/Common/autogenerated/AutoLenses.generated.swift
@@ -1,4 +1,4 @@
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all

Expand Down
2 changes: 1 addition & 1 deletion Sources/Common/autogenerated/AutoMockable.generated.swift
@@ -1,4 +1,4 @@
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all

Expand Down
63 changes: 36 additions & 27 deletions Sources/MessagingInApp/MessagingInApp.swift
Expand Up @@ -4,18 +4,27 @@ import Foundation
import Gist

public protocol MessagingInAppInstance: AutoMockable {
func initialize(organizationId: String)
// sourcery:Name=initialize
func initialize()
// sourcery:Name=initializeEventListener
func initialize(organizationId: String, eventListener: InAppEventListener)
func initialize(eventListener: InAppEventListener)

@available(*, deprecated, message: "Parameter organizationId no longer being used. Remove the parameter from your function call to migrate to new function.")
// sourcery:Name=initializeOrganizationId
func initialize(organizationId: String)
}

public class MessagingInApp: ModuleTopLevelObject<MessagingInAppInstance>, MessagingInAppInstance {
@Atomic public private(set) static var shared = MessagingInApp()
@Atomic public internal(set) static var shared = MessagingInApp()

// constructor that is called by test classes
// This function's job is to populate the `shared` property with
// overrides such as DI graph.
override internal init(implementation: MessagingInAppInstance?, sdkInitializedUtil: SdkInitializedUtil) {
super.init(implementation: implementation, sdkInitializedUtil: sdkInitializedUtil)
}

// constructor used in production with default DI graph
// singleton constructor
override private init() {
super.init()
Expand All @@ -26,59 +35,59 @@ public class MessagingInApp: ModuleTopLevelObject<MessagingInAppInstance>, Messa
Self.shared = MessagingInApp()
}

// testing constructor
internal static func initialize(organizationId: String, eventListener: InAppEventListener?, implementation: MessagingInAppInstance?, sdkInitializedUtil: SdkInitializedUtil) {
Self.shared = MessagingInApp(implementation: implementation, sdkInitializedUtil: sdkInitializedUtil)

if let eventListener = eventListener {
Self.initialize(organizationId: organizationId, eventListener: eventListener)
} else {
Self.initialize(organizationId: organizationId)
}
}

// MARK: static initialized functions for customers.

// static functions are identical to initialize functions in InAppInstance protocol to try and make a more convenient
// API for customers. Customers can use `MessagingInApp.initialize(...)` instead of `MessagingInApp.shared.initialize(...)`.
// Trying to follow the same API as `CustomerIO` class with `initialize()`.

public static func initialize(organizationId: String) {
Self.shared.initialize(organizationId: organizationId)
// Initialize SDK module
public static func initialize() {
Self.shared.initialize()
}

public static func initialize(eventListener: InAppEventListener) {
Self.shared.initialize(eventListener: eventListener)
}

public static func initialize(organizationId: String, eventListener: InAppEventListener) {
Self.shared.initialize(organizationId: organizationId, eventListener: eventListener)
@available(*, deprecated, message: "Parameter organizationId no longer being used. Remove the parameter from your function call to migrate to new function.")
public static func initialize(organizationId: String) {
Self.shared.initialize(organizationId: organizationId)
}

// MARK: initialize functions to initialize module.

// Multiple initialize functions to inherit the InAppInstance protocol which contains multiple initialize functions.

public func initialize(organizationId: String) {
commonInitialize(organizationId: organizationId, eventListener: nil)
public func initialize() {
commonInitialize(eventListener: nil)
}

public func initialize(eventListener: InAppEventListener) {
commonInitialize(eventListener: eventListener)
}

public func initialize(organizationId: String, eventListener: InAppEventListener) {
commonInitialize(organizationId: organizationId, eventListener: eventListener)
@available(*, deprecated, message: "Parameter organizationId no longer being used. Remove the parameter from your function call to migrate to new function.")
public func initialize(organizationId: String) {
commonInitialize(eventListener: nil)
}

private func commonInitialize(organizationId: String, eventListener: InAppEventListener?) {
private func commonInitialize(eventListener: InAppEventListener?) {
guard let implementation = implementation else {
sdkNotInitializedAlert("CustomerIO class has not yet been initialized. Request to initialize the in-app module has been ignored.")
return
}

initialize()
initializeModuleIfSdkInitialized()

if let eventListener = eventListener {
implementation.initialize(organizationId: organizationId, eventListener: eventListener)
implementation.initialize(eventListener: eventListener)
} else {
implementation.initialize(organizationId: organizationId)
implementation.initialize()
}
}

override public func inititlize(diGraph: DIGraph) {
override public func inititlizeModule(diGraph: DIGraph) {
let logger = diGraph.logger
logger.debug("Setting up in-app module...")

Expand Down
16 changes: 12 additions & 4 deletions Sources/MessagingInApp/MessagingInAppImplementation.swift
Expand Up @@ -4,6 +4,8 @@ import Foundation
import Gist

internal class MessagingInAppImplementation: MessagingInAppInstance {
private let siteId: SiteId
private let region: Region
private let logger: Logger
private var queue: Queue
private var jsonAdapter: JsonAdapter
Expand All @@ -13,15 +15,17 @@ internal class MessagingInAppImplementation: MessagingInAppInstance {
private var eventListener: InAppEventListener?

init(diGraph: DIGraph) {
self.siteId = diGraph.siteId
self.region = diGraph.sdkConfig.region
self.logger = diGraph.logger
self.queue = diGraph.queue
self.jsonAdapter = diGraph.jsonAdapter
self.inAppProvider = diGraph.inAppProvider
self.profileStore = diGraph.profileStore
}

func initialize(organizationId: String) {
inAppProvider.initialize(organizationId: organizationId, delegate: self)
func initialize() {
inAppProvider.initialize(siteId: siteId, region: region, delegate: self)

// if identifier is already present, set the userToken again so in case if the customer was already identified and
// module was added later on, we can notify gist about it.
Expand All @@ -30,10 +34,14 @@ internal class MessagingInAppImplementation: MessagingInAppInstance {
}
}

func initialize(organizationId: String, eventListener: InAppEventListener) {
func initialize(eventListener: InAppEventListener) {
self.eventListener = eventListener
initialize(organizationId: organizationId)
initialize()
}

// Functions deprecated but need to exist for `MessagingInAppInstance` protocol.
// Do not call these functions but non-deprecated ones.
func initialize(organizationId: String) {}
}

extension MessagingInAppImplementation: ProfileIdentifyHook {
Expand Down
6 changes: 3 additions & 3 deletions Sources/MessagingInApp/Provider/InAppProvider.swift
Expand Up @@ -4,16 +4,16 @@ import Gist

// wrapper around Gist SDK to make it mockable
internal protocol InAppProvider: AutoMockable {
func initialize(organizationId: String, delegate: GistDelegate)
func initialize(siteId: String, region: Region, delegate: GistDelegate)
func setProfileIdentifier(_ id: String)
func clearIdentify()
func setRoute(_ route: String)
}

// sourcery: InjectRegister = "InAppProvider"
internal class GistInAppProvider: InAppProvider {
func initialize(organizationId: String, delegate: GistDelegate) {
Gist.shared.setup(organizationId: organizationId)
func initialize(siteId: String, region: Region, delegate: GistDelegate) {
Gist.shared.setup(siteId: siteId, dataCenter: region.rawValue)
Gist.shared.delegate = delegate
}

Expand Down
@@ -1,4 +1,4 @@
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all

Expand Down
@@ -1,4 +1,4 @@
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all

Expand Down
83 changes: 54 additions & 29 deletions Sources/MessagingInApp/autogenerated/AutoMockable.generated.swift
@@ -1,4 +1,4 @@
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// Generated using Sourcery 2.0.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all

Expand Down Expand Up @@ -275,21 +275,21 @@ internal class InAppProviderMock: InAppProvider, Mock {
}

/// The arguments from the *last* time the function was called.
internal private(set) var initializeReceivedArguments: (organizationId: String, delegate: GistDelegate)?
internal private(set) var initializeReceivedArguments: (siteId: String, region: Region, delegate: GistDelegate)?
/// Arguments from *all* of the times that the function was called.
internal private(set) var initializeReceivedInvocations: [(organizationId: String, delegate: GistDelegate)] = []
internal private(set) var initializeReceivedInvocations: [(siteId: String, region: Region, delegate: GistDelegate)] = []
/**
Set closure to get called when function gets called. Great way to test logic or return a value for the function.
*/
internal var initializeClosure: ((String, GistDelegate) -> Void)?
internal var initializeClosure: ((String, Region, GistDelegate) -> Void)?

/// Mocked function for `initialize(organizationId: String, delegate: GistDelegate)`. Your opportunity to return a mocked value and check result of mock in test code.
internal func initialize(organizationId: String, delegate: GistDelegate) {
/// Mocked function for `initialize(siteId: String, region: Region, delegate: GistDelegate)`. Your opportunity to return a mocked value and check result of mock in test code.
internal func initialize(siteId: String, region: Region, delegate: GistDelegate) {
mockCalled = true
initializeCallsCount += 1
initializeReceivedArguments = (organizationId: organizationId, delegate: delegate)
initializeReceivedInvocations.append((organizationId: organizationId, delegate: delegate))
initializeClosure?(organizationId, delegate)
initializeReceivedArguments = (siteId: siteId, region: region, delegate: delegate)
initializeReceivedInvocations.append((siteId: siteId, region: region, delegate: delegate))
initializeClosure?(siteId, region, delegate)
}

// MARK: - setProfileIdentifier
Expand Down Expand Up @@ -385,14 +385,17 @@ public class MessagingInAppInstanceMock: MessagingInAppInstance, Mock {

public func resetMock() {
initializeCallsCount = 0
initializeReceivedArguments = nil
initializeReceivedInvocations = []

mockCalled = false // do last as resetting properties above can make this true
initializeEventListenerCallsCount = 0
initializeEventListenerReceivedArguments = nil
initializeEventListenerReceivedInvocations = []

mockCalled = false // do last as resetting properties above can make this true
initializeOrganizationIdCallsCount = 0
initializeOrganizationIdReceivedArguments = nil
initializeOrganizationIdReceivedInvocations = []

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

Expand All @@ -405,22 +408,16 @@ public class MessagingInAppInstanceMock: MessagingInAppInstance, Mock {
initializeCallsCount > 0
}

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

/// Mocked function for `initialize(organizationId: String)`. Your opportunity to return a mocked value and check result of mock in test code.
public func initialize(organizationId: String) {
/// Mocked function for `initialize()`. Your opportunity to return a mocked value and check result of mock in test code.
public func initialize() {
mockCalled = true
initializeCallsCount += 1
initializeReceivedArguments = organizationId
initializeReceivedInvocations.append(organizationId)
initializeClosure?(organizationId)
initializeClosure?()
}

// MARK: - initialize
Expand All @@ -433,20 +430,48 @@ public class MessagingInAppInstanceMock: MessagingInAppInstance, Mock {
}

/// The arguments from the *last* time the function was called.
public private(set) var initializeEventListenerReceivedArguments: (organizationId: String, eventListener: InAppEventListener)?
public private(set) var initializeEventListenerReceivedArguments: InAppEventListener?
/// Arguments from *all* of the times that the function was called.
public private(set) var initializeEventListenerReceivedInvocations: [(organizationId: String, eventListener: InAppEventListener)] = []
public private(set) var initializeEventListenerReceivedInvocations: [InAppEventListener] = []
/**
Set closure to get called when function gets called. Great way to test logic or return a value for the function.
*/
public var initializeEventListenerClosure: ((String, InAppEventListener) -> Void)?
public var initializeEventListenerClosure: ((InAppEventListener) -> Void)?

/// Mocked function for `initialize(organizationId: String, eventListener: InAppEventListener)`. Your opportunity to return a mocked value and check result of mock in test code.
public func initialize(organizationId: String, eventListener: InAppEventListener) {
/// Mocked function for `initialize(eventListener: InAppEventListener)`. Your opportunity to return a mocked value and check result of mock in test code.
public func initialize(eventListener: InAppEventListener) {
mockCalled = true
initializeEventListenerCallsCount += 1
initializeEventListenerReceivedArguments = (organizationId: organizationId, eventListener: eventListener)
initializeEventListenerReceivedInvocations.append((organizationId: organizationId, eventListener: eventListener))
initializeEventListenerClosure?(organizationId, eventListener)
initializeEventListenerReceivedArguments = eventListener
initializeEventListenerReceivedInvocations.append(eventListener)
initializeEventListenerClosure?(eventListener)
}

// MARK: - initialize

/// Number of times the function was called.
public private(set) var initializeOrganizationIdCallsCount = 0
/// `true` if the function was ever called.
public var initializeOrganizationIdCalled: Bool {
initializeOrganizationIdCallsCount > 0
}

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

/// Mocked function for `initialize(organizationId: String)`. Your opportunity to return a mocked value and check result of mock in test code.
@available(*, deprecated, message: "Parameter organizationId no longer being used. Remove the parameter from your function call to migrate to new function.")
public func initialize(organizationId: String) {
mockCalled = true
initializeOrganizationIdCallsCount += 1
initializeOrganizationIdReceivedArguments = organizationId
initializeOrganizationIdReceivedInvocations.append(organizationId)
initializeOrganizationIdClosure?(organizationId)
}
}

0 comments on commit acd12da

Please sign in to comment.