356 lines
11 KiB
Swift
356 lines
11 KiB
Swift
/*
|
|
* 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
|
|
|
|
final class AEMConfigurationTests: XCTestCase {
|
|
|
|
enum Keys {
|
|
static let defaultCurrency = "default_currency"
|
|
static let cutoffTime = "cutoff_time"
|
|
static let validFrom = "valid_from"
|
|
static let mode = "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.mode: 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.0,
|
|
],
|
|
[
|
|
Keys.currency: Values.JPY,
|
|
Keys.amount: 1000.0,
|
|
],
|
|
],
|
|
],
|
|
[
|
|
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() {
|
|
XCTAssertIdentical(
|
|
AEMConfiguration.ruleProvider as AnyObject,
|
|
advertiserRuleFactory,
|
|
"Should configure the AEMConfiguration correctly"
|
|
)
|
|
}
|
|
|
|
func testValidCases() {
|
|
let configuration = AEMConfiguration(json: sampleData)
|
|
|
|
XCTAssertEqual(
|
|
configuration?.defaultCurrency,
|
|
Values.USD,
|
|
"Should parse the expected default_currency with the correct value"
|
|
)
|
|
XCTAssertEqual(
|
|
configuration?.cutoffTime,
|
|
1,
|
|
"Should parse the expected cutoff_time with the correct value"
|
|
)
|
|
XCTAssertEqual(
|
|
configuration?.validFrom,
|
|
10000,
|
|
"Should parse the expected valid_from with the correct value"
|
|
)
|
|
XCTAssertEqual(
|
|
configuration?.mode,
|
|
Values.defaultMode,
|
|
"Should parse the expected config_mode with the correct value"
|
|
)
|
|
XCTAssertEqual(
|
|
configuration?.businessID,
|
|
Values.coffeeBrand,
|
|
"Should parse the expected business_id with the correct value"
|
|
)
|
|
XCTAssertEqual(
|
|
configuration?.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.mode: 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 configuration json valid with unexpected type for default_currency"
|
|
)
|
|
invalidData = [
|
|
Keys.defaultCurrency: Values.USD,
|
|
Keys.cutoffTime: 1,
|
|
Keys.validFrom: 10000,
|
|
Keys.mode: Values.defaultMode,
|
|
]
|
|
XCTAssertNil(
|
|
AEMConfiguration(json: invalidData),
|
|
"Should not consider the configuration json valid without any conversion value rules"
|
|
)
|
|
invalidData = [
|
|
Keys.defaultCurrency: Values.USD,
|
|
Keys.cutoffTime: 1,
|
|
Keys.validFrom: 10000,
|
|
Keys.mode: 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 configuration 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.createConfigurationWithBusinessID()
|
|
let configWithoutBusinessID = SampleAEMConfigurations.createConfigurationWithoutBusinessID()
|
|
|
|
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 configuration has business ID"
|
|
)
|
|
|
|
XCTAssertTrue(
|
|
configWithoutBusinessID.isSameBusinessID(nil) == true,
|
|
"Should return true for nil business ID if the configuration doesn't have business ID"
|
|
)
|
|
XCTAssertFalse(
|
|
configWithoutBusinessID.isSameBusinessID("test_advertiserid_123") == true,
|
|
"Should return false for non-nil business ID if the configuration has business ID"
|
|
)
|
|
}
|
|
|
|
func testIsSameValidFromAndBusinessID() {
|
|
let configWithBusinessID = SampleAEMConfigurations.createConfigurationWithBusinessID()
|
|
let configWithoutBusinessID = SampleAEMConfigurations.createConfigurationWithoutBusinessID()
|
|
|
|
XCTAssertTrue(
|
|
configWithBusinessID.isSame(validFrom: 10000, businessID: "test_advertiserid_123") == true,
|
|
"Should return true for the same validFrom and business ID"
|
|
)
|
|
XCTAssertFalse(
|
|
configWithBusinessID.isSame(validFrom: 10000, businessID: "test_advertiserid_6666") == true,
|
|
"Should return false for the unexpected validFrom and business ID"
|
|
)
|
|
XCTAssertFalse(
|
|
configWithBusinessID.isSame(validFrom: 10001, businessID: "test_advertiserid_123") == true,
|
|
"Should return false for the unexpected validFrom and business ID"
|
|
)
|
|
XCTAssertFalse(
|
|
configWithBusinessID.isSame(validFrom: 10000, businessID: nil) == true,
|
|
"Should return false for the unexpected validFrom and business ID"
|
|
)
|
|
|
|
XCTAssertTrue(
|
|
configWithoutBusinessID.isSame(validFrom: 10000, businessID: nil) == true,
|
|
"Should return true for nil business ID if the configuration doesn't have business ID"
|
|
)
|
|
XCTAssertFalse(
|
|
configWithoutBusinessID.isSame(validFrom: 10000, businessID: "test_advertiserid_123") == true,
|
|
"Should return false for the unexpected validFrom and business ID"
|
|
)
|
|
XCTAssertFalse(
|
|
configWithoutBusinessID.isSame(validFrom: 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 testEncodingAndDecoding() throws {
|
|
// swiftlint:disable:next force_unwrapping
|
|
let configuration = AEMConfiguration(json: sampleData)!
|
|
let decodedObject = try CodabilityTesting.encodeAndDecode(configuration)
|
|
|
|
// Test Object
|
|
XCTAssertNotIdentical(configuration, decodedObject)
|
|
XCTAssertNotEqual(configuration, decodedObject) // isEqual method not added yet
|
|
|
|
// Test Properties
|
|
XCTAssertEqual(configuration.defaultCurrency, decodedObject.defaultCurrency, .isCodable)
|
|
XCTAssertEqual(configuration.cutoffTime, decodedObject.cutoffTime, .isCodable)
|
|
XCTAssertEqual(configuration.validFrom, decodedObject.validFrom, .isCodable)
|
|
XCTAssertEqual(configuration.mode, decodedObject.mode, .isCodable)
|
|
XCTAssertEqual(configuration.businessID, decodedObject.businessID, .isCodable)
|
|
XCTAssertEqual(
|
|
configuration.conversionValueRules,
|
|
decodedObject.conversionValueRules,
|
|
.isCodable
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - Assumptions
|
|
|
|
extension String {
|
|
fileprivate static let isCodable = "AEMConfiguration should be encodable and decodable"
|
|
}
|