FBAEMKit/FBAEMKitTests/AEMAdvertiserRuleFactoryTests.swift (314 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 XCTest #if !os(tvOS) final class AEMAdvertiserRuleFactoryTests: XCTestCase { let factory = _AEMAdvertiserRuleFactory() func testCreateRuleWithJson() { XCTAssertNil( factory.createRule(withJson: nil), "Should not create valid Single Entry Rule with nil" ) XCTAssertNil( factory.createRule(withJson: ""), "Should not create valid Single Entry Rule with empty string" ) XCTAssertNil( factory.createRule(withJson: nil), "Should not create valid Single Entry Rule with nil" ) XCTAssertNotNil( factory.createRule(withJson: #"{"and": [{"value": {"contains": "abc"}}]}"#), "Should create expected Multi Entry Rule" ) XCTAssertNotNil( factory.createRule(withJson: #"{"value": {"contains": "abc"}}"#), "Should create expected Single Entry Rule" ) XCTAssertNotNil( factory.createRule(withJson: #"{"and": [{"event": {"eq": "Lead"}}, {"or": [{"URL": {"contains": "achievetestprep.com"}}]}]}"#), // swiftlint:disable:this line_length "Should create expected nested Multi Entry Rule" ) } func testCreateRuleWithDict() { XCTAssertNil( factory.createRule(withDict: [:]), "Should not create valid Single Entry Rule with emtpy dictionary" ) XCTAssertNil( factory.createRule(withDict: ["value": ["contains": 10]]), "Should not create valid Single Entry Rule with invalid dictionary" ) let multiEntryRule = factory.createRule(withDict: ["and": [SampleAEMData.validAdvertiserSingleEntryRuleJson1]]) as? _AEMAdvertiserMultiEntryRule // swiftlint:disable:this line_length XCTAssertNotNil( multiEntryRule, "Should create expected Multi Entry Rule" ) let singleEntryRule = factory.createRule(withDict: ["value": ["contains": "abc"]]) as? _AEMAdvertiserSingleEntryRule // swiftlint:disable:this line_length XCTAssertNotNil( singleEntryRule, "Should create expected Single Entry Rule" ) } func testCreateSingleEntryRuleWithValidDict() { var rule: _AEMAdvertiserSingleEntryRule? rule = factory.createSingleEntryRule(withDict: SampleAEMData.validAdvertiserSingleEntryRuleJson1) XCTAssertTrue( SampleAEMData.advertiserSingleEntryRule1.isEqual(rule), "Should create the expected Single Entry Rule" ) rule = factory.createSingleEntryRule(withDict: SampleAEMData.validAdvertiserSingleEntryRuleJson2) XCTAssertTrue( SampleAEMData.advertiserSingleEntryRule2.isEqual(rule), "Should create the expected Single Entry Rule" ) rule = factory.createSingleEntryRule(withDict: SampleAEMData.validAdvertiserSingleEntryRuleJson3) XCTAssertTrue( SampleAEMData.advertiserSingleEntryRule3.isEqual(rule), "Should create the expected Single Entry Rule" ) } func testCreateSingleEntryRuleWithInvalidDict() { XCTAssertNil( factory.createSingleEntryRule(withDict: [:]), "Should not create valid Single Entry Rule with empty dictionary" ) XCTAssertNil( factory.createSingleEntryRule(withDict: ["contains": []]), "Should not create valid Single Entry Rule with invalid dictionary" ) XCTAssertNil( factory.createSingleEntryRule(withDict: ["value": ["contains": 10]]), "Should not create valid Single Entry Rule with invalid dictionary" ) XCTAssertNil( factory.createSingleEntryRule(withDict: ["value": ["lt": "abc"]]), "Should not create valid Single Entry Rule with invalid dictionary" ) } func testCreateMultiEntryRuleWithValidDict() { zip( ["and", "or", "not"], [ .and, .or, .not, ] as [_AEMAdvertiserRuleOperator] ).forEach { opString, expectedOperator in let rule: _AEMAdvertiserMultiEntryRule? = factory.createMultiEntryRule( withDict: [opString: [SampleAEMData.validAdvertiserSingleEntryRuleJson1, SampleAEMData.validAdvertiserSingleEntryRuleJson2]]) // swiftlint:disable:this line_length XCTAssertNotNil( rule, "Should create Multi Entry Rule with valid dictionary" ) XCTAssertEqual( expectedOperator, rule?.operator, "Multi Entry Rule should have the expected operator" ) XCTAssertEqual( 2, rule?.rules.count, "Multi Entry Rule should have the expected number of subrules" ) } // swiftlint:disable:this closure_end_indentation } func testCreateMultiEntryRuleWithInvalidDict() { XCTAssertNil( factory.createMultiEntryRule(withDict: [:]), "Should not create valid Multi Entry Rule with empty dictionary" ) XCTAssertNil( factory.createMultiEntryRule(withDict: ["contains": [["content": ["starts_with": "abc"]]]]), "Should not create valid Multi Entry Rule with invlaid operator" ) XCTAssertNil( factory.createMultiEntryRule(withDict: ["and": []]), "Should not create valid Multi Entry Rule with empty subrules" ) XCTAssertNil( factory.createMultiEntryRule(withDict: ["and": ["value": ["contains": 10]]]), "Should not create valid Multi Entry Rule with invlaid subrule" ) } func testGetPrimaryKey() { XCTAssertEqual( factory.primaryKey(forRule: ["test_key": "abc"]), "test_key", "Should get the expected key of the dictionary" ) XCTAssertNil( factory.primaryKey(forRule: [:]), "Should not get the unexpected key while the dictionay is empty" ) } func testGetOperator() { XCTAssertEqual( factory.getOperator(["test_key": "abc"]), .unknown, "Should get the expected Unknown operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["And": "abc"]), .and, "Should get the expected AND operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["and": "abc"]), .and, "Should get the expected AND operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["or": "abc"]), .or, "Should get the expected OR operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["not": "abc"]), .not, "Should get the expected NOT operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["contains": "abc"]), .contains, "Should get the expected Contains operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["not_contains": "abc"]), .notContains, "Should get the expected NotContains operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["starts_with": "abc"]), .startsWith, "Should get the expected StartsWith operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["i_contains": "abc"]), .caseInsensitiveContains, "Should get the expected i_contains operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["i_not_contains": "abc"]), .caseInsensitiveNotContains, "Should get the expected I_NotContains operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["i_starts_with": "abc"]), .caseInsensitiveStartsWith, "Should get the expected I_StartsWith operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["regex_match": "abc"]), .regexMatch, "Should get the expected REGEX_MATCH operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["eq": "abc"]), .equal, "Should get the expected EQ operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["neq": "abc"]), .notEqual, "Should get the expected NEQ operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["lt": 10]), .lessThan, "Should get the expected LT operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["lte": 10]), .lessThanOrEqual, "Should get the expected LTE operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["gt": 10]), .greaterThan, "Should get the expected GT operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["gte": 10]), .greaterThanOrEqual, "Should get the expected GTE operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["i_is_any": ["abc"]]), .caseInsensitiveIsAny, "Should get the expected I_IsAny operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["i_is_not_any": ["abc"]]), .caseInsensitiveIsNotAny, "Should get the expected I_IsNotAny operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["is_any": ["abc"]]), .isAny, "Should get the expected IsAny operator of the dictionary" ) XCTAssertEqual( factory.getOperator(["is_not_any": ["abc"]]), .isNotAny, "Should get the expected IsNotAny operator of the dictionary" ) } func testIsOperatorForMultiEntryRule() { for ruleOperator in [ .and, .or, .not, ] as [_AEMAdvertiserRuleOperator] { XCTAssertTrue( factory.isOperator(forMultiEntryRule: ruleOperator), "Should expect the operator for multi entry rule" ) } for ruleOperator in [ .contains, .notContains, .startsWith, .caseInsensitiveContains, .caseInsensitiveNotContains, .caseInsensitiveStartsWith, .regexMatch, .equal, .notEqual, .lessThan, .lessThanOrEqual, .greaterThan, .greaterThanOrEqual, .caseInsensitiveIsAny, .caseInsensitiveIsNotAny, .isAny, .isNotAny, ] as [_AEMAdvertiserRuleOperator] { XCTAssertFalse( factory.isOperator(forMultiEntryRule: ruleOperator), "Should expect the operator not for multi entry rule" ) } } } extension _AEMAdvertiserSingleEntryRule { open override func isEqual(_ object: Any?) -> Bool { // swiftlint:disable:this override_in_extension if let rule = object as? _AEMAdvertiserSingleEntryRule { let isOpEqual = self.operator == rule.operator let isParamKeyEqual = paramKey == rule.paramKey let isLinguisticConditionEqual = linguisticCondition == rule.linguisticCondition var isArrayConditionEqual = false if let array1 = arrayCondition { let array2 = rule.arrayCondition isArrayConditionEqual = array1 == array2 } else { isArrayConditionEqual = rule.arrayCondition == nil } let isNumericConditionEqual = ((numericalCondition == nil && rule.numericalCondition == nil) || (numericalCondition?.isEqual(to: rule.numericalCondition ?? NSNumber(value: -1)) == true)) return isOpEqual && isParamKeyEqual && isLinguisticConditionEqual && isArrayConditionEqual && isNumericConditionEqual } return false } } #endif