359 lines
9.2 KiB
Swift
359 lines
9.2 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 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.0,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
]
|
|
|
|
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.0,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
])! // 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.0])
|
|
}
|
|
|
|
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 testEncodingAndDecoding() throws {
|
|
let rule = validRule
|
|
let decodedObject = try CodabilityTesting.encodeAndDecode(rule)
|
|
|
|
// Test Objects
|
|
XCTAssertNotIdentical(decodedObject, rule, .isCodable)
|
|
XCTAssertEqual(decodedObject, rule, .isCodable)
|
|
|
|
// Test Properties
|
|
XCTAssertEqual(decodedObject.conversionValue, rule.conversionValue, .isCodable)
|
|
XCTAssertEqual(decodedObject.priority, rule.priority, .isCodable)
|
|
XCTAssertEqual(rule.events, decodedObject.events, .isCodable)
|
|
}
|
|
|
|
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.0,
|
|
],
|
|
[
|
|
Keys.currency: Values.EU,
|
|
Keys.amount: 100.0,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
]) else {
|
|
return XCTFail("Fail to initalize AEM rule")
|
|
}
|
|
XCTAssertTrue(
|
|
rule.isMatched(
|
|
withRecordedEvents: [Values.activateApp, Values.purchase],
|
|
recordedValues: [Values.purchase: [Values.USD: 1000.0]]
|
|
),
|
|
"Should match the expected events and values for the rule"
|
|
)
|
|
XCTAssertTrue(
|
|
rule.isMatched(
|
|
withRecordedEvents: [Values.activateApp, Values.purchase],
|
|
recordedValues: [Values.purchase: [Values.EU: 1000.0]]
|
|
),
|
|
"Should match the expected events and values for the rule"
|
|
)
|
|
XCTAssertFalse(
|
|
rule.isMatched(
|
|
withRecordedEvents: [Values.activateApp],
|
|
recordedValues: [Values.purchase: [Values.USD: 1000.0]]
|
|
),
|
|
"Should not match the unexpected events for the rule"
|
|
)
|
|
XCTAssertFalse(
|
|
rule.isMatched(
|
|
withRecordedEvents: [Values.activateApp, Values.purchase],
|
|
recordedValues: [Values.purchase: [Values.JPY: 1000.0]]
|
|
),
|
|
"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.0,
|
|
],
|
|
],
|
|
],
|
|
[
|
|
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.0]]
|
|
),
|
|
"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.0]]
|
|
),
|
|
"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.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"
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - Assumptions
|
|
|
|
extension String {
|
|
fileprivate static let isCodable = "AEMRule should be encodable and decodable"
|
|
}
|