DailyView/Carthage/Checkouts/facebook-ios-sdk/FBAEMKit/FBAEMKitTests/AEMConfigurationTests.swift
2025-12-30 16:40:31 +08:00

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"
}