FBAEMKit/FBAEMKitTests/AEMConfigurationTests.swift (374 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 AEMConfigurationTests: XCTestCase {
enum Keys {
static let defaultCurrency = "default_currency"
static let cutoffTime = "cutoff_time"
static let validFrom = "valid_from"
static let configMode = "config_mode"
static let advertiserID = "advertiser_id"
static let businessID = "business_id"
static let paramRule = "param_rule"
static let conversionValueRules = "conversion_value_rules"
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 coffeeBrand = "coffeebrand"
static let paramRule = #"{"and": [{"fb_content[*].brand": {"eq": "CoffeeShop"}}]}"#
static let purchase = "fb_mobile_purchase"
static let donate = "Donate"
static let defaultMode = "default"
static let USD = "USD"
static let JPY = "JPY"
}
var sampleData: [String: Any] = [
Keys.defaultCurrency: Values.USD,
Keys.cutoffTime: 1,
Keys.validFrom: 10000,
Keys.configMode: Values.defaultMode,
Keys.advertiserID: Values.coffeeBrand,
Keys.paramRule: Values.paramRule,
Keys.conversionValueRules: [
[
Keys.conversionValue: 2,
Keys.priority: 10,
Keys.events: [
[
Keys.eventName: Values.purchase,
],
[
Keys.eventName: Values.donate,
],
],
],
],
]
var rulesData = [
[
Keys.conversionValue: 9,
Keys.priority: 10,
Keys.events: [
[
Keys.eventName: Values.purchase,
Keys.values: [
[
Keys.currency: Values.USD,
Keys.amount: 100,
],
[
Keys.currency: Values.JPY,
Keys.amount: 1000,
],
],
],
[
Keys.eventName: Values.donate,
],
],
],
[
Keys.conversionValue: 15,
Keys.priority: 7,
Keys.events: [
[
Keys.eventName: Values.donate,
],
],
],
[
Keys.conversionValue: 20,
Keys.priority: 15,
Keys.events: [
[
Keys.eventName: Values.purchase,
],
],
],
]
let advertiserRuleFactory = _AEMAdvertiserRuleFactory()
override func setUp() {
super.setUp()
_AEMConfiguration.configure(withRuleProvider: advertiserRuleFactory)
}
func testConfiguration() {
XCTAssertEqual(
_AEMConfiguration.ruleProvider() as! _AEMAdvertiserRuleFactory, // swiftlint:disable:this force_cast
advertiserRuleFactory,
"Should configure the _AEMConfiguration correctly"
)
}
func testValidCases() {
let config = _AEMConfiguration(json: sampleData)
XCTAssertEqual(
config?.defaultCurrency,
Values.USD,
"Should parse the expected default_currency with the correct value"
)
XCTAssertEqual(
config?.cutoffTime,
1,
"Should parse the expected cutoff_time with the correct value"
)
XCTAssertEqual(
config?.validFrom,
10000,
"Should parse the expected valid_from with the correct value"
)
XCTAssertEqual(
config?.configMode,
Values.defaultMode,
"Should parse the expected config_mode with the correct value"
)
XCTAssertEqual(
config?.businessID,
Values.coffeeBrand,
"Should parse the expected business_id with the correct value"
)
XCTAssertEqual(
config?.conversionValueRules.count,
1,
"Should parse the expected conversion_value_rules with the correct value"
)
}
func testInvalidCases() {
var invalidData: [String: Any] = [:]
XCTAssertNil(_AEMConfiguration(json: invalidData))
invalidData = [
Keys.defaultCurrency: 100,
Keys.cutoffTime: 1,
Keys.validFrom: 10000,
Keys.configMode: Values.defaultMode,
Keys.conversionValueRules: [
[
Keys.conversionValue: 2,
Keys.priority: 10,
Keys.events: [
[
Keys.eventName: Values.purchase,
],
[
Keys.eventName: Values.donate,
],
],
],
],
]
XCTAssertNil(
_AEMConfiguration(json: invalidData),
"Should not consider the config json valid with unexpected type for default_currency"
)
invalidData = [
Keys.defaultCurrency: Values.USD,
Keys.cutoffTime: 1,
Keys.validFrom: 10000,
Keys.configMode: Values.defaultMode,
]
XCTAssertNil(
_AEMConfiguration(json: invalidData),
"Should not consider the config json valid without any conversion value rules"
)
invalidData = [
Keys.defaultCurrency: Values.USD,
Keys.cutoffTime: 1,
Keys.validFrom: 10000,
Keys.configMode: Values.defaultMode,
Keys.conversionValueRules: [
[
Keys.conversionValue: "2",
Keys.priority: 10,
Keys.events: [
[
Keys.eventName: Values.purchase,
],
[
Keys.eventName: Values.donate,
],
],
],
],
]
XCTAssertNil(
_AEMConfiguration(json: invalidData),
"Should not consider the config json valid with invalid conversion value rule"
)
}
func testGetEventSet() {
guard let parsedRules: [_AEMRule] = _AEMConfiguration.parseRules(rulesData)
else { return XCTFail("Unwrapping Error") }
let eventSet = _AEMConfiguration.getEventSet(from: parsedRules)
XCTAssertEqual(eventSet, [Values.purchase, Values.donate], "Should get the expected event set")
}
func testGetCurrencySet() {
guard let parsedRules: [_AEMRule] = _AEMConfiguration.parseRules(rulesData)
else { return XCTFail("Unwrapping Error") }
let eventSet = _AEMConfiguration.getCurrencySet(from: parsedRules)
XCTAssertEqual(eventSet, [Values.USD, Values.JPY], "Should get the expected event set")
}
func testParseRules() {
let parsedRules: [_AEMRule]? = _AEMConfiguration.parseRules(rulesData)
XCTAssertEqual(
parsedRules?[0].priority, 15, "Shoule parse the rules in descending priority order"
)
XCTAssertEqual(
parsedRules?[1].priority, 10, "Shoule parse the rules in descending priority order"
)
XCTAssertEqual(
parsedRules?[2].priority, 7, "Shoule parse the rules in descending priority order"
)
}
func testParsing() {
(1 ... 100).forEach { _ in
if let data = (Fuzzer.randomize(json: self.sampleData) as? [String: Any]) {
_ = _AEMConfiguration(json: data)
}
}
}
func testIsSameBusinessID() {
let configWithBusinessID = SampleAEMConfigurations.createConfigWithBusinessID()
let configWithoutBusinessID = SampleAEMConfigurations.createConfigWithoutBusinessID()
XCTAssertTrue(
configWithBusinessID.isSameBusinessID("test_advertiserid_123") == true,
"Should return true for the same business ID"
)
XCTAssertFalse(
configWithBusinessID.isSameBusinessID("test_advertiserid_6666") == true,
"Should return false for the unexpected business ID"
)
XCTAssertFalse(
configWithBusinessID.isSameBusinessID(nil) == true,
"Should return false for nil business ID if the config has business ID"
)
XCTAssertTrue(
configWithoutBusinessID.isSameBusinessID(nil) == true,
"Should return true for nil business ID if the config doesn't have business ID"
)
XCTAssertFalse(
configWithoutBusinessID.isSameBusinessID("test_advertiserid_123") == true,
"Should return false for non-nil business ID if the config has business ID"
)
}
func testIsSameValidFromAndBusinessID() {
let configWithBusinessID = SampleAEMConfigurations.createConfigWithBusinessID()
let configWithoutBusinessID = SampleAEMConfigurations.createConfigWithoutBusinessID()
XCTAssertTrue(
configWithBusinessID.isSameValid(from: 10000, businessID: "test_advertiserid_123") == true,
"Should return true for the same validFrom and business ID"
)
XCTAssertFalse(
configWithBusinessID.isSameValid(from: 10000, businessID: "test_advertiserid_6666") == true,
"Should return false for the unexpected validFrom and business ID"
)
XCTAssertFalse(
configWithBusinessID.isSameValid(from: 10001, businessID: "test_advertiserid_123") == true,
"Should return false for the unexpected validFrom and business ID"
)
XCTAssertFalse(
configWithBusinessID.isSameValid(from: 10000, businessID: nil) == true,
"Should return false for the unexpected validFrom and business ID"
)
XCTAssertTrue(
configWithoutBusinessID.isSameValid(from: 10000, businessID: nil) == true,
"Should return true for nil business ID if the config doesn't have business ID"
)
XCTAssertFalse(
configWithoutBusinessID.isSameValid(from: 10000, businessID: "test_advertiserid_123") == true,
"Should return false for the unexpected validFrom and business ID"
)
XCTAssertFalse(
configWithoutBusinessID.isSameValid(from: 10001, businessID: nil) == true,
"Should return false for the unexpected validFrom and business ID"
)
}
func testSecureCoding() {
XCTAssertTrue(
_AEMConfiguration.supportsSecureCoding,
"AEM Configuration should support secure coding"
)
}
func testEncoding() {
let coder = TestCoder()
let config = _AEMConfiguration(json: sampleData)
config?.encode(with: coder)
XCTAssertEqual(
coder.encodedObject[Keys.defaultCurrency] as? String,
config?.defaultCurrency,
"Should encode the expected default_currency with the correct key"
)
let cutoffTime = coder.encodedObject[Keys.cutoffTime] as? NSNumber
XCTAssertEqual(
cutoffTime?.intValue,
config?.cutoffTime,
"Should encode the expected cutoff_time with the correct key"
)
let validFrom = coder.encodedObject[Keys.validFrom] as? NSNumber
XCTAssertEqual(
validFrom?.intValue,
config?.validFrom,
"Should encode the expected valid_from with the correct key"
)
XCTAssertEqual(
coder.encodedObject[Keys.configMode] as? String,
config?.configMode,
"Should encode the expected config_mode with the correct key"
)
XCTAssertEqual(
coder.encodedObject[Keys.businessID] as? String,
config?.businessID,
"Should encode the expected business_id with the correct key"
)
XCTAssertTrue(
coder.encodedObject[Keys.paramRule] is _AEMAdvertiserRuleMatching,
"Should encode the expected param_rule with the correct key"
)
XCTAssertEqual(
coder.encodedObject[Keys.conversionValueRules] as? [_AEMRule],
config?.conversionValueRules,
"Should encode the expected conversion_value_rules with the correct key"
)
}
func testDecoding() {
let decoder = TestCoder()
_ = _AEMConfiguration(coder: decoder)
XCTAssertTrue(
decoder.decodedObject[Keys.defaultCurrency] is NSString.Type,
"Should decode the expected type for the default_currency key"
)
XCTAssertEqual(
decoder.decodedObject[Keys.cutoffTime] as? String,
"decodeIntegerForKey",
"Should decode the expected type for the cutoff_time key"
)
XCTAssertEqual(
decoder.decodedObject[Keys.validFrom] as? String,
"decodeIntegerForKey",
"Should decode the expected type for the valid_from key"
)
XCTAssertTrue(
decoder.decodedObject[Keys.configMode] is NSString.Type,
"Should decode the expected type for the config_mode key"
)
XCTAssertTrue(
decoder.decodedObject[Keys.businessID] is NSString.Type,
"Should decode the expected type for the business_id key"
)
XCTAssertEqual(
decoder.decodedObject[Keys.paramRule] as? NSSet,
[NSArray.self, _AEMAdvertiserMultiEntryRule.self, _AEMAdvertiserSingleEntryRule.self],
"Should decode the expected type for the param_rule key"
)
XCTAssertEqual(
decoder.decodedObject[Keys.conversionValueRules] as? NSSet,
[NSArray.self, _AEMEvent.self, _AEMRule.self],
"Should decode the expected type for the conversion_value_rules key"
)
}
}
#endif