diff --git a/.swiftlint.yml b/.swiftlint.yml index 0197f8b..29287ee 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -22,7 +22,6 @@ closing_brace: error colon: severity: error comma: error -empty_count: warning empty_enum_arguments: error function_body_length: warning: 100 diff --git a/Sources/Clickstream/AWSClickstreamPlugin+ClientBehavior.swift b/Sources/Clickstream/AWSClickstreamPlugin+ClientBehavior.swift index 1547578..aa51b03 100644 --- a/Sources/Clickstream/AWSClickstreamPlugin+ClientBehavior.swift +++ b/Sources/Clickstream/AWSClickstreamPlugin+ClientBehavior.swift @@ -8,7 +8,7 @@ import Amplify import Foundation -public extension AWSClickstreamPlugin { +extension AWSClickstreamPlugin { func identifyUser(userId: String, userProfile: AnalyticsUserProfile?) { if userId == Event.User.USER_ID_EMPTY { userProfile?.properties?.forEach { key, value in diff --git a/Sources/Clickstream/AWSClickstreamPlugin+Configure.swift b/Sources/Clickstream/AWSClickstreamPlugin+Configure.swift index c20cb50..1c74e43 100644 --- a/Sources/Clickstream/AWSClickstreamPlugin+Configure.swift +++ b/Sources/Clickstream/AWSClickstreamPlugin+Configure.swift @@ -12,7 +12,7 @@ import Network import UIKit #endif -public extension AWSClickstreamPlugin { +extension AWSClickstreamPlugin { /// called when sdk init. func configure(using configuration: Any?) throws { guard let config = configuration as? JSONValue else { @@ -72,7 +72,7 @@ public extension AWSClickstreamPlugin { // MARK: Internal /// Internal configure method to set the properties of the plugin - internal func configure( + func configure( autoFlushEventsTimer: DispatchSourceTimer?, networkMonitor: NetworkMonitor ) { diff --git a/Sources/Clickstream/AWSClickstreamPlugin+Reset.swift b/Sources/Clickstream/AWSClickstreamPlugin+Reset.swift index 2ed0cd7..d4eef27 100644 --- a/Sources/Clickstream/AWSClickstreamPlugin+Reset.swift +++ b/Sources/Clickstream/AWSClickstreamPlugin+Reset.swift @@ -5,7 +5,7 @@ // SPDX-License-Identifier: Apache-2.0 // -public extension AWSClickstreamPlugin { +extension AWSClickstreamPlugin { func reset() { if clickstream != nil { clickstream = nil diff --git a/Sources/Clickstream/AWSClickstreamPlugin.swift b/Sources/Clickstream/AWSClickstreamPlugin.swift index 9df3286..8eb3272 100644 --- a/Sources/Clickstream/AWSClickstreamPlugin.swift +++ b/Sources/Clickstream/AWSClickstreamPlugin.swift @@ -8,8 +8,8 @@ import Amplify import Foundation -public final class AWSClickstreamPlugin: AnalyticsCategoryPlugin { - public var clickstream: ClickstreamContext! +final class AWSClickstreamPlugin: AnalyticsCategoryPlugin { + var clickstream: ClickstreamContext! /// Automatically flushes the events that have been recorded on an interval var autoFlushEventsTimer: DispatchSourceTimer? @@ -24,10 +24,10 @@ public final class AWSClickstreamPlugin: AnalyticsCategoryPlugin { var analyticsClient: AnalyticsClientBehaviour! /// The configuration file plugin key of clickstream plugin - public var key: PluginKey { + var key: PluginKey { "awsClickstreamPlugin" } /// Instantiates an instance of the AWSClickstreamPlugin - public init() {} + init() {} } diff --git a/Sources/Clickstream/ClickstreamAnalytics.swift b/Sources/Clickstream/ClickstreamAnalytics.swift index 1ec67d9..b305dbe 100644 --- a/Sources/Clickstream/ClickstreamAnalytics.swift +++ b/Sources/Clickstream/ClickstreamAnalytics.swift @@ -7,6 +7,7 @@ import Amplify +/// ClickstreamAnalytics api for swift public enum ClickstreamAnalytics { /// Init ClickstreamAnalytics public static func initSDK() throws { @@ -14,19 +15,22 @@ public enum ClickstreamAnalytics { try Amplify.configure() } - /// Use this method to record Event. - /// - Parameter event: ClickstreamEvent to record - public static func recordEvent(event: AnalyticsEvent) { - Amplify.Analytics.record(event: event) - } - - /// Use this method to record Event. + /// Use this method to record event /// - Parameter eventName: the event name public static func recordEvent(eventName: String) { Amplify.Analytics.record(eventWithName: eventName) } - /// Use this method to send events immediately. + /// The method to record event with ClickstreamAttribute + /// - Parameters: + /// - eventName: the event name + /// - attributes: the event attributes + public static func recordEvent(eventName: String, attributes: ClickstreamAttribute) { + let event = BaseClickstreamEvent(name: eventName, attribute: attributes) + Amplify.Analytics.record(event: event) + } + + /// Use this method to send events immediately public static func flushEvents() { Amplify.Analytics.flushEvents() } @@ -38,7 +42,7 @@ public enum ClickstreamAnalytics { } /// Delete global attributes - /// - Parameter attributes: the global attributes to delete + /// - Parameter attributes: the global attributes names to delete public static func deleteGlobalAttributes(attributes: String...) { Amplify.Analytics.unregisterGlobalProperties(attributes) } @@ -61,10 +65,12 @@ public enum ClickstreamAnalytics { } } - /// Get clickstream configuration, please config it after initialize. - /// - Returns: ClickstreamContextConfiguration: current userId, nil for logout - public static func getClickStreamConfiguration() throws -> ClickstreamContextConfiguration? { + /// Get Clickstream configuration, please config it after initialize sdk + /// - Returns: ClickstreamContextConfiguration to modify the configuration of clickstream sdk + public static func getClickstreamConfiguration() throws -> ClickstreamContextConfiguration { let plugin = try Amplify.Analytics.getPlugin(for: "awsClickstreamPlugin") - return (plugin as? AWSClickstreamPlugin)?.getEscapeHatch().configuration + // swiftlint:disable force_cast + return (plugin as! AWSClickstreamPlugin).getEscapeHatch().configuration + // swiftlint:enable force_cast } } diff --git a/Sources/Clickstream/ClickstreamAttribute.swift b/Sources/Clickstream/ClickstreamAttribute.swift index 4e70873..587f5c8 100644 --- a/Sources/Clickstream/ClickstreamAttribute.swift +++ b/Sources/Clickstream/ClickstreamAttribute.swift @@ -7,34 +7,29 @@ import Amplify +/// the attribute for Clickstream which support String, Int, Int64, Double and Bool public typealias ClickstreamAttribute = AnalyticsProperties -public typealias AttributeValue = AnalyticsPropertyValue + +typealias AttributeValue = AnalyticsPropertyValue extension Int64: AnalyticsPropertyValue {} -public struct BaseClickstreamEvent: AnalyticsEvent { - public var properties: AnalyticsProperties? +struct BaseClickstreamEvent: AnalyticsEvent { + var properties: AnalyticsProperties? /// The name of the event - public var name: String + var name: String /// Properties of the event - public var attribute: ClickstreamAttribute? + var attribute: ClickstreamAttribute? /// Initializer /// - Parameters: /// - name: The name of the event /// - attribute: Attribute of the event - public init(name: String, - attribute: ClickstreamAttribute? = nil) + init(name: String, + attribute: ClickstreamAttribute? = nil) { self.name = name self.attribute = attribute } } - -public struct ClickstreamUserAttribute { - public var attribute: ClickstreamAttribute? - public init(attribute: ClickstreamAttribute?) { - self.attribute = attribute - } -} diff --git a/Sources/Clickstream/ClickstreamObjc.swift b/Sources/Clickstream/ClickstreamObjc.swift new file mode 100644 index 0000000..0d533ef --- /dev/null +++ b/Sources/Clickstream/ClickstreamObjc.swift @@ -0,0 +1,85 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import Foundation + +/// ClickstreamAnalytics api for objective-c +@objcMembers public class ClickstreamObjc: NSObject { + /// Init the Clickstream sdk + public static func initSDK() throws { + try ClickstreamAnalytics.initSDK() + } + + /// Use this method to record event + /// - Parameter eventName: the event name + public static func recordEvent(_ eventName: String) { + ClickstreamAnalytics.recordEvent(eventName: eventName) + } + + /// The method to record event with attributes + /// - Parameters: + /// - eventName: the event name + /// - attributes: the event attributes which type is NSDictionary + public static func recordEvent(_ eventName: String, _ attributes: NSDictionary) { + ClickstreamAnalytics.recordEvent(eventName: eventName, attributes: getAttributes(attributes)) + } + + /// Use this method to send events immediately + public static func flushEvents() { + ClickstreamAnalytics.flushEvents() + } + + /// Add global attributes + /// - Parameter attributes: the global attributes to add + public static func addGlobalAttributes(_ attributes: NSDictionary) { + ClickstreamAnalytics.addGlobalAttributes(attributes: getAttributes(attributes)) + } + + /// Delete global attributes + /// - Parameter attributes: the global attributes names to delete + public static func deleteGlobalAttributes(_ attributes: [String]) { + for attribute in attributes { + ClickstreamAnalytics.deleteGlobalAttributes(attributes: attribute) + } + } + + /// Add user attributes + /// - Parameter attributes: the user attributes to add + public static func addUserAttributes(_ attributes: NSDictionary) { + ClickstreamAnalytics.addUserAttributes(attributes: getAttributes(attributes)) + } + + /// Set user id for login and logout + /// - Parameter userId: current userId, nil for logout + public static func setUserId(_ userId: String?) { + ClickstreamAnalytics.setUserId(userId: userId) + } + + /// Get Clickstream configuration, please config it after initialize sdk + /// - Returns: ClickstreamContextConfiguration to modify the configuration of clickstream sdk + public static func getClickstreamConfiguration() throws -> ClickstreamContextConfiguration { + try ClickstreamAnalytics.getClickstreamConfiguration() + } + + private static func getAttributes(_ attributes: NSDictionary) -> ClickstreamAttribute { + var result: ClickstreamAttribute = [:] + for case let (key as String, value) in attributes { + if value is String { + result[key] = value as? String + } else if value is Bool { + if let boolValue = value as? Bool { + result[key] = boolValue ? true : false + } + } else if value is Int { + result[key] = value as? Int + } else if value is Double { + result[key] = value as? Double + } + } + return result + } +} diff --git a/Sources/Clickstream/Configuration/AWSClickstreamPluginConfiguration.swift b/Sources/Clickstream/Configuration/AWSClickstreamPluginConfiguration.swift index 83ea5d8..9d4de87 100644 --- a/Sources/Clickstream/Configuration/AWSClickstreamPluginConfiguration.swift +++ b/Sources/Clickstream/Configuration/AWSClickstreamPluginConfiguration.swift @@ -7,7 +7,7 @@ import Amplify -public struct AWSClickstreamConfiguration { +struct AWSClickstreamConfiguration { static let appIdKey = "appId" static let endpointKey = "endpoint" static let sendEventsIntervalKey = "autoFlushEventsInterval" diff --git a/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift b/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift index c449694..6dc3094 100644 --- a/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift +++ b/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift @@ -33,23 +33,25 @@ extension UserDefaults: UserDefaultsBehaviour { // MARK: - ClickstreamContext -/// the configuration object contains the necessary and optional param which required to use clickstream -public class ClickstreamContextConfiguration { - // The clickstream appId +/// The configuration object for clickstream, modify the params after sdk initialize +@objcMembers public class ClickstreamContextConfiguration: NSObject { + /// The clickstream appId public var appId: String /// The clickstream endpoint public var endpoint: String /// Time interval after which the events are automatically submitted to server private let sendEventsInterval: Int - /// Whether to track app lifecycle events automatically - public var isTrackAppExceptionEvents: Bool /// Whether to track app exception events automatically + public var isTrackAppExceptionEvents: Bool + /// Whether to track app scren view events automatically public var isTrackScreenViewEvents: Bool - /// Whether to compress events + /// Whether to compress events when send to server public var isCompressEvents: Bool - /// Whether to log events json in terminal when debug + /// Whether to log events json in console when debug public var isLogEvents: Bool + /// The auth cookie for request public var authCookie: String? + /// The session timeout calculated the duration from last app in background, defalut is 1800000ms public var sessionTimeoutDuration: Int64 init(appId: String, @@ -76,7 +78,7 @@ struct ClickstreamContextStorage { let userDefaults: UserDefaultsBehaviour } -public class ClickstreamContext { +class ClickstreamContext { var sessionClient: SessionClientBehaviour! var analyticsClient: AnalyticsClientBehaviour! var networkMonitor: NetworkMonitor! diff --git a/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift b/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift index 45e5a53..1de1322 100644 --- a/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift +++ b/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift @@ -15,7 +15,7 @@ enum Event { /// - key: attribute key /// - value: attribute value /// - Returns: the ErrorType - public static func checkAttribute(currentNumber: Int, key: String, value: AttributeValue) -> EventError? { + static func checkAttribute(currentNumber: Int, key: String, value: AttributeValue) -> EventError? { if currentNumber >= Limit.MAX_NUM_OF_ATTRIBUTES { let errorMsg = """ reached the max number of attributes limit (\(Limit.MAX_NUM_OF_ATTRIBUTES)).\ @@ -70,7 +70,7 @@ enum Event { /// - key: attribute key /// - value: attribute value /// - Returns: the ErrorType - public static func checkUserAttribute(currentNumber: Int, key: String, value: AttributeValue) -> EventError? { + static func checkUserAttribute(currentNumber: Int, key: String, value: AttributeValue) -> EventError? { if currentNumber >= Limit.MAX_NUM_OF_USER_ATTRIBUTES { let errorMsg = """ reached the max number of user attributes limit (\(Limit.MAX_NUM_OF_USER_ATTRIBUTES)).\ @@ -123,7 +123,7 @@ enum Event { /// Check the event name whether valide /// - Parameter eventType: the event name /// - Returns: the eventType is valide and the error type - public static func isValidEventType(eventType: String) -> (Bool, String) { + static func isValidEventType(eventType: String) -> (Bool, String) { if eventType.utf8.count > Event.Limit.MAX_EVENT_TYPE_LENGTH { let errorMsg = """ Event name is too long, the max event type length is \ @@ -144,7 +144,7 @@ enum Event { /// underscores, and is not start with a number /// - Parameter name: the name to verify /// - Returns: the name is valid. - public static func isValidName(name: String) -> Bool { + static func isValidName(name: String) -> Bool { let regex = try? NSRegularExpression(pattern: "^(?![0-9])[0-9a-zA-Z_]+$") let range = NSRange(location: 0, length: name.utf8.count) let matches = regex?.matches(in: name, range: range) @@ -156,64 +156,64 @@ enum Event { } enum ReservedAttribute { - public static let USER_ID = "_user_id" - public static let USER_FIRST_TOUCH_TIMESTAMP = "_user_first_touch_timestamp" - public static let PREVIOUS_APP_VERSION = "_previous_app_version" - public static let PREVIOUS_OS_VERSION = "_previous_os_version" - public static let ENGAGEMENT_TIMESTAMP = "_engagement_time_msec" - public static let ENTRANCES = "_entrances" - public static let PREVIOUS_SCREEN_ID = "_previous_screen_id" - public static let PREVIOUS_SCREEN_NAME = "_previous_screen_name" - public static let SCREEN_ID = "_screen_id" - public static let SCREEN_NAME = "_screen_name" + static let USER_ID = "_user_id" + static let USER_FIRST_TOUCH_TIMESTAMP = "_user_first_touch_timestamp" + static let PREVIOUS_APP_VERSION = "_previous_app_version" + static let PREVIOUS_OS_VERSION = "_previous_os_version" + static let ENGAGEMENT_TIMESTAMP = "_engagement_time_msec" + static let ENTRANCES = "_entrances" + static let PREVIOUS_SCREEN_ID = "_previous_screen_id" + static let PREVIOUS_SCREEN_NAME = "_previous_screen_name" + static let SCREEN_ID = "_screen_id" + static let SCREEN_NAME = "_screen_name" } enum User { - public static let USER_ID_NIL = "_clickstream_user_id_nil" - public static let USER_ID_EMPTY = "_clickstream_user_id_empty" + static let USER_ID_NIL = "_clickstream_user_id_nil" + static let USER_ID_EMPTY = "_clickstream_user_id_empty" } enum Limit { /// max event type length - public static let MAX_EVENT_TYPE_LENGTH = 50 + static let MAX_EVENT_TYPE_LENGTH = 50 /// max limit of single event attribute number. - public static let MAX_NUM_OF_ATTRIBUTES = 500 + static let MAX_NUM_OF_ATTRIBUTES = 500 /// max limit of single event user attribute number. - public static let MAX_NUM_OF_USER_ATTRIBUTES = 100 + static let MAX_NUM_OF_USER_ATTRIBUTES = 100 /// max limit of attribute name character length. - public static let MAX_LENGTH_OF_NAME = 50 + static let MAX_LENGTH_OF_NAME = 50 /// max limit of attribute value character length. - public static let MAX_LENGTH_OF_VALUE = 1_024 + static let MAX_LENGTH_OF_VALUE = 1_024 /// max limit of user attribute value character length. - public static let MAX_LENGTH_OF_USER_VALUE = 256 + static let MAX_LENGTH_OF_USER_VALUE = 256 /// max limit of one batch event number. - public static let MAX_EVENT_NUMBER_OF_BATCH = 100 + static let MAX_EVENT_NUMBER_OF_BATCH = 100 /// max limit of error attribute value length. - public static let MAX_LENGTH_OF_ERROR_VALUE = 256 + static let MAX_LENGTH_OF_ERROR_VALUE = 256 } enum PresetEvent { - public static let SESSION_START = "_session_start" - public static let PROFILE_SET = "_profile_set" - public static let APP_UPDATE = "_app_update" - public static let OS_UPDATE = "_os_update" - public static let FIRST_OPEN = "_first_open" - public static let USER_ENGAGEMENT = "_user_engagement" - public static let SCREEN_VIEW = "_screen_view" + static let SESSION_START = "_session_start" + static let PROFILE_SET = "_profile_set" + static let APP_UPDATE = "_app_update" + static let OS_UPDATE = "_os_update" + static let FIRST_OPEN = "_first_open" + static let USER_ENGAGEMENT = "_user_engagement" + static let SCREEN_VIEW = "_screen_view" } enum ErrorType { - public static let ATTRIBUTE_NAME_INVALID = "_error_name_invalid" - public static let ATTRIBUTE_NAME_LENGTH_EXCEED = "_error_name_length_exceed" - public static let ATTRIBUTE_VALUE_LENGTH_EXCEED = "_error_value_length_exceed" - public static let ATTRIBUTE_SIZE_EXCEED = "_error_attribute_size_exceed" + static let ATTRIBUTE_NAME_INVALID = "_error_name_invalid" + static let ATTRIBUTE_NAME_LENGTH_EXCEED = "_error_name_length_exceed" + static let ATTRIBUTE_VALUE_LENGTH_EXCEED = "_error_value_length_exceed" + static let ATTRIBUTE_SIZE_EXCEED = "_error_attribute_size_exceed" } class EventError { diff --git a/Sources/Clickstream/PackageInfo.swift b/Sources/Clickstream/PackageInfo.swift index 75d2fe1..c034738 100644 --- a/Sources/Clickstream/PackageInfo.swift +++ b/Sources/Clickstream/PackageInfo.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -public enum PackageInfo { +enum PackageInfo { /// the clickstream analytics iOS sdk version /// note: update and align the version with new tag version before committing new tag - public static let version = "0.4.0" + static let version = "0.4.1" } diff --git a/Sources/Clickstream/Support/Utils/ClickstreamLogger.swift b/Sources/Clickstream/Support/Utils/ClickstreamLogger.swift index 0e8c65e..70e0d9b 100644 --- a/Sources/Clickstream/Support/Utils/ClickstreamLogger.swift +++ b/Sources/Clickstream/Support/Utils/ClickstreamLogger.swift @@ -7,12 +7,12 @@ import Amplify -public protocol ClickstreamLogger { +protocol ClickstreamLogger { static var log: Logger { get } var log: Logger { get } } -public extension ClickstreamLogger { +extension ClickstreamLogger { static var log: Logger { Amplify.Logging.logger(forCategory: String(describing: self), logLevel: LogLevel.debug) } diff --git a/Tests/ClickstreamTests/Clickstream/EventRecorderTest.swift b/Tests/ClickstreamTests/Clickstream/EventRecorderTest.swift index acc1772..64900d8 100644 --- a/Tests/ClickstreamTests/Clickstream/EventRecorderTest.swift +++ b/Tests/ClickstreamTests/Clickstream/EventRecorderTest.swift @@ -42,7 +42,7 @@ class EventRecorderTest: XCTestCase { sendEventsInterval: 10_000, isTrackAppExceptionEvents: false, isCompressEvents: false) - contextConfiguration.isLogEvents = true + contextConfiguration.isLogEvents = false clickstream = try ClickstreamContext(with: contextConfiguration) clickstreamEvent = ClickstreamEvent(eventType: "testEvent", appId: testAppId, @@ -342,7 +342,7 @@ class EventRecorderTest: XCTestCase { eventRecorder.submitEvents() XCTAssertEqual(1, eventRecorder.queue.operationCount) - Thread.sleep(forTimeInterval: 0.1) + Thread.sleep(forTimeInterval: 0.3) let totalEvent = try dbUtil.getEventCount() XCTAssertEqual(0, totalEvent) XCTAssertTrue(eventRecorder.bundleSequenceId == 3) @@ -359,7 +359,7 @@ class EventRecorderTest: XCTestCase { } eventRecorder.submitEvents() XCTAssertEqual(1, eventRecorder.queue.operationCount) - Thread.sleep(forTimeInterval: 0.2) + Thread.sleep(forTimeInterval: 0.3) let totalEvent = try dbUtil.getEventCount() XCTAssertTrue(totalEvent > 0) } @@ -376,7 +376,11 @@ class EventRecorderTest: XCTestCase { eventRecorder.submitEvents() eventRecorder.submitEvents() XCTAssertEqual(2, eventRecorder.queue.operationCount) - Thread.sleep(forTimeInterval: 1) + if clickstream.systemInfo.model == "iPhone 14 Pro" { + Thread.sleep(forTimeInterval: 15) + } else { + Thread.sleep(forTimeInterval: 0.5) + } let totalEvent = try dbUtil.getEventCount() XCTAssertEqual(0, totalEvent) } diff --git a/Tests/ClickstreamTests/Clickstream/SessionClientTests.swift b/Tests/ClickstreamTests/Clickstream/SessionClientTests.swift index 97f1b39..816bed8 100644 --- a/Tests/ClickstreamTests/Clickstream/SessionClientTests.swift +++ b/Tests/ClickstreamTests/Clickstream/SessionClientTests.swift @@ -83,6 +83,7 @@ class SessionClientTests: XCTestCase { func testGoBackground() { XCTAssertTrue(sessionClient.getCurrentSession() == nil) activityTracker.callback?(.runningInForeground) + Thread.sleep(forTimeInterval: 0.1) activityTracker.callback?(.runningInBackground) let session = sessionClient.getCurrentSession()! XCTAssertTrue(session.pauseTime != nil) diff --git a/Tests/ClickstreamTests/ClickstreamAnalyticsTest.swift b/Tests/ClickstreamTests/ClickstreamAnalyticsTest.swift index 981e060..1c2820c 100644 --- a/Tests/ClickstreamTests/ClickstreamAnalyticsTest.swift +++ b/Tests/ClickstreamTests/ClickstreamAnalyticsTest.swift @@ -21,4 +21,16 @@ class ClickstreamAnalyticsTest: XCTestCase { } } } + + func testThrowMissingConfigureFileWhenInitSDKForObjc() throws { + do { + try ClickstreamObjc.initSDK() + XCTFail("Should have thrown a invalidAmplifyConfigurationFile error, if no configuration file is specified") + } catch { + guard case ConfigurationError.invalidAmplifyConfigurationFile = error else { + XCTFail("Should have thrown a invalidAmplifyConfigurationFile error") + return + } + } + } } diff --git a/Tests/ClickstreamTests/IntegrationTest.swift b/Tests/ClickstreamTests/IntegrationTest.swift index ff3f8ec..bca8dc4 100644 --- a/Tests/ClickstreamTests/IntegrationTest.swift +++ b/Tests/ClickstreamTests/IntegrationTest.swift @@ -66,16 +66,17 @@ class IntegrationTest: XCTestCase { "Successful": true, "Score": 90 ] - let event = BaseClickstreamEvent(name: "userId", attribute: attribute) - ClickstreamAnalytics.recordEvent(event: event) - Thread.sleep(forTimeInterval: 0.5) + ClickstreamAnalytics.recordEvent(eventName: "userId", attributes: attribute) + ClickstreamAnalytics.flushEvents() + Thread.sleep(forTimeInterval: 0.2) let eventCount = try eventRecorder.dbUtil.getEventCount() XCTAssertEqual(0, eventCount) } func testRecordOneEventWithNameSuccess() throws { ClickstreamAnalytics.recordEvent(eventName: "testEvent") - Thread.sleep(forTimeInterval: 0.5) + ClickstreamAnalytics.flushEvents() + Thread.sleep(forTimeInterval: 0.2) let eventCount = try eventRecorder.dbUtil.getEventCount() XCTAssertEqual(0, eventCount) } @@ -175,20 +176,90 @@ class IntegrationTest: XCTestCase { } func testModifyEndpoint() throws { - let configuration = try ClickstreamAnalytics.getClickStreamConfiguration()! + let configuration = try ClickstreamAnalytics.getClickstreamConfiguration() configuration.endpoint = testFailEndpoint ClickstreamAnalytics.recordEvent(eventName: "testEvent") - Thread.sleep(forTimeInterval: 2) + ClickstreamAnalytics.flushEvents() + Thread.sleep(forTimeInterval: 0.2) let eventCount = try eventRecorder.dbUtil.getEventCount() XCTAssertNotEqual(0, eventCount) } func testModifyConfiguration() throws { - let configuration = try ClickstreamAnalytics.getClickStreamConfiguration()! + let configuration = try ClickstreamAnalytics.getClickstreamConfiguration() + configuration.isCompressEvents = true + configuration.isLogEvents = true + configuration.authCookie = "authCookie" + ClickstreamAnalytics.recordEvent(eventName: "testEvent") + ClickstreamAnalytics.flushEvents() + Thread.sleep(forTimeInterval: 0.2) + let eventCount = try eventRecorder.dbUtil.getEventCount() + XCTAssertEqual(0, eventCount) + } + + // MARK: - Objc test + + func testRecordEventForObjc() throws { + let attribute: NSDictionary = [ + "Channel": "SMS", + "Successful": true, + "Score": 90.1, + "level": 5 + ] + ClickstreamObjc.recordEvent("userId") + ClickstreamObjc.recordEvent("testEvent", attribute) + ClickstreamObjc.flushEvents() + Thread.sleep(forTimeInterval: 0.2) + let eventCount = try eventRecorder.dbUtil.getEventCount() + XCTAssertEqual(0, eventCount) + } + + func testGlobalAttributeForObjc() throws { + let attribute: NSDictionary = [ + "Channel": "SMS", + "Successful": true, + "Score": 90.1, + "level": 5 + ] + ClickstreamObjc.addGlobalAttributes(attribute) + ClickstreamObjc.deleteGlobalAttributes(["Channel"]) + ClickstreamObjc.recordEvent("testEvent") + Thread.sleep(forTimeInterval: 0.1) + let testEvent = try getTestEvent() + let eventAttribute = testEvent["attributes"] as! [String: Any] + XCTAssertNil(eventAttribute["Channel"]) + XCTAssertEqual(5, eventAttribute["level"] as! Int) + XCTAssertEqual(90.1, eventAttribute["Score"] as! Double) + XCTAssertEqual(true, eventAttribute["Successful"] as! Bool) + } + + func testUserAttributeForObjc() throws { + ClickstreamObjc.setUserId("3231") + let userAttribute: NSDictionary = [ + "_user_age": 21, + "isFirstOpen": true, + "score": 85.2, + "_user_name": "carl" + ] + ClickstreamObjc.addUserAttributes(userAttribute) + ClickstreamObjc.recordEvent("testEvent") + Thread.sleep(forTimeInterval: 0.1) + let testEvent = try getTestEvent() + let userInfo = testEvent["user"] as! [String: Any] + XCTAssertEqual(21, (userInfo["_user_age"] as! JsonObject)["value"] as! Int) + XCTAssertEqual(true, (userInfo["isFirstOpen"] as! JsonObject)["value"] as! Bool) + XCTAssertEqual(85.2, (userInfo["score"] as! JsonObject)["value"] as! Double) + XCTAssertEqual("carl", (userInfo["_user_name"] as! JsonObject)["value"] as! String) + XCTAssertEqual("3231", (userInfo[Event.ReservedAttribute.USER_ID] as! JsonObject)["value"] as! String) + } + + func testModifyConfigurationForObjc() throws { + let configuration = try ClickstreamObjc.getClickstreamConfiguration() configuration.isCompressEvents = true configuration.authCookie = "authCookie" ClickstreamAnalytics.recordEvent(eventName: "testEvent") - Thread.sleep(forTimeInterval: 0.5) + ClickstreamAnalytics.flushEvents() + Thread.sleep(forTimeInterval: 0.2) let eventCount = try eventRecorder.dbUtil.getEventCount() XCTAssertEqual(0, eventCount) }