// // AnalyticsGeneratorTests.swift // // // Created by Thibaut Schmitt on 06/09/2022. // import Foundation import XCTest import ToolCore @testable import ResgenSwift final class AnalyticsGeneratorTests: XCTestCase { private func getAnalyticsDefinition(id: String, path: String, name: String, type: AnalyticsDefinition.TagType, tags: [String]) -> AnalyticsDefinition { let definition = AnalyticsDefinition(id: id, name: name, type: type) definition.tags = tags return definition } func testGeneratedExtensionContentFirebase() { // Given let sectionOne = AnalyticsCategory(id: "section_one") sectionOne.definitions = [ getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: AnalyticsDefinition.TagType.screen, tags: ["ios", "iosonly"]), getAnalyticsDefinition(id: "s1_def_two", path: "s1_def_two/", name: "s1 def two", type: AnalyticsDefinition.TagType.event, tags: ["ios", "iosonly"]), ] let sectionTwo = AnalyticsCategory(id: "section_two") sectionTwo.definitions = [ getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: AnalyticsDefinition.TagType.screen, tags: ["ios","iosonly"]), getAnalyticsDefinition(id: "s2_def_two", path: "s2_def_two/", name: "s2 def two", type: AnalyticsDefinition.TagType.event, tags: ["droid","droidonly"]), ] let sectionThree = AnalyticsCategory(id: "section_three") sectionThree.definitions = [ getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: AnalyticsDefinition.TagType.screen, tags: ["droid","droidonly"]), getAnalyticsDefinition(id: "s3_def_two", path: "s3_def_two/", name: "s3 def two", type: AnalyticsDefinition.TagType.event, tags: ["droid","droidonly"]), ] // When AnalyticsGenerator.targets = [Analytics.TargetType.firebase] let extensionContent = AnalyticsGenerator.getExtensionContent(sections: [sectionOne, sectionTwo, sectionThree], tags: ["ios", "iosonly"], staticVar: false, extensionName: "GenAnalytics") // Expect Analytics let expect = """ // Generated by ResgenSwift.Analytics 1.2 import UIKit import Firebase // MARK: - Protocol protocol AnalyticsManagerProtocol { func logScreen(name: String, path: String) func logEvent(name: String) } // MARK: - Firebase class FirebaseAnalyticsManager: AnalyticsManagerProtocol { func logScreen(name: String, path: String) { Analytics.logEvent(AnalyticsEventScreenView, parameters: [AnalyticsParameterScreenName: name]) } func logEvent(name: String) { var parameters = [ AnalyticsParameterValue: name ] Analytics.logEvent(AnalyticsEventSelectContent, parameters: parameters) } } // MARK: - Manager class AnalyticsManager { static var shared = AnalyticsManager() // MARK: - Properties var managers: [AnalyticsManagerProtocol] = [] private var isEnabled: Bool = true // MARK: - Methods func setAnalyticsEnabled(_ enable: Bool) { isEnabled = enable } func configure() { managers.append(FirebaseAnalyticsManager()) } private func logScreen(name: String, path: String) { guard isEnabled else { return } managers.forEach { manager in manager.logScreen(name: name, path: path) } } private func logEvent(name: String) { guard isEnabled else { return } managers.forEach { manager in manager.logEvent(name: name) } } // MARK: - section_one func logScreenS1DefOne() { logScreen(name: "s1 def one", path: "s1_def_one/") } func logEventS1DefTwo() { logEvent(name: "s1 def two") } // MARK: - section_two func logScreenS2DefOne() { logScreen(name: "s2 def one", path: "s2_def_one/") } } """ if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) } func testGeneratedExtensionContentMatomo() { // Given let sectionOne = AnalyticsCategory(id: "section_one") sectionOne.definitions = [ getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: AnalyticsDefinition.TagType.screen, tags: ["ios", "iosonly"]), getAnalyticsDefinition(id: "s1_def_two", path: "s1_def_two/", name: "s1 def two", type: AnalyticsDefinition.TagType.event, tags: ["ios", "iosonly"]), ] let sectionTwo = AnalyticsCategory(id: "section_two") sectionTwo.definitions = [ getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: AnalyticsDefinition.TagType.screen, tags: ["ios","iosonly"]), getAnalyticsDefinition(id: "s2_def_two", path: "s2_def_two/", name: "s2 def two", type: AnalyticsDefinition.TagType.event, tags: ["droid","droidonly"]), ] let sectionThree = AnalyticsCategory(id: "section_three") sectionThree.definitions = [ getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: AnalyticsDefinition.TagType.screen, tags: ["droid","droidonly"]), getAnalyticsDefinition(id: "s3_def_two", path: "s3_def_two/", name: "s3 def two", type: AnalyticsDefinition.TagType.event, tags: ["droid","droidonly"]), ] // When AnalyticsGenerator.targets = [Analytics.TargetType.matomo] let extensionContent = AnalyticsGenerator.getExtensionContent(sections: [sectionOne, sectionTwo, sectionThree], tags: ["ios", "iosonly"], staticVar: false, extensionName: "GenAnalytics") // Expect Analytics let expect = """ // Generated by ResgenSwift.Analytics 1.2 import UIKit import MatomoTracker // MARK: - Protocol protocol AnalyticsManagerProtocol { func logScreen(name: String, path: String) func logEvent(name: String) } // MARK: - Matomo class MatomoAnalyticsManager: AnalyticsManagerProtocol { // MARK: - Properties private var tracker: MatomoTracker // MARK: - Init init(siteId: String, url: String) { debugPrint("[Matomo service] Server URL: \\(url)") debugPrint("[Matomo service] Site ID: \\(siteId)") tracker = MatomoTracker(siteId: siteId, baseURL: URL(string: url)!) #if DEBUG tracker.dispatchInterval = 5 #endif #if DEBUG tracker.logger = DefaultLogger(minLevel: .verbose) #endif debugPrint("[Matomo service] Configured with content base: \\(tracker.contentBase?.absoluteString ?? "-")") debugPrint("[Matomo service] Opt out: \\(tracker.isOptedOut)") } // MARK: - Methods func logScreen(name: String, path: String) { guard !tracker.isOptedOut else { return } guard let trackerUrl = tracker.contentBase?.absoluteString else { return } let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") tracker.track( view: [name], url: urlString ) } func logEvent(name: String) { guard !tracker.isOptedOut else { return } tracker.track( eventWithCategory: "category", action: "action", name: name, number: nil, url: nil ) } } // MARK: - Manager class AnalyticsManager { static var shared = AnalyticsManager() // MARK: - Properties var managers: [AnalyticsManagerProtocol] = [] private var isEnabled: Bool = true // MARK: - Methods func setAnalyticsEnabled(_ enable: Bool) { isEnabled = enable } func configure(siteId: String, url: String) { managers.append(MatomoAnalyticsManager(siteId: siteId, url: url)) } private func logScreen(name: String, path: String) { guard isEnabled else { return } managers.forEach { manager in manager.logScreen(name: name, path: path) } } private func logEvent(name: String) { guard isEnabled else { return } managers.forEach { manager in manager.logEvent(name: name) } } // MARK: - section_one func logScreenS1DefOne() { logScreen(name: "s1 def one", path: "s1_def_one/") } func logEventS1DefTwo() { logEvent(name: "s1 def two") } // MARK: - section_two func logScreenS2DefOne() { logScreen(name: "s2 def one", path: "s2_def_one/") } } """ if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) } func testGeneratedExtensionContentMatomoAndFirebase() { // Given let sectionOne = AnalyticsCategory(id: "section_one") sectionOne.definitions = [ getAnalyticsDefinition(id: "s1_def_one", path: "s1_def_one/", name: "s1 def one", type: AnalyticsDefinition.TagType.screen, tags: ["ios", "iosonly"]), getAnalyticsDefinition(id: "s1_def_two", path: "s1_def_two/", name: "s1 def two", type: AnalyticsDefinition.TagType.event, tags: ["ios", "iosonly"]), ] let sectionTwo = AnalyticsCategory(id: "section_two") sectionTwo.definitions = [ getAnalyticsDefinition(id: "s2_def_one", path: "s2_def_one/", name: "s2 def one", type: AnalyticsDefinition.TagType.screen, tags: ["ios","iosonly"]), getAnalyticsDefinition(id: "s2_def_two", path: "s2_def_two/", name: "s2 def two", type: AnalyticsDefinition.TagType.event, tags: ["droid","droidonly"]), ] let sectionThree = AnalyticsCategory(id: "section_three") sectionThree.definitions = [ getAnalyticsDefinition(id: "s3_def_one", path: "s3_def_one/", name: "s3 def one", type: AnalyticsDefinition.TagType.screen, tags: ["droid","droidonly"]), getAnalyticsDefinition(id: "s3_def_two", path: "s3_def_two/", name: "s3 def two", type: AnalyticsDefinition.TagType.event, tags: ["droid","droidonly"]), ] // When AnalyticsGenerator.targets = [Analytics.TargetType.matomo, Analytics.TargetType.firebase] let extensionContent = AnalyticsGenerator.getExtensionContent(sections: [sectionOne, sectionTwo, sectionThree], tags: ["ios", "iosonly"], staticVar: false, extensionName: "GenAnalytics") // Expect Analytics let expect = """ // Generated by ResgenSwift.Analytics 1.2 import UIKit import MatomoTracker import Firebase // MARK: - Protocol protocol AnalyticsManagerProtocol { func logScreen(name: String, path: String) func logEvent(name: String) } // MARK: - Matomo class MatomoAnalyticsManager: AnalyticsManagerProtocol { // MARK: - Properties private var tracker: MatomoTracker // MARK: - Init init(siteId: String, url: String) { debugPrint("[Matomo service] Server URL: \\(url)") debugPrint("[Matomo service] Site ID: \\(siteId)") tracker = MatomoTracker(siteId: siteId, baseURL: URL(string: url)!) #if DEBUG tracker.dispatchInterval = 5 #endif #if DEBUG tracker.logger = DefaultLogger(minLevel: .verbose) #endif debugPrint("[Matomo service] Configured with content base: \\(tracker.contentBase?.absoluteString ?? "-")") debugPrint("[Matomo service] Opt out: \\(tracker.isOptedOut)") } // MARK: - Methods func logScreen(name: String, path: String) { guard !tracker.isOptedOut else { return } guard let trackerUrl = tracker.contentBase?.absoluteString else { return } let urlString = URL(string: "\\(trackerUrl)" + "/" + "\\(path)" + "iOS") tracker.track( view: [name], url: urlString ) } func logEvent(name: String) { guard !tracker.isOptedOut else { return } tracker.track( eventWithCategory: "category", action: "action", name: name, number: nil, url: nil ) } } // MARK: - Firebase class FirebaseAnalyticsManager: AnalyticsManagerProtocol { func logScreen(name: String, path: String) { Analytics.logEvent(AnalyticsEventScreenView, parameters: [AnalyticsParameterScreenName: name]) } func logEvent(name: String) { var parameters = [ AnalyticsParameterValue: name ] Analytics.logEvent(AnalyticsEventSelectContent, parameters: parameters) } } // MARK: - Manager class AnalyticsManager { static var shared = AnalyticsManager() // MARK: - Properties var managers: [AnalyticsManagerProtocol] = [] private var isEnabled: Bool = true // MARK: - Methods func setAnalyticsEnabled(_ enable: Bool) { isEnabled = enable } func configure(siteId: String, url: String) { managers.append(MatomoAnalyticsManager(siteId: siteId, url: url)) managers.append(FirebaseAnalyticsManager()) } private func logScreen(name: String, path: String) { guard isEnabled else { return } managers.forEach { manager in manager.logScreen(name: name, path: path) } } private func logEvent(name: String) { guard isEnabled else { return } managers.forEach { manager in manager.logEvent(name: name) } } // MARK: - section_one func logScreenS1DefOne() { logScreen(name: "s1 def one", path: "s1_def_one/") } func logEventS1DefTwo() { logEvent(name: "s1 def two") } // MARK: - section_two func logScreenS2DefOne() { logScreen(name: "s2 def one", path: "s2_def_one/") } } """ if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) } }