From 53f66dc2dc251460c4b14e240c0a8e51fb3e8240 Mon Sep 17 00:00:00 2001 From: Christina Sund Date: Thu, 25 Jun 2020 08:01:47 -0700 Subject: [PATCH] Update parameter mappings within logEvent to send parameters outside of expected param_ prefix (#6) Co-authored-by: Christina --- Cartfile.resolved | 4 +- Sources/FirebaseConstants.swift | 30 ++-- Sources/FirebaseRemoteCommand.swift | 60 ++++---- TealiumFirebase.podspec | 8 +- TealiumFirebase.xcodeproj/project.pbxproj | 1 + TealiumFirebaseExample/Podfile | 4 +- TealiumFirebaseExample/Podfile.lock | 48 +++---- .../project.pbxproj | 58 ++++---- .../TealiumHelper.swift | 2 +- Tests/FirebaseCommandTests.swift | 133 ++++++++++++++++++ Tests/FirebaseTrackerTests.swift | 22 +++ 11 files changed, 260 insertions(+), 110 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 327cd3e..e2a02b8 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ -binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json" "6.24.0" +binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json" "6.27.0" binary "https://tags.tiqcdn.com/dle/tealiummobile/tealium-ios-carthage/tealium-carthage-plcrashreporter.json?_cb=2" "1.4.0" -github "tealium/tealium-swift" "1.9.4" +github "tealium/tealium-swift" "1.9.5" diff --git a/Sources/FirebaseConstants.swift b/Sources/FirebaseConstants.swift index fa49e3c..994359b 100644 --- a/Sources/FirebaseConstants.swift +++ b/Sources/FirebaseConstants.swift @@ -10,26 +10,26 @@ import Foundation enum FirebaseConstants { + static let commandName = "command_name" static let separator: Character = "," static let commandId = "firebaseAnalytics" static let description = "Firebase Remote Command" static let errorPrefix = "Tealium Firebase: " - enum Keys: String { - case commandName = "command_name" - case sessionTimeout = "firebase_session_timeout_seconds" - case minSeconds = "firebase_session_minimum_seconds" - case analyticsEnabled = "firebase_analytics_enabled" - case logLevel = "firebase_log_level" - case eventName = "firebase_event_name" - case eventParams = "firebase_event_params" - case screenName = "firebase_screen_name" - case screenClass = "firebase_screen_class" - case userPropertyName = "firebase_property_name" - case userPropertyValue = "firebase_property_value" - case userId = "firebase_user_id" - case paramItems = "param_items" - case items = "items" + enum Keys { + static let sessionTimeout = "firebase_session_timeout_seconds" + static let minSeconds = "firebase_session_minimum_seconds" + static let analyticsEnabled = "firebase_analytics_enabled" + static let logLevel = "firebase_log_level" + static let eventName = "firebase_event_name" + static let eventParams = "firebase_event_params" + static let screenName = "firebase_screen_name" + static let screenClass = "firebase_screen_class" + static let userPropertyName = "firebase_property_name" + static let userPropertyValue = "firebase_property_value" + static let userId = "firebase_user_id" + static let paramItems = "param_items" + static let items = "items" } enum Commands: String { diff --git a/Sources/FirebaseRemoteCommand.swift b/Sources/FirebaseRemoteCommand.swift index b83b215..64f6814 100644 --- a/Sources/FirebaseRemoteCommand.swift +++ b/Sources/FirebaseRemoteCommand.swift @@ -30,7 +30,7 @@ public class FirebaseRemoteCommand { return TealiumRemoteCommand(commandId: FirebaseConstants.commandId, description: FirebaseConstants.description) { response in let payload = response.payload() - guard let command = payload[.commandName] as? String else { + guard let command = payload[FirebaseConstants.commandName] as? String else { return } let commands = command.split(separator: FirebaseConstants.separator) @@ -50,56 +50,58 @@ public class FirebaseRemoteCommand { var firebaseSessionTimeout: TimeInterval? var firebaseSessionMinimumSeconds: TimeInterval? var firebaseAnalyticsEnabled: Bool? - if let sessionTimeout = payload[.sessionTimeout] as? String { + if let sessionTimeout = payload[FirebaseConstants.Keys.sessionTimeout] as? String { firebaseSessionTimeout = TimeInterval(sessionTimeout) } - if let sessionMinimumSeconds = payload[.minSeconds] as? String { + if let sessionMinimumSeconds = payload[FirebaseConstants.Keys.minSeconds] as? String { firebaseSessionMinimumSeconds = TimeInterval(sessionMinimumSeconds) } - if let analyticsEnabled = payload[.analyticsEnabled] as? String { + if let analyticsEnabled = payload[FirebaseConstants.Keys.analyticsEnabled] as? String { firebaseAnalyticsEnabled = Bool(analyticsEnabled) } - if let logLevel = payload[.logLevel] as? String { + if let logLevel = payload[FirebaseConstants.Keys.logLevel] as? String { firebaseLogLevel = self.parseLogLevel(logLevel) } self.firebaseTracker.createAnalyticsConfig(firebaseSessionTimeout, firebaseSessionMinimumSeconds, firebaseAnalyticsEnabled, firebaseLogLevel) case .logEvent: - guard let name = payload[.eventName] as? String else { + guard let name = payload[FirebaseConstants.Keys.eventName] as? String else { return } let eventName = self.mapEvent(name) var normalizedParams = [String: Any]() - guard let params = payload[.eventParams] as? [String: Any] else { + guard let params = payload[FirebaseConstants.Keys.eventParams] as? [String: Any] else { return self.firebaseTracker.logEvent(eventName, nil) } - if let items = params[.paramItems] as? [[String: Any]] { + if let items = params[FirebaseConstants.Keys.paramItems] as? [[String: Any]] { var tempItems = [[String: Any]]() var item = [String: Any]() items.forEach { - item = eventParameters.map($0) + item = $0.mapParams() tempItems.append(item) } - normalizedParams[.items] = tempItems + normalizedParams[FirebaseConstants.Keys.items] = tempItems + } + normalizedParams += params.mapParams().filter { + $0.key != FirebaseConstants.Keys.paramItems } - normalizedParams += eventParameters.map(params) self.firebaseTracker.logEvent(eventName, normalizedParams) case .setScreenName: - guard let screenName = payload[.screenName] as? String else { + guard let screenName = payload[FirebaseConstants.Keys.screenName] as? String else { if firebaseLogLevel == .debug { print("\(FirebaseConstants.errorPrefix)`screen_name` required for setScreenName.") } return } - let screenClass = payload[.screenClass] as? String + let screenClass = payload[FirebaseConstants.Keys.screenClass] as? String self.firebaseTracker.setScreenName(screenName, screenClass) case .setUserProperty: - guard let propertyName = payload[.userPropertyName] as? String else { + guard let propertyName = payload[FirebaseConstants.Keys.userPropertyName] as? String else { if firebaseLogLevel == .debug { print("\(FirebaseConstants.errorPrefix)`firebase_property_name` required for setUserProperty.") } return } - guard let propertyValue = payload[.userPropertyValue] as? String else { + guard let propertyValue = payload[FirebaseConstants.Keys.userPropertyValue] as? String else { if firebaseLogLevel == .debug { print("\(FirebaseConstants.errorPrefix)`firebase_property_value` required for setUserProperty.") } @@ -107,7 +109,7 @@ public class FirebaseRemoteCommand { } self.firebaseTracker.setUserProperty(propertyName, value: propertyValue) case .setUserId: - guard let userId = payload[.userId] as? String else { + guard let userId = payload[FirebaseConstants.Keys.userId] as? String else { if firebaseLogLevel == .debug { print("\(FirebaseConstants.errorPrefix)`firebase_user_id` required for setUserId.") } @@ -183,7 +185,7 @@ public class FirebaseRemoteCommand { return eventsMap[eventName] ?? eventName } - let eventParameters = [ + static let eventParameters = [ "param_achievement_id": AnalyticsParameterAchievementID, "param_ad_network_click_id": AnalyticsParameterAdNetworkClickID, "param_affiliation": AnalyticsParameterAffiliation, @@ -245,26 +247,18 @@ public class FirebaseRemoteCommand { "param_virtual_currency_name": AnalyticsParameterVirtualCurrencyName, "param_user_signup_method": AnalyticsUserPropertySignUpMethod ] + + static func mapParam(_ param: String) -> String { + FirebaseRemoteCommand.eventParameters[param] ?? param + } } -fileprivate extension Dictionary where Key == String, Value == String { - func map(_ payload: [String: Any]) -> [String: Any] { +extension Dictionary where Key == String, Value == Any { + func mapParams() -> [String: Any] { return self.reduce(into: [String: Any]()) { result, dictionary in - if payload[dictionary.key] != nil { - result[dictionary.value] = payload[dictionary.key] - } - } - } -} - -fileprivate extension Dictionary where Key: ExpressibleByStringLiteral { - subscript(key: FirebaseConstants.Keys) -> Value? { - get { - return self[key.rawValue as! Key] - } - set { - self[key.rawValue as! Key] = newValue + let newKey = FirebaseRemoteCommand.mapParam(dictionary.key) + result[newKey] = dictionary.value } } } diff --git a/TealiumFirebase.podspec b/TealiumFirebase.podspec index 30582be..37d64ab 100644 --- a/TealiumFirebase.podspec +++ b/TealiumFirebase.podspec @@ -3,7 +3,7 @@ Pod::Spec.new do |s| # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.name = "TealiumFirebase" s.module_name = "TealiumFirebase" - s.version = "1.1.0" + s.version = "1.1.1" s.summary = "Tealium Swift and Firebase integration" s.description = <<-DESC Tealium's integration with Firebase for iOS. @@ -19,7 +19,7 @@ Pod::Spec.new do |s| s.social_media_url = "https://twitter.com/tealium" # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - s.swift_version = "4.2" + s.swift_version = "5.0" s.platform = :ios, "10.0" s.ios.deployment_target = "10.0" @@ -35,6 +35,6 @@ Pod::Spec.new do |s| s.ios.dependency 'tealium-swift/TealiumRemoteCommands', '~> 1.9' s.ios.dependency 'tealium-swift/TealiumDelegate', '~> 1.9' s.ios.dependency 'tealium-swift/TealiumTagManagement', '~> 1.9' - s.dependency 'Firebase', '~> 6.24' - s.dependency 'FirebaseAnalytics', '~> 6.5' + s.dependency 'Firebase', '~> 6.2' + s.dependency 'FirebaseAnalytics', '~> 6.6' end diff --git a/TealiumFirebase.xcodeproj/project.pbxproj b/TealiumFirebase.xcodeproj/project.pbxproj index 06f1e4f..29c2cc2 100644 --- a/TealiumFirebase.xcodeproj/project.pbxproj +++ b/TealiumFirebase.xcodeproj/project.pbxproj @@ -304,6 +304,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = CF17EB4A22F0E3D700C6086B; productRefGroup = CF17EB5522F0E3D700C6086B /* Products */; diff --git a/TealiumFirebaseExample/Podfile b/TealiumFirebaseExample/Podfile index 7720c2c..24157b6 100644 --- a/TealiumFirebaseExample/Podfile +++ b/TealiumFirebaseExample/Podfile @@ -1,12 +1,12 @@ # Uncomment the next line to define a global platform for your project -# platform :ios, '9.0' +platform :ios, '10.0' target 'TealiumFirebaseExample' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for TealiumFirebaseExample - pod 'TealiumFirebase', '~> 1.1' + pod 'TealiumFirebase', :path=> '../' pod 'tealium-swift/TealiumLogger', '~> 1.9' pod 'tealium-swift/TealiumAppData', '~> 1.9' pod 'tealium-swift/TealiumDeviceData', '~> 1.9' diff --git a/TealiumFirebaseExample/Podfile.lock b/TealiumFirebaseExample/Podfile.lock index 7f968ea..697a624 100644 --- a/TealiumFirebaseExample/Podfile.lock +++ b/TealiumFirebaseExample/Podfile.lock @@ -1,21 +1,21 @@ PODS: - - Firebase (6.24.0): - - Firebase/Core (= 6.24.0) - - Firebase/Core (6.24.0): + - Firebase (6.26.0): + - Firebase/Core (= 6.26.0) + - Firebase/Core (6.26.0): - Firebase/CoreOnly - - FirebaseAnalytics (= 6.5.0) - - Firebase/CoreOnly (6.24.0): - - FirebaseCore (= 6.7.0) - - FirebaseAnalytics (6.5.0): + - FirebaseAnalytics (= 6.6.0) + - Firebase/CoreOnly (6.26.0): + - FirebaseCore (= 6.7.2) + - FirebaseAnalytics (6.6.0): - FirebaseCore (~> 6.7) - - FirebaseInstallations (~> 1.2) - - GoogleAppMeasurement (= 6.5.0) + - FirebaseInstallations (~> 1.3) + - GoogleAppMeasurement (= 6.6.0) - GoogleUtilities/AppDelegateSwizzler (~> 6.0) - GoogleUtilities/MethodSwizzler (~> 6.0) - GoogleUtilities/Network (~> 6.0) - "GoogleUtilities/NSData+zlib (~> 6.0)" - nanopb (~> 1.30905.0) - - FirebaseCore (6.7.0): + - FirebaseCore (6.7.2): - FirebaseCoreDiagnostics (~> 1.3) - FirebaseCoreDiagnosticsInterop (~> 1.2) - GoogleUtilities/Environment (~> 6.5) @@ -27,18 +27,18 @@ PODS: - GoogleUtilities/Logger (~> 6.5) - nanopb (~> 1.30905.0) - FirebaseCoreDiagnosticsInterop (1.2.0) - - FirebaseInstallations (1.2.0): + - FirebaseInstallations (1.3.0): - FirebaseCore (~> 6.6) - GoogleUtilities/Environment (~> 6.6) - GoogleUtilities/UserDefaults (~> 6.6) - PromisesObjC (~> 1.2) - - GoogleAppMeasurement (6.5.0): + - GoogleAppMeasurement (6.6.0): - GoogleUtilities/AppDelegateSwizzler (~> 6.0) - GoogleUtilities/MethodSwizzler (~> 6.0) - GoogleUtilities/Network (~> 6.0) - "GoogleUtilities/NSData+zlib (~> 6.0)" - nanopb (~> 1.30905.0) - - GoogleDataTransport (6.1.0) + - GoogleDataTransport (6.2.1) - GoogleDataTransportCCTSupport (3.1.0): - GoogleDataTransport (~> 6.1) - nanopb (~> 1.30905.0) @@ -82,9 +82,9 @@ PODS: - tealium-swift/Core - tealium-swift/TealiumTagManagement (1.9.4): - tealium-swift/Core - - TealiumFirebase (1.1.0): - - Firebase (~> 6.24) - - FirebaseAnalytics (~> 6.5) + - TealiumFirebase (1.1.1): + - Firebase (~> 6.2) + - FirebaseAnalytics (~> 6.6) - tealium-swift/Core (~> 1.9) - tealium-swift/TealiumDelegate (~> 1.9) - tealium-swift/TealiumRemoteCommands (~> 1.9) @@ -118,21 +118,21 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - Firebase: b28e55c60efd98963cd9011fe2fac5a10c2ba124 - FirebaseAnalytics: 7386fc2176e3f93ad8ef34b5b1f2b33a891e4962 - FirebaseCore: e610482f64097b0e9f056cd97bc6b33dfabcbb6a + Firebase: 7cf5f9c67f03cb3b606d1d6535286e1080e57eb6 + FirebaseAnalytics: 96634d356482d4f3af8fe459a0ebf19a99c71b75 + FirebaseCore: f42e5e5f382cdcf6b617ed737bf6c871a6947b17 FirebaseCoreDiagnostics: 4a773a47bd83bbd5a9b1ccf1ce7caa8b2d535e67 FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 - FirebaseInstallations: 2119fb3e46b0a88bfdbf12562f855ee3252462fa - GoogleAppMeasurement: 4c644d86835d827bab30ab6aabb9ecaf1f500735 - GoogleDataTransport: f6f8eba931df03ebd2232ff4645aa85f8f47b5ab + FirebaseInstallations: 6f5f680e65dc374397a483c32d1799ba822a395b + GoogleAppMeasurement: 67458367830514fb20fd9e233496f1eef9d90185 + GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020 GoogleDataTransportCCTSupport: d70a561f7d236af529fee598835caad5e25f6d3d GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1 nanopb: c43f40fadfe79e8b8db116583945847910cbabc9 PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 tealium-swift: c478175eadd99de290a65c5c2cc38a7bb86ac28c - TealiumFirebase: e85bf3e7fc73eea3f6bfc07bbb4ae6a5a63ec411 + TealiumFirebase: 708529ed17cda7c60016bda700c1611f3b2bc4cd -PODFILE CHECKSUM: 393c580155612651d05ca3506f7427eb51a6c6c0 +PODFILE CHECKSUM: 7d856fa4357cf2dd7d577dfa2f1f6eaa8baa0e3c COCOAPODS: 1.9.1 diff --git a/TealiumFirebaseExample/TealiumFirebaseExample.xcodeproj/project.pbxproj b/TealiumFirebaseExample/TealiumFirebaseExample.xcodeproj/project.pbxproj index 25ad642..222f5e9 100644 --- a/TealiumFirebaseExample/TealiumFirebaseExample.xcodeproj/project.pbxproj +++ b/TealiumFirebaseExample/TealiumFirebaseExample.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 159814928FAE96EF342922AA /* Pods_TealiumFirebaseExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51BB94FAD8600995FA89F3DD /* Pods_TealiumFirebaseExample.framework */; }; + 54A9C0B46D247D69A5186046 /* Pods_TealiumFirebaseExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2AAB7CECF6DCD9B39B803633 /* Pods_TealiumFirebaseExample.framework */; }; CFC34EF022F8D7EB00E8723F /* REPLACE-ME.md in Resources */ = {isa = PBXBuildFile; fileRef = CFC34EEF22F8D7EB00E8723F /* REPLACE-ME.md */; }; CFDD8B2E22E1195800358234 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFDD8B2D22E1195800358234 /* AppDelegate.swift */; }; CFDD8B3322E1195800358234 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CFDD8B3122E1195800358234 /* Main.storyboard */; }; @@ -31,9 +31,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 51BB94FAD8600995FA89F3DD /* Pods_TealiumFirebaseExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TealiumFirebaseExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 807D97369EE6798AA9387C9E /* Pods-TealiumFirebaseExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TealiumFirebaseExample.debug.xcconfig"; path = "Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample.debug.xcconfig"; sourceTree = ""; }; - A1F3ECCDB5CC8E292C98B272 /* Pods-TealiumFirebaseExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TealiumFirebaseExample.release.xcconfig"; path = "Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample.release.xcconfig"; sourceTree = ""; }; + 2AAB7CECF6DCD9B39B803633 /* Pods_TealiumFirebaseExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TealiumFirebaseExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 65ED983B8D91B3FF8B696EC8 /* Pods-TealiumFirebaseExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TealiumFirebaseExample.debug.xcconfig"; path = "Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample.debug.xcconfig"; sourceTree = ""; }; CFC34EEF22F8D7EB00E8723F /* REPLACE-ME.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "REPLACE-ME.md"; sourceTree = ""; }; CFDD8B2A22E1195800358234 /* TealiumFirebaseExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TealiumFirebaseExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; CFDD8B2D22E1195800358234 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -56,6 +55,7 @@ CFDD8B7D22E2800A00358234 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = TealiumFirebaseExample/TealiumFirebaseExample/Base.lproj/Ecommerce.storyboard; sourceTree = ""; }; CFDD8BC322E5344F00358234 /* ProductCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductCell.swift; sourceTree = ""; }; CFDD8BC522E670E500358234 /* TealiumHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TealiumHelper.swift; sourceTree = ""; }; + F0E2E69B6C74DA773E2FF055 /* Pods-TealiumFirebaseExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TealiumFirebaseExample.release.xcconfig"; path = "Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -63,7 +63,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 159814928FAE96EF342922AA /* Pods_TealiumFirebaseExample.framework in Frameworks */, + 54A9C0B46D247D69A5186046 /* Pods_TealiumFirebaseExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -73,8 +73,8 @@ 7B241B4231FCD61ED237BA4A /* Pods */ = { isa = PBXGroup; children = ( - 807D97369EE6798AA9387C9E /* Pods-TealiumFirebaseExample.debug.xcconfig */, - A1F3ECCDB5CC8E292C98B272 /* Pods-TealiumFirebaseExample.release.xcconfig */, + 65ED983B8D91B3FF8B696EC8 /* Pods-TealiumFirebaseExample.debug.xcconfig */, + F0E2E69B6C74DA773E2FF055 /* Pods-TealiumFirebaseExample.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -85,7 +85,7 @@ CFDD8B2C22E1195800358234 /* TealiumFirebaseExample */, CFDD8B2B22E1195800358234 /* Products */, 7B241B4231FCD61ED237BA4A /* Pods */, - D4F46630F15CD962C7E6B19F /* Frameworks */, + E877B603A3BA0AD0CAC95674 /* Frameworks */, ); sourceTree = ""; }; @@ -141,10 +141,10 @@ path = Storyboards; sourceTree = ""; }; - D4F46630F15CD962C7E6B19F /* Frameworks */ = { + E877B603A3BA0AD0CAC95674 /* Frameworks */ = { isa = PBXGroup; children = ( - 51BB94FAD8600995FA89F3DD /* Pods_TealiumFirebaseExample.framework */, + 2AAB7CECF6DCD9B39B803633 /* Pods_TealiumFirebaseExample.framework */, ); name = Frameworks; sourceTree = ""; @@ -156,11 +156,11 @@ isa = PBXNativeTarget; buildConfigurationList = CFDD8B3C22E1195800358234 /* Build configuration list for PBXNativeTarget "TealiumFirebaseExample" */; buildPhases = ( - 6634AE4F5255C84EA770B6C5 /* [CP] Check Pods Manifest.lock */, + FCF68A696A0208B7CDA52AB7 /* [CP] Check Pods Manifest.lock */, CFDD8B2622E1195800358234 /* Sources */, CFDD8B2722E1195800358234 /* Frameworks */, CFDD8B2822E1195800358234 /* Resources */, - 864A90724949C7D12D32AB8C /* [CP] Embed Pods Frameworks */, + 25CBB7542BFE9B1AC0EC12B0 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -221,43 +221,43 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 6634AE4F5255C84EA770B6C5 /* [CP] Check Pods Manifest.lock */ = { + 25CBB7542BFE9B1AC0EC12B0 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-TealiumFirebaseExample-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 864A90724949C7D12D32AB8C /* [CP] Embed Pods Frameworks */ = { + FCF68A696A0208B7CDA52AB7 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-TealiumFirebaseExample-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TealiumFirebaseExample/Pods-TealiumFirebaseExample-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -441,7 +441,7 @@ }; CFDD8B3D22E1195800358234 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 807D97369EE6798AA9387C9E /* Pods-TealiumFirebaseExample.debug.xcconfig */; + baseConfigurationReference = 65ED983B8D91B3FF8B696EC8 /* Pods-TealiumFirebaseExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; @@ -461,7 +461,7 @@ }; CFDD8B3E22E1195800358234 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A1F3ECCDB5CC8E292C98B272 /* Pods-TealiumFirebaseExample.release.xcconfig */; + baseConfigurationReference = F0E2E69B6C74DA773E2FF055 /* Pods-TealiumFirebaseExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; diff --git a/TealiumFirebaseExample/TealiumFirebaseExample/TealiumHelper.swift b/TealiumFirebaseExample/TealiumFirebaseExample/TealiumHelper.swift index cf7ba7b..cff7b5c 100644 --- a/TealiumFirebaseExample/TealiumFirebaseExample/TealiumHelper.swift +++ b/TealiumFirebaseExample/TealiumFirebaseExample/TealiumHelper.swift @@ -13,7 +13,7 @@ import TealiumFirebase enum TealiumConfiguration { static let account = "tealiummobile" static let profile = "firebase-tag" - static let environment = "qa" + static let environment = "dev" } class TealiumHelper { diff --git a/Tests/FirebaseCommandTests.swift b/Tests/FirebaseCommandTests.swift index 8401a93..6e6cf4c 100644 --- a/Tests/FirebaseCommandTests.swift +++ b/Tests/FirebaseCommandTests.swift @@ -118,5 +118,138 @@ class FirebaseCommandTests: XCTestCase { } } + + func testMapParam() { + acceptedTealiumVariableNames = ["param_achievement_id", + "param_ad_network_click_id", + "param_affiliation", + "param_cp1", + "param_campaign", + "param_character", + "param_checkout_option", + "param_checkout_step", + "param_content", + "param_content_type", + "param_coupon", + "param_creative_name", + "param_creative_slot", + "param_currency", + "param_destination", + "param_end_date", + "param_flight_number", + "param_group_id", + "param_index", + "param_item_brand", + "param_item_category", + "param_item_id", + "param_item_list", + "param_item_location_id", + "param_item_name", + "param_item_variant", + "param_level", + "param_location", + "param_medium", + "param_number_nights", + "param_number_pax", + "param_number_rooms", + "param_origin", + "param_price", + "param_quantity", + "param_score", + "param_search_term", + "param_shipping", + "param_signup_method", + "param_source", + "param_start_date", + "param_tax", + "param_term", + "param_transaction_id", + "param_travel_class", + "param_value", + "param_virtual_currency_name", + "param_user_signup_method"] + firebaseParameterNames = [AnalyticsParameterAchievementID, + AnalyticsParameterAdNetworkClickID, + AnalyticsParameterAffiliation, + AnalyticsParameterCP1, + AnalyticsParameterCampaign, + AnalyticsParameterCharacter, + AnalyticsParameterCheckoutOption, + AnalyticsParameterCheckoutStep, + AnalyticsParameterContent, + AnalyticsParameterContentType, + AnalyticsParameterCoupon, + AnalyticsParameterCreativeName, + AnalyticsParameterCreativeSlot, + AnalyticsParameterCurrency, + AnalyticsParameterDestination, + AnalyticsParameterEndDate, + AnalyticsParameterFlightNumber, + AnalyticsParameterGroupID, + AnalyticsParameterIndex, + AnalyticsParameterItemBrand, + AnalyticsParameterItemCategory, + AnalyticsParameterItemID, + AnalyticsParameterItemList, + AnalyticsParameterItemLocationID, + AnalyticsParameterItemName, + AnalyticsParameterItemVariant, + AnalyticsParameterLevel, + AnalyticsParameterLocation, + AnalyticsParameterMedium, + AnalyticsParameterNumberOfNights, + AnalyticsParameterNumberOfPassengers, + AnalyticsParameterNumberOfRooms, + AnalyticsParameterOrigin, + AnalyticsParameterPrice, + AnalyticsParameterQuantity, + AnalyticsParameterScore, + AnalyticsParameterSearchTerm, + AnalyticsParameterShipping, + AnalyticsParameterSignUpMethod, + AnalyticsParameterSource, + AnalyticsParameterStartDate, + AnalyticsParameterTax, + AnalyticsParameterTerm, + AnalyticsParameterTransactionID, + AnalyticsParameterTravelClass, + AnalyticsParameterValue, + AnalyticsParameterVirtualCurrencyName, + AnalyticsUserPropertySignUpMethod] + + for (index, parameterName) in acceptedTealiumVariableNames.enumerated() { + let actual = FirebaseRemoteCommand.mapParam(parameterName) + let expected = firebaseParameterNames[index] + XCTAssertEqual(expected, actual) + } + + } + + func testMapParamsWithAllInMappings() { + let payload: [String: Any] = ["param_value": 19.99, "param_transaction_id": "ord1222", "param_currency": "USD", "param_shipping": 2.00, "param_tax": 1.00, "param_coupon": "summer", "param_item_id": ["abc123", "def456"], "param_item_name": ["coolthing", "verycoolthing"], "param_item_variant": ["xyz-89-01", "xyz-99-02"], "param_item_brand": ["acme", "roadrunner"], "param_item_category": ["category1", "category2"]] + + let expected: [String: Any] = ["value": 19.99, "transaction_id": "ord1222", "currency": "USD", "shipping": 2.00, "tax": 1.00, "coupon": "summer", "item_id": ["abc123", "def456"], "item_name": ["coolthing", "verycoolthing"], "item_variant": ["xyz-89-01", "xyz-99-02"], "item_brand": ["acme", "roadrunner"], "item_category": ["category1", "category2"]] + + let actual = payload.mapParams() + XCTAssert(NSDictionary(dictionary: actual).isEqual(to: expected)) + } + + func testMapParamsWithAllNotInMappings() { + let payload: [String: Any] = ["value": 19.99, "transaction_id": "ord1222", "currency": "USD", "shipping": 2.00, "tax": 1.00, "coupon": "summer", "item_id": ["abc123", "def456"], "item_name": ["coolthing", "verycoolthing"], "item_variant": ["xyz-89-01", "xyz-99-02"], "item_brand": ["acme", "roadrunner"], "item_category": ["category1", "category2"]] + + let expected: [String: Any] = ["value": 19.99, "transaction_id": "ord1222", "currency": "USD", "shipping": 2.00, "tax": 1.00, "coupon": "summer", "item_id": ["abc123", "def456"], "item_name": ["coolthing", "verycoolthing"], "item_variant": ["xyz-89-01", "xyz-99-02"], "item_brand": ["acme", "roadrunner"], "item_category": ["category1", "category2"]] + + let actual = payload.mapParams() + XCTAssert(NSDictionary(dictionary: actual).isEqual(to: expected)) + } + + func testMapParamsWithSomeInMappingsSomeNot() { + let payload: [String: Any] = ["param_value": 19.99, "transaction_id": "ord1222", "param_currency": "USD", "param_shipping": 2.00, "param_tax": 1.00, "param_coupon": "summer", "item_id": ["abc123", "def456"], "param_item_name": ["coolthing", "verycoolthing"], "item_variant": ["xyz-89-01", "xyz-99-02"], "item_brand": ["acme", "roadrunner"], "param_item_category": ["category1", "category2"]] + + let expected: [String: Any] = ["value": 19.99, "transaction_id": "ord1222", "currency": "USD", "shipping": 2.00, "tax": 1.00, "coupon": "summer", "item_id": ["abc123", "def456"], "item_name": ["coolthing", "verycoolthing"], "item_variant": ["xyz-89-01", "xyz-99-02"], "item_brand": ["acme", "roadrunner"], "item_category": ["category1", "category2"]] + + let actual = payload.mapParams() + XCTAssert(NSDictionary(dictionary: actual).isEqual(to: expected)) + } } diff --git a/Tests/FirebaseTrackerTests.swift b/Tests/FirebaseTrackerTests.swift index 3f97cb0..02e368f 100644 --- a/Tests/FirebaseTrackerTests.swift +++ b/Tests/FirebaseTrackerTests.swift @@ -164,5 +164,27 @@ class FirebaseTrackerTests: XCTestCase { expect.fulfill() wait(for: [expect], timeout: 2.0) } + + func testMapParamsWhenTheyDontExistInLookup() { + let expect = expectation(description: "set user id should not run") + let payload: [String: Any] = ["command_name": "logevent", "firebase_event_name": "ecommerce_purchase", "coupon": "couponCode", "currency": "AUD", "value": 19.99, "tax": 1.99, "shipping": 2.00, "transaction_id": "1232312321"] + if let response = createRemoteCommandResponse(commandId: "firebase", payload: payload) { + remoteCommand.remoteCommandCompletion(response) + XCTAssertEqual(0, firebaseTracker.logEventWithParamsCallCount) + } + expect.fulfill() + wait(for: [expect], timeout: 2.0) + } + + func testMapParamsWhenTheyDoExistInLookup() { + let expect = expectation(description: "set user id should not run") + let payload: [String: Any] = ["command_name": "logevent", "firebase_event_name": "event_ecommerce_purchase", "param_coupon": "couponCode", "param_currency": "AUD", "param_value": 19.99, "param_tax": 1.99, "param_shipping": 2.00, "param_transaction_id": "1232312321"] + if let response = createRemoteCommandResponse(commandId: "firebase", payload: payload) { + remoteCommand.remoteCommandCompletion(response) + XCTAssertEqual(0, firebaseTracker.logEventWithParamsCallCount) + } + expect.fulfill() + wait(for: [expect], timeout: 2.0) + } }