FBAEMKit/FBAEMKitTests/AEMRuleTests.swift (348 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ @testable import FBAEMKit import TestTools import XCTest #if !os(tvOS) final class AEMRuleTests: XCTestCase { enum Keys { static let conversionValue = "conversion_value" static let priority = "priority" static let events = "events" static let eventName = "event_name" static let values = "values" static let currency = "currency" static let amount = "amount" } enum Values { static let purchase = "fb_mobile_purchase" static let donate = "Donate" static let activateApp = "fb_activate_app" static let testEvent = "fb_test_event" static let USD = "USD" static let EU = "EU" static let JPY = "JPY" } var sampleData: [String: Any] = [ Keys.conversionValue: 2, Keys.priority: 7, Keys.events: [ [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 100, ], ], ], ], ] var validRule = _AEMRule(json: [ Keys.conversionValue: 10, Keys.priority: 7, Keys.events: [ [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 100, ], ], ], ], ])! // swiftlint:disable:this force_unwrapping func testValidCase1() { let validData: [String: Any] = [ Keys.conversionValue: 2, Keys.priority: 10, Keys.events: [ [ Keys.eventName: Values.purchase, ], [ Keys.eventName: Values.donate, ], ], ] guard let rule = _AEMRule(json: validData) else { return XCTFail("Unwraping Error") } XCTAssertEqual(2, rule.conversionValue) XCTAssertEqual(10, rule.priority) XCTAssertEqual(2, rule.events.count) let event1 = rule.events[0] XCTAssertEqual(event1.eventName, Values.purchase) XCTAssertNil(event1.values) let event2 = rule.events[1] XCTAssertEqual(event2.eventName, Values.donate) XCTAssertNil(event2.values) } func testValidCase2() { guard let rule = _AEMRule(json: sampleData) else { return XCTFail("Unwraping Error") } XCTAssertEqual(2, rule.conversionValue) XCTAssertEqual(7, rule.priority) XCTAssertEqual(1, rule.events.count) let event = rule.events[0] XCTAssertEqual(event.eventName, Values.purchase) XCTAssertEqual(event.values, [Values.USD: 100]) } func testInvalidCases() { var invalidData: [String: Any] = [:] XCTAssertNil(_AEMRule(json: invalidData)) invalidData = [Keys.conversionValue: 2] XCTAssertNil(_AEMRule(json: invalidData)) invalidData = [Keys.priority: 7] XCTAssertNil(_AEMRule(json: invalidData)) invalidData = [ Keys.events: [ [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 100, ], ], ], ], ] XCTAssertNil(_AEMRule(json: invalidData)) invalidData = [ Keys.conversionValue: 2, Keys.events: [ [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: 100, Keys.amount: Values.USD, ], ], ], ], ] XCTAssertNil(_AEMRule(json: invalidData)) invalidData = [ Keys.priority: 2, Keys.events: [ [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 100, ], ], ], ], ] XCTAssertNil(_AEMRule(json: invalidData)) } func testParsing() { (1 ... 100).forEach { _ in if let data = (Fuzzer.randomize(json: self.sampleData) as? [String: Any]) { _ = _AEMRule(json: data) } } } func testContainsEvent() { let rule = validRule XCTAssertTrue( rule.containsEvent(Values.purchase), "Should expect to return true for the event in the rule" ) XCTAssertFalse( rule.containsEvent(Values.testEvent), "Should expect to return false for the event not in the rule" ) } func testSecureCoding() { XCTAssertTrue( _AEMRule.supportsSecureCoding, "AEM Rule should support secure coding" ) } func testEncoding() { let coder = TestCoder() let rule = validRule rule.encode(with: coder) let encodedConversionValue = coder.encodedObject[Keys.conversionValue] as? NSNumber XCTAssertEqual( encodedConversionValue?.intValue, rule.conversionValue, "Should encode the expected conversion_value with the correct key" ) let encodedPriority = coder.encodedObject[Keys.priority] as? NSNumber XCTAssertEqual( encodedPriority?.intValue, rule.priority, "Should encode the expected priority with the correct key" ) XCTAssertEqual( coder.encodedObject[Keys.events] as? [_AEMEvent], rule.events, "Should encode the expected events with the correct key" ) } func testDecoding() { let decoder = TestCoder() _ = _AEMRule(coder: decoder) XCTAssertEqual( decoder.decodedObject[Keys.conversionValue] as? String, "decodeIntegerForKey", "Should decode the expected type for the conversion_value key" ) XCTAssertEqual( decoder.decodedObject[Keys.priority] as? String, "decodeIntegerForKey", "Should decode the expected type for the priority key" ) XCTAssertEqual( decoder.decodedObject[Keys.events] as? NSSet, [NSArray.self, _AEMEvent.self], "Should decode the expected type for the events key" ) } func testRuleMatch() { guard let rule = _AEMRule(json: [ Keys.conversionValue: 10, Keys.priority: 7, Keys.events: [ [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 100, ], [ Keys.currency: Values.EU, Keys.amount: 100, ], ], ], ], ]) else { return XCTFail("Fail to initalize AEM rule") } XCTAssertTrue( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase], recordedValues: [Values.purchase: [Values.USD: 1000]] ), "Should match the expected events and values for the rule" ) XCTAssertTrue( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase], recordedValues: [Values.purchase: [Values.EU: 1000]] ), "Should match the expected events and values for the rule" ) XCTAssertFalse( rule.isMatched( withRecordedEvents: [Values.activateApp], recordedValues: [Values.purchase: [Values.USD: 1000]] ), "Should not match the unexpected events for the rule" ) XCTAssertFalse( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase], recordedValues: [Values.purchase: [Values.JPY: 1000]] ), "Should not match the unexpected values for the rule" ) } func testRuleMatchWithEventBundle() { guard let rule = _AEMRule(json: [ Keys.conversionValue: 10, Keys.priority: 7, Keys.events: [ [ Keys.eventName: Values.activateApp, ], [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 100, ], ], ], [ Keys.eventName: Values.testEvent, ], ], ]) else { return XCTFail("Fail to initalize AEM rule") } XCTAssertTrue( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase, Values.testEvent], recordedValues: [Values.purchase: [Values.USD: 1000]] ), "Should match the expected events and values for the rule" ) XCTAssertFalse( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase, Values.testEvent], recordedValues: nil ), "Should not match the unexpected values for the rule" ) XCTAssertFalse( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase], recordedValues: [Values.purchase: [Values.USD: 1000]] ), "Should not match the unexpected events for the rule" ) XCTAssertFalse( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase, Values.testEvent], recordedValues: [Values.purchase: [Values.JPY: 1000]] ), "Should not match the unexpected values for the rule" ) } func testRuleMatchWithoutValue() { guard let rule = _AEMRule(json: [ Keys.conversionValue: 10, Keys.priority: 7, Keys.events: [ [ Keys.eventName: Values.activateApp, ], [ Keys.eventName: Values.purchase, Keys.values: [ [ Keys.currency: Values.USD, Keys.amount: 0, ], ], ], [ Keys.eventName: Values.testEvent, ], ], ]) else { return XCTFail("Fail to initalize AEM rule") } XCTAssertTrue( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase, Values.testEvent], recordedValues: nil ), "Should match the expected events and values for the rule" ) XCTAssertTrue( rule.isMatched( withRecordedEvents: [Values.activateApp, Values.purchase, Values.testEvent], recordedValues: [Values.purchase: [Values.JPY: 1000]] ), "Should match the expected events and values for the rule" ) } } #endif