diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 97b16c90..99812ec1 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -29,12 +29,9 @@ 474F37A42C16F5B000F38BB0 /* NotificationCenterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474F37A32C16F5B000F38BB0 /* NotificationCenterView.swift */; }; 474F37AE2C170FB600F38BB0 /* NotificationCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474F37AD2C170FB600F38BB0 /* NotificationCellView.swift */; }; 4774807A2C174BAA00580FB2 /* Payload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 477480792C174BAA00580FB2 /* Payload.swift */; }; - 4774807F2C174C2000580FB2 /* MBPushNotification+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4774807E2C174C2000580FB2 /* MBPushNotification+Extensions.swift */; }; - 47D63E2D2C2EAD220055E7D8 /* Mindbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47D63E2C2C2EAD220055E7D8 /* Mindbox.framework */; }; 47FFE2232C187B650007E2F6 /* Item+SwiftData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472423982C185B8400B2A9BC /* Item+SwiftData.swift */; }; 47FFE2262C187D3C0007E2F6 /* SwiftDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47FFE2252C187D3C0007E2F6 /* SwiftDataManager.swift */; }; 47FFE2282C187D5C0007E2F6 /* SwiftDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47FFE2252C187D3C0007E2F6 /* SwiftDataManager.swift */; }; - 47FFE22A2C1885A90007E2F6 /* MBPushNotification+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4774807E2C174C2000580FB2 /* MBPushNotification+Extensions.swift */; }; 47FFE22C2C1886550007E2F6 /* Payload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 477480792C174BAA00580FB2 /* Payload.swift */; }; 9E3108F96D4F26745D3B37A4 /* Pods_MindboxNotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4AF2BFD8ABA97C73F589C5DB /* Pods_MindboxNotificationServiceExtension.framework */; }; D9585975AC05213E1682C760 /* Pods_MindboxNotificationContentExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91EB2315545CE887D05CB505 /* Pods_MindboxNotificationContentExtension.framework */; }; @@ -102,7 +99,6 @@ 474F37A32C16F5B000F38BB0 /* NotificationCenterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCenterView.swift; sourceTree = ""; }; 474F37AD2C170FB600F38BB0 /* NotificationCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCellView.swift; sourceTree = ""; }; 477480792C174BAA00580FB2 /* Payload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Payload.swift; sourceTree = ""; }; - 4774807E2C174C2000580FB2 /* MBPushNotification+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MBPushNotification+Extensions.swift"; sourceTree = ""; }; 47D63E2C2C2EAD220055E7D8 /* Mindbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Mindbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 47FFE2252C187D3C0007E2F6 /* SwiftDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDataManager.swift; sourceTree = ""; }; 4AF2BFD8ABA97C73F589C5DB /* Pods_MindboxNotificationServiceExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MindboxNotificationServiceExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -120,7 +116,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 47D63E2D2C2EAD220055E7D8 /* Mindbox.framework in Frameworks */, 9E3108F96D4F26745D3B37A4 /* Pods_MindboxNotificationServiceExtension.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -202,7 +197,6 @@ 474F37AF2C1710BB00F38BB0 /* Models */, 0AEDBC9D2BB71FC600EE8722 /* Views */, 0AEDBC9E2BB71FD700EE8722 /* ViewModels */, - 4774807B2C174BD900580FB2 /* Extensions */, ); path = Example; sourceTree = ""; @@ -254,14 +248,6 @@ path = Models; sourceTree = ""; }; - 4774807B2C174BD900580FB2 /* Extensions */ = { - isa = PBXGroup; - children = ( - 4774807E2C174C2000580FB2 /* MBPushNotification+Extensions.swift */, - ); - path = Extensions; - sourceTree = ""; - }; 477480842C1760BE00580FB2 /* ChooseInAppMessagesDelegate */ = { isa = PBXGroup; children = ( @@ -529,7 +515,6 @@ 47FFE2232C187B650007E2F6 /* Item+SwiftData.swift in Sources */, 0A0DE3482BB8455A00812E73 /* NotificationService.swift in Sources */, 47FFE22C2C1886550007E2F6 /* Payload.swift in Sources */, - 47FFE22A2C1885A90007E2F6 /* MBPushNotification+Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -558,7 +543,6 @@ 0AEDBC7C2BB6F8F200EE8722 /* SceneDelegate.swift in Sources */, 0AEDBC9B2BB70D6E00EE8722 /* SDKDataView.swift in Sources */, 0A4B681A2BBC82B500639BC5 /* ChooseInAppMessagesDelegate.swift in Sources */, - 4774807F2C174C2000580FB2 /* MBPushNotification+Extensions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -590,7 +574,6 @@ "$(inherited)", "\"${PODS_CONFIGURATION_BUILD_DIR}/MindboxLogger\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/MindboxNotifications\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/Mindbox\"", ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = MindboxNotificationServiceExtension/Info.plist; @@ -624,7 +607,6 @@ "$(inherited)", "\"${PODS_CONFIGURATION_BUILD_DIR}/MindboxLogger\"", "\"${PODS_CONFIGURATION_BUILD_DIR}/MindboxNotifications\"", - "\"${PODS_CONFIGURATION_BUILD_DIR}/Mindbox\"", ); GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = MindboxNotificationServiceExtension/Info.plist; diff --git a/Example/Example/Extensions/MBPushNotification+Extensions.swift b/Example/Example/Extensions/MBPushNotification+Extensions.swift deleted file mode 100644 index 55b26d64..00000000 --- a/Example/Example/Extensions/MBPushNotification+Extensions.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// MBPushNotification+Extensions.swift -// Example -// -// Created by Sergei Semko on 6/10/24. -// Copyright © 2024 Mindbox. All rights reserved. -// - -import Foundation -import Mindbox - -public extension MBPushNotification { - init?(jsonString: String) { - guard let jsonData = jsonString.data(using: .utf8) else { - return nil - } - - do { - let decoder = JSONDecoder() - self = try decoder.decode(Self.self, from: jsonData) - } catch { - print(error.localizedDescription) - return nil - } - } - - var decodedPayload: Payload? { - guard let payloadData = payload?.data(using: .utf8) else { return nil } - return try? JSONDecoder().decode(Payload.self, from: payloadData) - } -} diff --git a/Example/Example/Models/Item+SwiftData.swift b/Example/Example/Models/Item+SwiftData.swift index 243a3208..207c4674 100644 --- a/Example/Example/Models/Item+SwiftData.swift +++ b/Example/Example/Models/Item+SwiftData.swift @@ -7,16 +7,29 @@ // import Foundation -import Mindbox import SwiftData @Model public final class Item { public var timestamp: Date - public var mbPushNotification: MBPushNotification + public var mbPushNotification: PushNotification - public init(timestamp: Date, pushNotification: MBPushNotification) { + public init(timestamp: Date, pushNotification: PushNotification) { self.timestamp = timestamp self.mbPushNotification = pushNotification } } + +public struct PushNotification: Codable { + public let title: String? + public let body: String? + public let clickUrl: String? + public let imageUrl: String? + public let payload: String? + public let uniqueKey: String? + + var decodedPayload: Payload? { + guard let payloadData = payload?.data(using: .utf8) else { return nil } + return try? JSONDecoder().decode(Payload.self, from: payloadData) + } +} diff --git a/Example/Example/Services/SwiftDataManager.swift b/Example/Example/Services/SwiftDataManager.swift index 068d2021..0133ad3c 100644 --- a/Example/Example/Services/SwiftDataManager.swift +++ b/Example/Example/Services/SwiftDataManager.swift @@ -7,7 +7,6 @@ // import Foundation -import Mindbox import SwiftData import SwiftUI @@ -48,12 +47,8 @@ public struct SwiftDataManager { private func saveMockData() { let context = SwiftDataManager.shared.container.mainContext - testNotifications.forEach { notification in - guard let pushNotification = MBPushNotification(jsonString: notification) else { - print("Failed to create MBPushNotification") - return - } - let newItem = Item(timestamp: Date(), pushNotification: pushNotification) + mockNotifications.forEach { notification in + let newItem = Item(timestamp: Date(), pushNotification: notification) context.insert(newItem) @@ -67,64 +62,34 @@ public struct SwiftDataManager { } private extension SwiftDataManager { - var testNotifications: [String] { + var mockNotifications: [PushNotification] { [ - """ - { - "aps": { - "alert": { - "title": "First notification title", - "body": "First notification body" - }, - "sound": "default", - "mutable-content": 1, - "content-available": 1 - }, - "uniqueKey": "Push unique key: 1", - "imageUrl": "https://mobpush-images.mindbox.ru/Mpush-test/1a73ebaa-3e5f-49f4-ae6c-462c9b64d34c/307be696-77e6-4d83-b7eb-c94be85f7a03.png", - "payload": "{\\"pushName\\": \\"\\", \\"pushDate\\": \\"\\"}", - "buttons": [], - "clickUrl": "https://mindbox.ru/" - } - """, + PushNotification( + title: "First notification title", + body: "First notification body", + clickUrl: "https://mindbox.ru/", + imageUrl: "https://mobpush-images.mindbox.ru/Mpush-test/1a73ebaa-3e5f-49f4-ae6c-462c9b64d34c/307be696-77e6-4d83-b7eb-c94be85f7a03.png", + payload: "{\"pushName\": \"\", \"pushDate\": \"\"}", + uniqueKey: "Push unique key: 1" + ), - """ - { - "aps": { - "alert": { - "title": "Second notification title", - "body": "Second notification body" - }, - "sound": "default", - "mutable-content": 1, - "content-available": 1 - }, - "uniqueKey": "Push unique key: 2", - "imageUrl": "https://mobpush-images.mindbox.ru/Mpush-test/1a73ebaa-3e5f-49f4-ae6c-462c9b64d34c/2397fea9-383d-49bf-a6a0-181a267faa94.png", - "payload": "{\\"pushName\\": \\"\\", \\"pushDate\\": \\"\\"}", - "buttons": [], - "clickUrl": "https://mindbox.ru/" - } - """, + PushNotification( + title: "Second notification title", + body: "Second notification body", + clickUrl: "https://mindbox.ru/", + imageUrl: "https://mobpush-images.mindbox.ru/Mpush-test/1a73ebaa-3e5f-49f4-ae6c-462c9b64d34c/2397fea9-383d-49bf-a6a0-181a267faa94.png", + payload: "{\"pushName\": \"\", \"pushDate\": \"\"}", + uniqueKey: "Push unique key: 2" + ), - """ - { - "aps": { - "alert": { - "title": "Third notification title", - "body": "Third notification body" - }, - "sound": "default", - "mutable-content": 1, - "content-available": 1 - }, - "uniqueKey": "Push unique key: 3", - "imageUrl": "https://mobpush-images.mindbox.ru/Mpush-test/1a73ebaa-3e5f-49f4-ae6c-462c9b64d34c/bd4250b1-a7ac-4b8a-b91b-481b3b5c565c.png", - "payload": "{\\"pushName\\": \\"\\", \\"pushDate\\": \\"\\"}", - "buttons": [], - "clickUrl": "https://mindbox.ru/" - } - """ + PushNotification( + title: "Third notification title", + body: "Third notification body", + clickUrl: "https://mindbox.ru/", + imageUrl: "https://mobpush-images.mindbox.ru/Mpush-test/1a73ebaa-3e5f-49f4-ae6c-462c9b64d34c/bd4250b1-a7ac-4b8a-b91b-481b3b5c565c.png", + payload: "{\"pushName\": \"\", \"pushDate\": \"\"}", + uniqueKey: "Push unique key: 3" + ), ] } } diff --git a/Example/Example/ViewModels/NotificationCenterViewModel.swift b/Example/Example/ViewModels/NotificationCenterViewModel.swift index 5f17d310..882ac0b8 100644 --- a/Example/Example/ViewModels/NotificationCenterViewModel.swift +++ b/Example/Example/ViewModels/NotificationCenterViewModel.swift @@ -10,10 +10,10 @@ import Mindbox import Observation protocol NotificationCenterViewModelProtocol: AnyObject { - var lastTappedNotification: MBPushNotification? { get } + var lastTappedNotification: PushNotification? { get } var errorMessage: String? { get } - func sendOperationNCPushOpen(notification: MBPushNotification) + func sendOperationNCPushOpen(notification: PushNotification) func sendOperationNCOpen() } @@ -21,9 +21,9 @@ protocol NotificationCenterViewModelProtocol: AnyObject { // MARK: - NotificationCenterViewModelProtocol var errorMessage: String? - var lastTappedNotification: MBPushNotification? + var lastTappedNotification: PushNotification? - func sendOperationNCPushOpen(notification: MBPushNotification) { + func sendOperationNCPushOpen(notification: PushNotification) { lastTappedNotification = notification /*Assuming payload of push notification has this structure: diff --git a/Example/Example/Views/NotificationCenterViews/NotificationCellView.swift b/Example/Example/Views/NotificationCenterViews/NotificationCellView.swift index c459efa6..cd477a7d 100644 --- a/Example/Example/Views/NotificationCenterViews/NotificationCellView.swift +++ b/Example/Example/Views/NotificationCenterViews/NotificationCellView.swift @@ -10,7 +10,7 @@ import SwiftUI import Mindbox struct NotificationCellView: View { - var notification: MBPushNotification + var notification: PushNotification var body: some View { HStack(alignment: .center, content: { @@ -27,9 +27,9 @@ struct NotificationCellView: View { } VStack(alignment: .leading, content: { - Text(notification.aps?.alert?.title ?? "Empty") + Text(notification.title ?? "Empty") .font(.headline) - Text(notification.aps?.alert?.body ?? "Empty") + Text(notification.body ?? "Empty") .font(.subheadline) .foregroundStyle(.gray) Text(notification.clickUrl ?? "Empty") diff --git a/Example/MindboxNotificationServiceExtension/NotificationService.swift b/Example/MindboxNotificationServiceExtension/NotificationService.swift index 78f25e0d..ab6ef4b9 100644 --- a/Example/MindboxNotificationServiceExtension/NotificationService.swift +++ b/Example/MindboxNotificationServiceExtension/NotificationService.swift @@ -8,15 +8,15 @@ import UserNotifications import MindboxNotifications -import Mindbox class NotificationService: UNNotificationServiceExtension { lazy var mindboxService = MindboxNotificationService() override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + let userInfo = request.content.userInfo - if let mindboxPushNotification = Mindbox.shared.getMindboxPushData(userInfo: request.content.userInfo) { + if mindboxService.isMindboxPush(userInfo: userInfo), let mindboxPushNotification = mindboxService.getMindboxPushData(userInfo: userInfo) { Task { await saveSwiftDataItem(mindboxPushNotification) } @@ -32,10 +32,16 @@ class NotificationService: UNNotificationServiceExtension { } @MainActor - private func saveSwiftDataItem(_ pushNotification: MBPushNotification) async { + private func saveSwiftDataItem(_ mindboxPushNotification: MBPushNotification) async { let context = SwiftDataManager.shared.container.mainContext - let newItem = Item(timestamp: Date(), pushNotification: pushNotification) + let push = PushNotification(title: mindboxPushNotification.aps?.alert?.title, + body: mindboxPushNotification.aps?.alert?.body, + clickUrl: mindboxPushNotification.clickUrl, + imageUrl: mindboxPushNotification.imageUrl, + payload: mindboxPushNotification.payload, + uniqueKey: mindboxPushNotification.uniqueKey) + let newItem = Item(timestamp: Date(), pushNotification: push) context.insert(newItem) do { diff --git a/Example/Podfile b/Example/Podfile index 56f4389a..c5a7635d 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,13 +1,13 @@ use_frameworks! target 'Example' do - pod 'Mindbox', '2.11.0' + pod 'Mindbox', '2.11.1' end target 'MindboxNotificationServiceExtension' do - pod 'MindboxNotifications', '2.11.0' + pod 'MindboxNotifications', '2.11.1' end target 'MindboxNotificationContentExtension' do - pod 'MindboxNotifications', '2.11.0' + pod 'MindboxNotifications', '2.11.1' end diff --git a/Gemfile.lock b/Gemfile.lock index 8c944d1c..9cbcc6ce 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,16 +5,17 @@ GEM base64 nkf rexml - activesupport (7.1.3.4) + activesupport (7.2.1) base64 bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) algoliasearch (1.27.5) @@ -23,20 +24,20 @@ GEM artifactory (3.0.17) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.960.0) - aws-sdk-core (3.201.3) + aws-partitions (1.981.0) + aws-sdk-core (3.209.1) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.8) + aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.88.0) - aws-sdk-core (~> 3, >= 3.201.0) + aws-sdk-kms (1.94.0) + aws-sdk-core (~> 3, >= 3.207.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.156.0) - aws-sdk-core (~> 3, >= 3.201.0) + aws-sdk-s3 (1.166.0) + aws-sdk-core (~> 3, >= 3.207.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.9.1) + aws-sigv4 (1.10.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -83,7 +84,7 @@ GEM colored2 (3.1.2) commander (4.6.0) highline (~> 2.0.0) - concurrent-ruby (1.3.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) declarative (0.0.20) digest-crc (0.6.5) @@ -96,7 +97,7 @@ GEM ethon (0.16.0) ffi (>= 1.15.0) excon (0.111.0) - faraday (1.10.3) + faraday (1.10.4) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -122,10 +123,10 @@ GEM faraday-patron (1.0.0) faraday-rack (1.0.0) faraday-retry (1.0.3) - faraday_middleware (1.2.0) + faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.222.0) + fastlane (2.223.1) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -166,9 +167,17 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + ffi (1.17.0) + ffi (1.17.0-aarch64-linux-gnu) + ffi (1.17.0-aarch64-linux-musl) + ffi (1.17.0-arm-linux-gnu) + ffi (1.17.0-arm-linux-musl) ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86-linux-gnu) + ffi (1.17.0-x86-linux-musl) ffi (1.17.0-x86_64-darwin) ffi (1.17.0-x86_64-linux-gnu) + ffi (1.17.0-x86_64-linux-musl) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) @@ -188,7 +197,7 @@ GEM google-apis-core (>= 0.11.0, < 2.a) google-apis-storage_v1 (0.31.0) google-apis-core (>= 0.11.0, < 2.a) - google-cloud-core (1.7.0) + google-cloud-core (1.7.1) google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) @@ -209,22 +218,22 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.6) + http-cookie (1.0.7) domain_name (~> 0.5) httpclient (2.8.3) - i18n (1.14.5) + i18n (1.14.6) concurrent-ruby (~> 1.0) jmespath (1.6.2) json (2.7.2) - jwt (2.8.2) + jwt (2.9.1) base64 + logger (1.6.1) mini_magick (4.13.2) mini_mime (1.1.5) - minitest (5.24.1) + minitest (5.25.1) molinillo (0.8.0) multi_json (1.15.0) multipart-post (2.4.1) - mutex_m (0.2.0) nanaimo (0.3.0) nap (1.1.0) naturally (2.2.1) @@ -240,12 +249,12 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.6) - strscan + rexml (3.3.8) rouge (2.0.7) ruby-macho (2.5.1) ruby2_keywords (0.0.5) rubyzip (2.3.2) + securerandom (0.3.1) security (0.1.5) signet (0.19.0) addressable (~> 2.8) @@ -255,7 +264,6 @@ GEM simctl (1.6.10) CFPropertyList naturally - strscan (3.1.0) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -269,7 +277,7 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) uber (0.1.0) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) word_wrap (1.0.0) xcodeproj (1.25.0) CFPropertyList (>= 2.3.3, < 4.0) @@ -284,14 +292,21 @@ GEM xcpretty (~> 0.2, >= 0.0.7) PLATFORMS - arm64-darwin-21 - arm64-darwin-23 - x86_64-darwin-21 - x86_64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + ruby + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl DEPENDENCIES cocoapods fastlane BUNDLED WITH - 2.3.26 + 2.5.18 diff --git a/Mindbox.podspec b/Mindbox.podspec index ecbe5f25..c82ac7b5 100644 --- a/Mindbox.podspec +++ b/Mindbox.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = "Mindbox" - spec.version = "2.11.0" + spec.version = "2.11.1" spec.summary = "SDK for integration with Mindbox" spec.description = "This library allows you to integrate data transfer to Mindbox Marketing Cloud" spec.homepage = "https://github.com/mindbox-cloud/ios-sdk" @@ -14,6 +14,6 @@ Pod::Spec.new do |spec| 'Mindbox' => ['Mindbox/**/*.xcassets', 'Mindbox/**/*.xcdatamodeld', 'Mindbox/**/*.xcprivacy'] } spec.swift_version = "5" - spec.dependency 'MindboxLogger', '2.11.0' + spec.dependency 'MindboxLogger', '2.11.1' end diff --git a/Mindbox.xcodeproj/project.pbxproj b/Mindbox.xcodeproj/project.pbxproj index 00a80393..5cf324c2 100644 --- a/Mindbox.xcodeproj/project.pbxproj +++ b/Mindbox.xcodeproj/project.pbxproj @@ -94,12 +94,44 @@ 33C81EA4264145CD00863380 /* TimerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C81EA3264145CD00863380 /* TimerManager.swift */; }; 33E42E5C268323E60046CBCB /* CashdeskRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33E42E5B268323E60046CBCB /* CashdeskRequest.swift */; }; 33EBF0B0264E6283002A35D5 /* MBSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33EBF0AF264E6283002A35D5 /* MBSessionManager.swift */; }; + 472179A72C80755A00C15E7F /* ShownInAppsIdsMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472179A62C80755A00C15E7F /* ShownInAppsIdsMigration.swift */; }; 472F549E2C6E272A0008C465 /* MBPushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F549D2C6E272A0008C465 /* MBPushNotification.swift */; }; 472F54A32C6E27C80008C465 /* NotificationFormatStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F54A22C6E27C80008C465 /* NotificationFormatStrategy.swift */; }; 472F54A52C6E27DD0008C465 /* NotificationStrategyFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F54A42C6E27DD0008C465 /* NotificationStrategyFactory.swift */; }; 472F54A72C6E28030008C465 /* NotificationFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F54A62C6E28030008C465 /* NotificationFormatter.swift */; }; 472F54AA2C6E294F0008C465 /* PushValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F54A92C6E294F0008C465 /* PushValidator.swift */; }; 472F54AC2C6E29E50008C465 /* MindboxPushNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472F54AB2C6E29E50008C465 /* MindboxPushNotification.swift */; }; + 473A98262C918C3A005A3B94 /* ConfigParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 473A98252C918C3A005A3B94 /* ConfigParsingTests.swift */; }; + 473A982D2C91A38C005A3B94 /* SettingsConfigParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 473A982C2C91A38C005A3B94 /* SettingsConfigParsingTests.swift */; }; + 473A98332C91A4B3005A3B94 /* MonitoringConfigParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 473A98322C91A4B3005A3B94 /* MonitoringConfigParsingTests.swift */; }; + 473A98362C91A7AB005A3B94 /* GetConfigFunc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 473A98352C91A7AB005A3B94 /* GetConfigFunc.swift */; }; + 473A98382C91ABD9005A3B94 /* ConfigWithSettingsABTestsMonitoringInapps.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98372C91ABD9005A3B94 /* ConfigWithSettingsABTestsMonitoringInapps.json */; }; + 473A983A2C91ABF5005A3B94 /* SettingsConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98392C91ABF5005A3B94 /* SettingsConfig.json */; }; + 473A983C2C91ABFB005A3B94 /* MonitoringConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A983B2C91ABFB005A3B94 /* MonitoringConfig.json */; }; + 473A98412C91AD85005A3B94 /* SettingsTtlInappsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98402C91AD85005A3B94 /* SettingsTtlInappsError.json */; }; + 473A98432C91AD8A005A3B94 /* SettingsTtlInappsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98422C91AD89005A3B94 /* SettingsTtlInappsTypeError.json */; }; + 473A98452C91B309005A3B94 /* SettingsTtlError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98442C91B309005A3B94 /* SettingsTtlError.json */; }; + 473A98472C91B323005A3B94 /* SettingsTtlTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98462C91B323005A3B94 /* SettingsTtlTypeError.json */; }; + 473A984B2C91B606005A3B94 /* SettingsOperationsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A984A2C91B606005A3B94 /* SettingsOperationsError.json */; }; + 473A984D2C91B620005A3B94 /* SettingsOperationsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A984C2C91B620005A3B94 /* SettingsOperationsTypeError.json */; }; + 473A984F2C91B641005A3B94 /* SettingsOperationsViewProductError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A984E2C91B641005A3B94 /* SettingsOperationsViewProductError.json */; }; + 473A98512C91B66B005A3B94 /* SettingsOperationsViewProductSystemNameError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98502C91B66B005A3B94 /* SettingsOperationsViewProductSystemNameError.json */; }; + 473A98532C91B68D005A3B94 /* SettingsOperationsViewProductSystemNameTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98522C91B68D005A3B94 /* SettingsOperationsViewProductSystemNameTypeError.json */; }; + 473A98552C91B6B6005A3B94 /* SettingsOperationsViewProductTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98542C91B6B6005A3B94 /* SettingsOperationsViewProductTypeError.json */; }; + 473A98572C91BB02005A3B94 /* SettingsAllOperationsWithErrors.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98562C91BB02005A3B94 /* SettingsAllOperationsWithErrors.json */; }; + 473A98592C91BB1B005A3B94 /* SettingsAllOperationsWithTypeErrors.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98582C91BB1B005A3B94 /* SettingsAllOperationsWithTypeErrors.json */; }; + 473A985B2C91D1B3005A3B94 /* SettingsOperationsViewCategoryAndSetCartError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A985A2C91D1B3005A3B94 /* SettingsOperationsViewCategoryAndSetCartError.json */; }; + 473A985D2C91D1CE005A3B94 /* SettingsOperationsViewCategoryAndSetCartTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A985C2C91D1CE005A3B94 /* SettingsOperationsViewCategoryAndSetCartTypeError.json */; }; + 473A985F2C91D20B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A985E2C91D20B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameError.json */; }; + 473A98612C91D22B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98602C91D22B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json */; }; + 473A98632C91D256005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98622C91D256005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json */; }; + 473A98652C91DFB5005A3B94 /* MonitoringLogsOneElementError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98642C91DFB5005A3B94 /* MonitoringLogsOneElementError.json */; }; + 473A98672C91DFD1005A3B94 /* MonitoringLogsTwoElementsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98662C91DFD1005A3B94 /* MonitoringLogsTwoElementsError.json */; }; + 473A98692C91DFEA005A3B94 /* MonitoringLogsOneElementTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98682C91DFEA005A3B94 /* MonitoringLogsOneElementTypeError.json */; }; + 473A986B2C91E010005A3B94 /* MonitoringLogsTwoElementsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A986A2C91E010005A3B94 /* MonitoringLogsTwoElementsTypeError.json */; }; + 473A986D2C91E032005A3B94 /* MonitoringLogsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A986C2C91E032005A3B94 /* MonitoringLogsError.json */; }; + 473A986F2C91E047005A3B94 /* MonitoringLogsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A986E2C91E047005A3B94 /* MonitoringLogsTypeError.json */; }; + 473A98712C91E629005A3B94 /* MonitoringLogsElementsMixedError.json in Resources */ = {isa = PBXBuildFile; fileRef = 473A98702C91E629005A3B94 /* MonitoringLogsElementsMixedError.json */; }; 4747708B2C6B838B00C36FC8 /* SharedInternalMethodsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4747708A2C6B838B00C36FC8 /* SharedInternalMethodsTests.swift */; }; 4747708F2C6B93AC00C36FC8 /* MindboxNotificationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4747708E2C6B93AC00C36FC8 /* MindboxNotificationServiceTests.swift */; }; 474770912C6B9A7200C36FC8 /* MindboxNotificationContentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474770902C6B9A7200C36FC8 /* MindboxNotificationContentTests.swift */; }; @@ -108,6 +140,25 @@ 474851C52C6A62AE0026C38E /* NotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474851C42C6A62AE0026C38E /* NotificationContent.swift */; }; 474851C72C6A63C30026C38E /* SharedInternalMethods.swift in Sources */ = {isa = PBXBuildFile; fileRef = 474851C62C6A63C30026C38E /* SharedInternalMethods.swift */; }; 475558C32C59300400CDA026 /* MigrationManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 475558C22C59300400CDA026 /* MigrationManagerTests.swift */; }; + 476689C72C85B6AE0066BB12 /* ShownInAppsIdsMigrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 476689C62C85B6AE0066BB12 /* ShownInAppsIdsMigrationTests.swift */; }; + 4766A8942C92FEF6002D15A4 /* SettingsOperationsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4766A8932C92FEF6002D15A4 /* SettingsOperationsModel.swift */; }; + 4766A8962C92FF3A002D15A4 /* TimeToLiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4766A8952C92FF3A002D15A4 /* TimeToLiveModel.swift */; }; + 4766A8992C931B30002D15A4 /* ConfigSettingsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8982C931B30002D15A4 /* ConfigSettingsError.json */; }; + 4766A89B2C931B51002D15A4 /* ConfigSettingsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A89A2C931B51002D15A4 /* ConfigSettingsTypeError.json */; }; + 4766A89D2C931BD6002D15A4 /* ConfigMonitoringError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A89C2C931BD6002D15A4 /* ConfigMonitoringError.json */; }; + 4766A89F2C931BEC002D15A4 /* ConfigMonitoringTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A89E2C931BEC002D15A4 /* ConfigMonitoringTypeError.json */; }; + 4766A8A12C931CDA002D15A4 /* ConfigABTestsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8A02C931CDA002D15A4 /* ConfigABTestsError.json */; }; + 4766A8A32C931CF8002D15A4 /* ConfigABTestsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8A22C931CF8002D15A4 /* ConfigABTestsTypeError.json */; }; + 4766A8A52C931E27002D15A4 /* ConfigInAppsError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8A42C931E27002D15A4 /* ConfigInAppsError.json */; }; + 4766A8A72C931E40002D15A4 /* ConfigInAppsTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8A62C931E40002D15A4 /* ConfigInAppsTypeError.json */; }; + 4766A8AE2C9325B0002D15A4 /* ABTestsConfigParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4766A8AD2C9325B0002D15A4 /* ABTestsConfigParsingTests.swift */; }; + 4766A8B02C932624002D15A4 /* ABTestsConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8AF2C932624002D15A4 /* ABTestsConfig.json */; }; + 4766A8B22C932A3C002D15A4 /* ABTestsIdConfigError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8B12C932A3C002D15A4 /* ABTestsIdConfigError.json */; }; + 4766A8B42C932C79002D15A4 /* ABTestsIdConfigTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8B32C932C79002D15A4 /* ABTestsIdConfigTypeError.json */; }; + 4766A8B62C932D92002D15A4 /* ABTestsSdkVersionConfigError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8B52C932D92002D15A4 /* ABTestsSdkVersionConfigError.json */; }; + 4766A8B82C932EFC002D15A4 /* ABTestsSdkVersionConfigTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8B72C932EFC002D15A4 /* ABTestsSdkVersionConfigTypeError.json */; }; + 4766A8BC2C9332ED002D15A4 /* ConfigABTestsOneElementError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8BB2C9332ED002D15A4 /* ConfigABTestsOneElementError.json */; }; + 4766A8BE2C933416002D15A4 /* ConfigABTestsOneElementTypeError.json in Resources */ = {isa = PBXBuildFile; fileRef = 4766A8BD2C933416002D15A4 /* ConfigABTestsOneElementTypeError.json */; }; 47B90E2F2C625F9A00BD93E7 /* TestBaseMigrations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B90E2E2C625F9A00BD93E7 /* TestBaseMigrations.swift */; }; 47B90E312C626B9300BD93E7 /* TestProtocolMigrations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B90E302C626B9300BD93E7 /* TestProtocolMigrations.swift */; }; 47BD5BFB2C578BC600F965C0 /* MigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47BD5BFA2C578BC600F965C0 /* MigrationManager.swift */; }; @@ -363,7 +414,6 @@ F331DD0B2A83A56500222120 /* CrossView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DCFD2A83A56500222120 /* CrossView.swift */; }; F331DD0C2A83A56500222120 /* ViewFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DCFF2A83A56500222120 /* ViewFactoryProtocol.swift */; }; F331DD0D2A83A56500222120 /* ModalViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DD002A83A56500222120 /* ModalViewFactory.swift */; }; - F331DD112A83CA7500222120 /* KeyedDecodingContainer+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DD102A83CA7400222120 /* KeyedDecodingContainer+Extensions.swift */; }; F331DD162A840D1700222120 /* iFormVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DD152A840D1700222120 /* iFormVariant.swift */; }; F331DD192A840D2100222120 /* ModalFormVariant.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DD182A840D2100222120 /* ModalFormVariant.swift */; }; F331DD1C2A84B5EF00222120 /* ImageContentBackgroundLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F331DD1B2A84B5EF00222120 /* ImageContentBackgroundLayer.swift */; }; @@ -637,12 +687,44 @@ 33C81EA3264145CD00863380 /* TimerManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimerManager.swift; sourceTree = ""; }; 33E42E5B268323E60046CBCB /* CashdeskRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CashdeskRequest.swift; sourceTree = ""; }; 33EBF0AF264E6283002A35D5 /* MBSessionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MBSessionManager.swift; sourceTree = ""; }; + 472179A62C80755A00C15E7F /* ShownInAppsIdsMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShownInAppsIdsMigration.swift; sourceTree = ""; }; 472F549D2C6E272A0008C465 /* MBPushNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MBPushNotification.swift; sourceTree = ""; }; 472F54A22C6E27C80008C465 /* NotificationFormatStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationFormatStrategy.swift; sourceTree = ""; }; 472F54A42C6E27DD0008C465 /* NotificationStrategyFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationStrategyFactory.swift; sourceTree = ""; }; 472F54A62C6E28030008C465 /* NotificationFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationFormatter.swift; sourceTree = ""; }; 472F54A92C6E294F0008C465 /* PushValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushValidator.swift; sourceTree = ""; }; 472F54AB2C6E29E50008C465 /* MindboxPushNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MindboxPushNotification.swift; sourceTree = ""; }; + 473A98252C918C3A005A3B94 /* ConfigParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigParsingTests.swift; sourceTree = ""; }; + 473A982C2C91A38C005A3B94 /* SettingsConfigParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsConfigParsingTests.swift; sourceTree = ""; }; + 473A98322C91A4B3005A3B94 /* MonitoringConfigParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonitoringConfigParsingTests.swift; sourceTree = ""; }; + 473A98352C91A7AB005A3B94 /* GetConfigFunc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetConfigFunc.swift; sourceTree = ""; }; + 473A98372C91ABD9005A3B94 /* ConfigWithSettingsABTestsMonitoringInapps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigWithSettingsABTestsMonitoringInapps.json; sourceTree = ""; }; + 473A98392C91ABF5005A3B94 /* SettingsConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsConfig.json; sourceTree = ""; }; + 473A983B2C91ABFB005A3B94 /* MonitoringConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringConfig.json; sourceTree = ""; }; + 473A98402C91AD85005A3B94 /* SettingsTtlInappsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsTtlInappsError.json; sourceTree = ""; }; + 473A98422C91AD89005A3B94 /* SettingsTtlInappsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsTtlInappsTypeError.json; sourceTree = ""; }; + 473A98442C91B309005A3B94 /* SettingsTtlError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsTtlError.json; sourceTree = ""; }; + 473A98462C91B323005A3B94 /* SettingsTtlTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsTtlTypeError.json; sourceTree = ""; }; + 473A984A2C91B606005A3B94 /* SettingsOperationsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsError.json; sourceTree = ""; }; + 473A984C2C91B620005A3B94 /* SettingsOperationsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsTypeError.json; sourceTree = ""; }; + 473A984E2C91B641005A3B94 /* SettingsOperationsViewProductError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewProductError.json; sourceTree = ""; }; + 473A98502C91B66B005A3B94 /* SettingsOperationsViewProductSystemNameError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewProductSystemNameError.json; sourceTree = ""; }; + 473A98522C91B68D005A3B94 /* SettingsOperationsViewProductSystemNameTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewProductSystemNameTypeError.json; sourceTree = ""; }; + 473A98542C91B6B6005A3B94 /* SettingsOperationsViewProductTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewProductTypeError.json; sourceTree = ""; }; + 473A98562C91BB02005A3B94 /* SettingsAllOperationsWithErrors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsAllOperationsWithErrors.json; sourceTree = ""; }; + 473A98582C91BB1B005A3B94 /* SettingsAllOperationsWithTypeErrors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsAllOperationsWithTypeErrors.json; sourceTree = ""; }; + 473A985A2C91D1B3005A3B94 /* SettingsOperationsViewCategoryAndSetCartError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewCategoryAndSetCartError.json; sourceTree = ""; }; + 473A985C2C91D1CE005A3B94 /* SettingsOperationsViewCategoryAndSetCartTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewCategoryAndSetCartTypeError.json; sourceTree = ""; }; + 473A985E2C91D20B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewCategoryAndSetCartSystemNameError.json; sourceTree = ""; }; + 473A98602C91D22B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json; sourceTree = ""; }; + 473A98622C91D256005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json; sourceTree = ""; }; + 473A98642C91DFB5005A3B94 /* MonitoringLogsOneElementError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsOneElementError.json; sourceTree = ""; }; + 473A98662C91DFD1005A3B94 /* MonitoringLogsTwoElementsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsTwoElementsError.json; sourceTree = ""; }; + 473A98682C91DFEA005A3B94 /* MonitoringLogsOneElementTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsOneElementTypeError.json; sourceTree = ""; }; + 473A986A2C91E010005A3B94 /* MonitoringLogsTwoElementsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsTwoElementsTypeError.json; sourceTree = ""; }; + 473A986C2C91E032005A3B94 /* MonitoringLogsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsError.json; sourceTree = ""; }; + 473A986E2C91E047005A3B94 /* MonitoringLogsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsTypeError.json; sourceTree = ""; }; + 473A98702C91E629005A3B94 /* MonitoringLogsElementsMixedError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = MonitoringLogsElementsMixedError.json; sourceTree = ""; }; 4747708A2C6B838B00C36FC8 /* SharedInternalMethodsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedInternalMethodsTests.swift; sourceTree = ""; }; 4747708E2C6B93AC00C36FC8 /* MindboxNotificationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MindboxNotificationServiceTests.swift; sourceTree = ""; }; 474770902C6B9A7200C36FC8 /* MindboxNotificationContentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MindboxNotificationContentTests.swift; sourceTree = ""; }; @@ -651,6 +733,25 @@ 474851C42C6A62AE0026C38E /* NotificationContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContent.swift; sourceTree = ""; }; 474851C62C6A63C30026C38E /* SharedInternalMethods.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedInternalMethods.swift; sourceTree = ""; }; 475558C22C59300400CDA026 /* MigrationManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationManagerTests.swift; sourceTree = ""; }; + 476689C62C85B6AE0066BB12 /* ShownInAppsIdsMigrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShownInAppsIdsMigrationTests.swift; sourceTree = ""; }; + 4766A8932C92FEF6002D15A4 /* SettingsOperationsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsOperationsModel.swift; sourceTree = ""; }; + 4766A8952C92FF3A002D15A4 /* TimeToLiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeToLiveModel.swift; sourceTree = ""; }; + 4766A8982C931B30002D15A4 /* ConfigSettingsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigSettingsError.json; sourceTree = ""; }; + 4766A89A2C931B51002D15A4 /* ConfigSettingsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigSettingsTypeError.json; sourceTree = ""; }; + 4766A89C2C931BD6002D15A4 /* ConfigMonitoringError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigMonitoringError.json; sourceTree = ""; }; + 4766A89E2C931BEC002D15A4 /* ConfigMonitoringTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigMonitoringTypeError.json; sourceTree = ""; }; + 4766A8A02C931CDA002D15A4 /* ConfigABTestsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigABTestsError.json; sourceTree = ""; }; + 4766A8A22C931CF8002D15A4 /* ConfigABTestsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigABTestsTypeError.json; sourceTree = ""; }; + 4766A8A42C931E27002D15A4 /* ConfigInAppsError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigInAppsError.json; sourceTree = ""; }; + 4766A8A62C931E40002D15A4 /* ConfigInAppsTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigInAppsTypeError.json; sourceTree = ""; }; + 4766A8AD2C9325B0002D15A4 /* ABTestsConfigParsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ABTestsConfigParsingTests.swift; sourceTree = ""; }; + 4766A8AF2C932624002D15A4 /* ABTestsConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ABTestsConfig.json; sourceTree = ""; }; + 4766A8B12C932A3C002D15A4 /* ABTestsIdConfigError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ABTestsIdConfigError.json; sourceTree = ""; }; + 4766A8B32C932C79002D15A4 /* ABTestsIdConfigTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ABTestsIdConfigTypeError.json; sourceTree = ""; }; + 4766A8B52C932D92002D15A4 /* ABTestsSdkVersionConfigError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ABTestsSdkVersionConfigError.json; sourceTree = ""; }; + 4766A8B72C932EFC002D15A4 /* ABTestsSdkVersionConfigTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ABTestsSdkVersionConfigTypeError.json; sourceTree = ""; }; + 4766A8BB2C9332ED002D15A4 /* ConfigABTestsOneElementError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigABTestsOneElementError.json; sourceTree = ""; }; + 4766A8BD2C933416002D15A4 /* ConfigABTestsOneElementTypeError.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ConfigABTestsOneElementTypeError.json; sourceTree = ""; }; 47B90E2E2C625F9A00BD93E7 /* TestBaseMigrations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestBaseMigrations.swift; sourceTree = ""; }; 47B90E302C626B9300BD93E7 /* TestProtocolMigrations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProtocolMigrations.swift; sourceTree = ""; }; 47BD5BFA2C578BC600F965C0 /* MigrationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationManager.swift; sourceTree = ""; }; @@ -905,7 +1006,6 @@ F331DCFD2A83A56500222120 /* CrossView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrossView.swift; sourceTree = ""; }; F331DCFF2A83A56500222120 /* ViewFactoryProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewFactoryProtocol.swift; sourceTree = ""; }; F331DD002A83A56500222120 /* ModalViewFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModalViewFactory.swift; sourceTree = ""; }; - F331DD102A83CA7400222120 /* KeyedDecodingContainer+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "KeyedDecodingContainer+Extensions.swift"; sourceTree = ""; }; F331DD152A840D1700222120 /* iFormVariant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iFormVariant.swift; sourceTree = ""; }; F331DD182A840D2100222120 /* ModalFormVariant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModalFormVariant.swift; sourceTree = ""; }; F331DD1B2A84B5EF00222120 /* ImageContentBackgroundLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageContentBackgroundLayer.swift; sourceTree = ""; }; @@ -1165,6 +1265,7 @@ 313B233D25ADEA0F00A1CB72 /* MindboxTests */ = { isa = PBXGroup; children = ( + 473A98242C918C32005A3B94 /* ConfigParsing */, D216DE4F2C07168D0020F58A /* Extensions */, D2F7E2452BADB9EF00B24BB8 /* UserVisitManagerTests */, 475558C12C592FDE00CDA026 /* MigrationsTests */, @@ -1406,6 +1507,14 @@ path = SessionManager; sourceTree = ""; }; + 472179A52C80751F00C15E7F /* ImplementationOfMigrations */ = { + isa = PBXGroup; + children = ( + 472179A62C80755A00C15E7F /* ShownInAppsIdsMigration.swift */, + ); + path = ImplementationOfMigrations; + sourceTree = ""; + }; 472F549F2C6E27770008C465 /* PushNotifications */ = { isa = PBXGroup; children = ( @@ -1425,6 +1534,100 @@ path = PushNotificationFormatStrategies; sourceTree = ""; }; + 473A98242C918C32005A3B94 /* ConfigParsing */ = { + isa = PBXGroup; + children = ( + 473A98342C91A68D005A3B94 /* Helpers */, + 4766A8A82C932473002D15A4 /* Config */, + 473A983F2C91ACCD005A3B94 /* Monitoring */, + 473A983E2C91ACAF005A3B94 /* Settings */, + 4766A8A92C932484002D15A4 /* ABTests */, + ); + path = ConfigParsing; + sourceTree = ""; + }; + 473A982A2C919226005A3B94 /* SettingsJsonStubs */ = { + isa = PBXGroup; + children = ( + 473A98492C91B5E6005A3B94 /* OperationsErrors */, + 473A98482C91B5D8005A3B94 /* TtlErrors */, + 473A98392C91ABF5005A3B94 /* SettingsConfig.json */, + ); + path = SettingsJsonStubs; + sourceTree = ""; + }; + 473A982B2C919229005A3B94 /* MonitoringJsonStubs */ = { + isa = PBXGroup; + children = ( + 473A983B2C91ABFB005A3B94 /* MonitoringConfig.json */, + 473A986C2C91E032005A3B94 /* MonitoringLogsError.json */, + 473A986E2C91E047005A3B94 /* MonitoringLogsTypeError.json */, + 473A98642C91DFB5005A3B94 /* MonitoringLogsOneElementError.json */, + 473A98662C91DFD1005A3B94 /* MonitoringLogsTwoElementsError.json */, + 473A98682C91DFEA005A3B94 /* MonitoringLogsOneElementTypeError.json */, + 473A986A2C91E010005A3B94 /* MonitoringLogsTwoElementsTypeError.json */, + 473A98702C91E629005A3B94 /* MonitoringLogsElementsMixedError.json */, + ); + path = MonitoringJsonStubs; + sourceTree = ""; + }; + 473A98342C91A68D005A3B94 /* Helpers */ = { + isa = PBXGroup; + children = ( + 473A98352C91A7AB005A3B94 /* GetConfigFunc.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + 473A983E2C91ACAF005A3B94 /* Settings */ = { + isa = PBXGroup; + children = ( + 473A982A2C919226005A3B94 /* SettingsJsonStubs */, + 473A982C2C91A38C005A3B94 /* SettingsConfigParsingTests.swift */, + ); + path = Settings; + sourceTree = ""; + }; + 473A983F2C91ACCD005A3B94 /* Monitoring */ = { + isa = PBXGroup; + children = ( + 473A982B2C919229005A3B94 /* MonitoringJsonStubs */, + 473A98322C91A4B3005A3B94 /* MonitoringConfigParsingTests.swift */, + ); + path = Monitoring; + sourceTree = ""; + }; + 473A98482C91B5D8005A3B94 /* TtlErrors */ = { + isa = PBXGroup; + children = ( + 473A98442C91B309005A3B94 /* SettingsTtlError.json */, + 473A98462C91B323005A3B94 /* SettingsTtlTypeError.json */, + 473A98402C91AD85005A3B94 /* SettingsTtlInappsError.json */, + 473A98422C91AD89005A3B94 /* SettingsTtlInappsTypeError.json */, + ); + path = TtlErrors; + sourceTree = ""; + }; + 473A98492C91B5E6005A3B94 /* OperationsErrors */ = { + isa = PBXGroup; + children = ( + 473A984A2C91B606005A3B94 /* SettingsOperationsError.json */, + 473A984C2C91B620005A3B94 /* SettingsOperationsTypeError.json */, + 473A984E2C91B641005A3B94 /* SettingsOperationsViewProductError.json */, + 473A98542C91B6B6005A3B94 /* SettingsOperationsViewProductTypeError.json */, + 473A98502C91B66B005A3B94 /* SettingsOperationsViewProductSystemNameError.json */, + 473A98522C91B68D005A3B94 /* SettingsOperationsViewProductSystemNameTypeError.json */, + 473A98562C91BB02005A3B94 /* SettingsAllOperationsWithErrors.json */, + 473A98582C91BB1B005A3B94 /* SettingsAllOperationsWithTypeErrors.json */, + 473A985A2C91D1B3005A3B94 /* SettingsOperationsViewCategoryAndSetCartError.json */, + 473A985C2C91D1CE005A3B94 /* SettingsOperationsViewCategoryAndSetCartTypeError.json */, + 473A985E2C91D20B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameError.json */, + 473A98602C91D22B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json */, + 473A98622C91D256005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json */, + ); + path = OperationsErrors; + sourceTree = ""; + }; 474770892C6B813700C36FC8 /* Utilities */ = { isa = PBXGroup; children = ( @@ -1436,24 +1639,74 @@ 475558C12C592FDE00CDA026 /* MigrationsTests */ = { isa = PBXGroup; children = ( - 47B90E2D2C625F8A00BD93E7 /* TestMigrations */, + 47B90E2D2C625F8A00BD93E7 /* TestsMigrations */, 475558C22C59300400CDA026 /* MigrationManagerTests.swift */, + 476689C62C85B6AE0066BB12 /* ShownInAppsIdsMigrationTests.swift */, ); path = MigrationsTests; sourceTree = ""; }; - 47B90E2D2C625F8A00BD93E7 /* TestMigrations */ = { + 4766A8972C931AEE002D15A4 /* ConfigJsonStub */ = { + isa = PBXGroup; + children = ( + 473A98372C91ABD9005A3B94 /* ConfigWithSettingsABTestsMonitoringInapps.json */, + 4766A8982C931B30002D15A4 /* ConfigSettingsError.json */, + 4766A89A2C931B51002D15A4 /* ConfigSettingsTypeError.json */, + 4766A89C2C931BD6002D15A4 /* ConfigMonitoringError.json */, + 4766A89E2C931BEC002D15A4 /* ConfigMonitoringTypeError.json */, + 4766A8A02C931CDA002D15A4 /* ConfigABTestsError.json */, + 4766A8A22C931CF8002D15A4 /* ConfigABTestsTypeError.json */, + 4766A8A42C931E27002D15A4 /* ConfigInAppsError.json */, + 4766A8A62C931E40002D15A4 /* ConfigInAppsTypeError.json */, + 4766A8BB2C9332ED002D15A4 /* ConfigABTestsOneElementError.json */, + 4766A8BD2C933416002D15A4 /* ConfigABTestsOneElementTypeError.json */, + ); + path = ConfigJsonStub; + sourceTree = ""; + }; + 4766A8A82C932473002D15A4 /* Config */ = { + isa = PBXGroup; + children = ( + 4766A8972C931AEE002D15A4 /* ConfigJsonStub */, + 473A98252C918C3A005A3B94 /* ConfigParsingTests.swift */, + ); + path = Config; + sourceTree = ""; + }; + 4766A8A92C932484002D15A4 /* ABTests */ = { + isa = PBXGroup; + children = ( + 4766A8AA2C9324D8002D15A4 /* ABTestsJsonStubs */, + 4766A8AD2C9325B0002D15A4 /* ABTestsConfigParsingTests.swift */, + ); + path = ABTests; + sourceTree = ""; + }; + 4766A8AA2C9324D8002D15A4 /* ABTestsJsonStubs */ = { + isa = PBXGroup; + children = ( + 4766A8AF2C932624002D15A4 /* ABTestsConfig.json */, + 4766A8B12C932A3C002D15A4 /* ABTestsIdConfigError.json */, + 4766A8B32C932C79002D15A4 /* ABTestsIdConfigTypeError.json */, + 4766A8B52C932D92002D15A4 /* ABTestsSdkVersionConfigError.json */, + 4766A8B72C932EFC002D15A4 /* ABTestsSdkVersionConfigTypeError.json */, + ); + path = ABTestsJsonStubs; + sourceTree = ""; + }; + 47B90E2D2C625F8A00BD93E7 /* TestsMigrations */ = { isa = PBXGroup; children = ( 47B90E2E2C625F9A00BD93E7 /* TestBaseMigrations.swift */, 47B90E302C626B9300BD93E7 /* TestProtocolMigrations.swift */, ); - path = TestMigrations; + path = TestsMigrations; sourceTree = ""; }; 47BD5BF82C578AD700F965C0 /* Migrations */ = { isa = PBXGroup; children = ( + 472179A52C80751F00C15E7F /* ImplementationOfMigrations */, 47BD5BFC2C578FAD00F965C0 /* MigrationAbstractions */, 47BD5BF92C578ADE00F965C0 /* MigrationManager */, ); @@ -2639,7 +2892,6 @@ F37613DF2A6A8CFF009F2EE4 /* Extensions */ = { isa = PBXGroup; children = ( - F331DD102A83CA7400222120 /* KeyedDecodingContainer+Extensions.swift */, F37613E02A6A8CFF009F2EE4 /* UIColor+Extensions.swift */, F382F2102BAC6AD100BC97FF /* UNAuthorizationStatus+Extensions.swift */, BB4D7CC62BDEC51D008E3AB8 /* Notification+Extensions.swift */, @@ -2810,6 +3062,8 @@ F3A8B9A22A3A6E6900E9C055 /* SdkVersionModel.swift */, F3A8B9A42A3A6F2800E9C055 /* MonitoringModel.swift */, F3A8B9A82A3A713E00E9C055 /* SettingsModel.swift */, + 4766A8932C92FEF6002D15A4 /* SettingsOperationsModel.swift */, + 4766A8952C92FF3A002D15A4 /* TimeToLiveModel.swift */, F3A8B9AA2A3A719C00E9C055 /* ABTestModel.swift */, ); path = Config; @@ -3082,60 +3336,95 @@ buildActionMask = 2147483647; files = ( A1B940B7298104ED00B0F994 /* UnknownTargetingsModel.json in Resources */, + 473A985D2C91D1CE005A3B94 /* SettingsOperationsViewCategoryAndSetCartTypeError.json in Resources */, F3F9E3572BB19A9500340045 /* VisitTargetingModelValid.json in Resources */, + 473A98692C91DFEA005A3B94 /* MonitoringLogsOneElementTypeError.json in Resources */, F39B67C82A3FBEA7005C0CCA /* ConfigWithABTypeNotInapps.json in Resources */, F3FAD8782AB8685D00D98C03 /* closeButtonMarginBelowZero.json in Resources */, + 4766A89F2C931BEC002D15A4 /* ConfigMonitoringTypeError.json in Resources */, F39117132AB4BD8500852298 /* emptyLayersSection.json in Resources */, F39B67BC2A3FB9A8005C0CCA /* ConfigWithABNoSalt.json in Resources */, 31ED2DF325C4456600301FAD /* TestConfig_Invalid_1.plist in Resources */, F39117192AB4C02500852298 /* unknownActionLayerType.json in Resources */, + 4766A8A32C931CF8002D15A4 /* ConfigABTestsTypeError.json in Resources */, F39117152AB4BEB900852298 /* unknownLayerType.json in Resources */, A153E04129BB0A8B003C34D4 /* InAppConfigurationWithOperations.json in Resources */, + 473A984D2C91B620005A3B94 /* SettingsOperationsTypeError.json in Resources */, + 4766A8B62C932D92002D15A4 /* ABTestsSdkVersionConfigError.json in Resources */, + 473A985B2C91D1B3005A3B94 /* SettingsOperationsViewCategoryAndSetCartError.json in Resources */, F31801FF2A386BE60021774C /* InappConfigResponseMonitoringInvalid.json in Resources */, F31470942B96632100E01E5C /* 16-17-TargetingRequests.json in Resources */, 31ED2DF225C4456600301FAD /* TestConfig_Invalid_2.plist in Resources */, F39117172AB4BF2700852298 /* knownImageUnknownPictureLayerType.json in Resources */, + 473A985F2C91D20B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameError.json in Resources */, 31ED2DF425C4456600301FAD /* TestConfig_Invalid_3.plist in Resources */, + 473A984F2C91B641005A3B94 /* SettingsOperationsViewProductError.json in Resources */, + 473A986D2C91E032005A3B94 /* MonitoringLogsError.json in Resources */, + 473A983C2C91ABFB005A3B94 /* MonitoringConfig.json in Resources */, F3FAD8722AB8673100D98C03 /* missingMarginFieldInSection.json in Resources */, 84CC79AB25CAEBBB00C062BD /* TestEventConfig.plist in Resources */, + 473A984B2C91B606005A3B94 /* SettingsOperationsError.json in Resources */, F31801FB2A386A5B0021774C /* InappConfigResponseSettingsInvalid.json in Resources */, F39B67BE2A3FB9EF005C0CCA /* ConfigWithABUnexpectedValue.json in Resources */, + 473A98672C91DFD1005A3B94 /* MonitoringLogsTwoElementsError.json in Resources */, A17958902978BE7000609E91 /* GeoTargetingModelValid.json in Resources */, F31470982B9668F100E01E5C /* 31-TargetingRequests.json in Resources */, F314708C2B96464900E01E5C /* 7-TargetingRequests.json in Resources */, + 4766A8B02C932624002D15A4 /* ABTestsConfig.json in Resources */, + 473A983A2C91ABF5005A3B94 /* SettingsConfig.json in Resources */, + 473A986F2C91E047005A3B94 /* MonitoringLogsTypeError.json in Resources */, F3FAD86C2AB8642C00D98C03 /* twoCloseButtonsInApp.json in Resources */, F31470922B96624F00E01E5C /* 14-TargetingRequests.json in Resources */, + 473A98632C91D256005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json in Resources */, F3FAD8742AB8678900D98C03 /* negativeCloseButtonSizeValues.json in Resources */, F3A8B9452A38870100E9C055 /* MixerUUIDS.json in Resources */, F391171B2AB4C07900852298 /* redirectUrlValueNumberInsteadOfString.json in Resources */, A179588D2978BE7000609E91 /* SegmentTargetingModelValid.json in Resources */, 9BE941F52916822900258077 /* InAppConfigurationInvalid.json in Resources */, F3FAD8702AB866B600D98C03 /* unknownSizeKind.json in Resources */, + 473A98652C91DFB5005A3B94 /* MonitoringLogsOneElementError.json in Resources */, F3FAD86E2AB8656700D98C03 /* closeButtonWithOpenButton.json in Resources */, F39B67C22A3FBB19005C0CCA /* ConfigWithABNoUpper.json in Resources */, F39117292AB4C2EF00852298 /* missingElementsSection.json in Resources */, + 4766A8A72C931E40002D15A4 /* ConfigInAppsTypeError.json in Resources */, F39B67C02A3FBA77005C0CCA /* ConfigWithABCrossRange.json in Resources */, + 473A98712C91E629005A3B94 /* MonitoringLogsElementsMixedError.json in Resources */, F3FAD8762AB867E700D98C03 /* closeButtonMarginAboveOne.json in Resources */, F31801FE2A386BE60021774C /* InappConfigResponseAbtestsInvalid.json in Resources */, + 4766A8BE2C933416002D15A4 /* ConfigABTestsOneElementTypeError.json in Resources */, A1A916E329C914C000D59D9E /* InAppConfigurationWithCategoryIDIn.json in Resources */, A17958922978C88B00609E91 /* AllTargetingsModelValid.json in Resources */, + 4766A8A12C931CDA002D15A4 /* ConfigABTestsError.json in Resources */, A179588E2978BE7000609E91 /* AndTargetingModelValid.json in Resources */, F39B67B32A3C8B1D005C0CCA /* ConfigWithAB_2.json in Resources */, A179588C2978BE7000609E91 /* OrTargetingModelValid.json in Resources */, + 473A98432C91AD8A005A3B94 /* SettingsTtlInappsTypeError.json in Resources */, F31470892B96387C00E01E5C /* 3-4-5-TargetingRequests.json in Resources */, A179588F2978BE7000609E91 /* TrueTargetingModelValid.json in Resources */, + 473A986B2C91E010005A3B94 /* MonitoringLogsTwoElementsTypeError.json in Resources */, + 473A98452C91B309005A3B94 /* SettingsTtlError.json in Resources */, F31470902B96514E00E01E5C /* 9-TargetingRequests.json in Resources */, F391172B2AB4C4AD00852298 /* invalidCloseButtonColor.json in Resources */, 31ED2DFA25C4459500301FAD /* TestConfig_Invalid_4.plist in Resources */, + 473A98612C91D22B005A3B94 /* SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json in Resources */, F39B67C62A3FBC47005C0CCA /* ConfigWithABNormal.json in Resources */, + 4766A8B82C932EFC002D15A4 /* ABTestsSdkVersionConfigTypeError.json in Resources */, + 4766A89D2C931BD6002D15A4 /* ConfigMonitoringError.json in Resources */, F31801F82A38649D0021774C /* InappConfigResponseValid.json in Resources */, F39B67B22A3C8B1D005C0CCA /* ConfigWithAB_1.json in Resources */, + 4766A8BC2C9332ED002D15A4 /* ConfigABTestsOneElementError.json in Resources */, 84FCD3BD25CA10F600D1E574 /* SuccessResponse.json in Resources */, + 473A98472C91B323005A3B94 /* SettingsTtlTypeError.json in Resources */, F39117212AB4C20200852298 /* emptyVariantsArray.json in Resources */, F39117252AB4C27B00852298 /* missingValueInSourceLayer.json in Resources */, F39B67C42A3FBB64005C0CCA /* ConfigWithABLowerBiggerThanUpper.json in Resources */, F391171D2AB4C0BE00852298 /* missingIntentPayloadInActionLayer.json in Resources */, + 4766A8992C931B30002D15A4 /* ConfigSettingsError.json in Resources */, F39117112AB4BD4500852298 /* missingBackgroundSection.json in Resources */, + 473A98592C91BB1B005A3B94 /* SettingsAllOperationsWithTypeErrors.json in Resources */, + 473A98412C91AD85005A3B94 /* SettingsTtlInappsError.json in Resources */, + 473A98552C91B6B6005A3B94 /* SettingsOperationsViewProductTypeError.json in Resources */, + 4766A8A52C931E27002D15A4 /* ConfigInAppsError.json in Resources */, F31470962B96681F00E01E5C /* 27-TargetingRequests.json in Resources */, 31EB907425C402F900368FFB /* TestConfig2.plist in Resources */, 31EB907325C402F900368FFB /* TestConfig3.plist in Resources */, @@ -3144,10 +3433,17 @@ F391171F2AB4C1C100852298 /* missingSourceSection.json in Resources */, F39117272AB4C2AA00852298 /* missingImageLinkInSourceLayerValue.json in Resources */, F39B67BA2A3FB943005C0CCA /* ConfigWithABBrokenRange.json in Resources */, + 4766A89B2C931B51002D15A4 /* ConfigSettingsTypeError.json in Resources */, + 4766A8B42C932C79002D15A4 /* ABTestsIdConfigTypeError.json in Resources */, 31A20D4925B6CBE000AAA0A3 /* TestConfig1.plist in Resources */, + 473A98532C91B68D005A3B94 /* SettingsOperationsViewProductSystemNameTypeError.json in Resources */, + 473A98382C91ABD9005A3B94 /* ConfigWithSettingsABTestsMonitoringInapps.json in Resources */, F3FAD86A2AB863CD00D98C03 /* missingCloseButtonColorLineWidthSize.json in Resources */, F314708E2B964BFF00E01E5C /* 8-TargetingRequests.json in Resources */, + 473A98512C91B66B005A3B94 /* SettingsOperationsViewProductSystemNameError.json in Resources */, + 4766A8B22C932A3C002D15A4 /* ABTestsIdConfigError.json in Resources */, 9BC24E7A28F6C08700C2619C /* InAppConfiguration.json in Resources */, + 473A98572C91BB02005A3B94 /* SettingsAllOperationsWithErrors.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3221,6 +3517,7 @@ F331DD032A83A56500222120 /* ModalPresentationStrategy.swift in Sources */, A17958792978AEC600609E91 /* GeoTargetingChecker.swift in Sources */, 33BEE80D2681EB7700993720 /* NotificationDecoder.swift in Sources */, + 472179A72C80755A00C15E7F /* ShownInAppsIdsMigration.swift in Sources */, 840042A12614CE0000CA17C5 /* ClickNotificationManager.swift in Sources */, 9B24FABD28C757A700F10B5D /* InAppResponse.swift in Sources */, 334F3AED264C199900A6AC00 /* SubscriptionRequest.swift in Sources */, @@ -3252,6 +3549,7 @@ 334F3A67264AA18500A6AC00 /* MindboxAppDelegate.swift in Sources */, B3A6254C2689F83100B6A3B7 /* PersonalOffersResponse.swift in Sources */, 84F565212628304A00269FD6 /* TrackVisit.swift in Sources */, + 4766A8942C92FEF6002D15A4 /* SettingsOperationsModel.swift in Sources */, 337A473C265510AA000DC613 /* IDS.swift in Sources */, 317F1FD525B879B200B54346 /* MBUtilitiesFetcher.swift in Sources */, F370940B2B8F9CDE00655AC7 /* InAppConfigurationDataFacade.swift in Sources */, @@ -3303,6 +3601,7 @@ 6FDD1459266F7CB700A50C35 /* ContentResponse.swift in Sources */, F37613E12A6A8CFF009F2EE4 /* UIColor+Extensions.swift in Sources */, F39116F82AA9B04E00852298 /* VariantsFilter.swift in Sources */, + 4766A8962C92FF3A002D15A4 /* TimeToLiveModel.swift in Sources */, F3A8B9582A389D9D00E9C055 /* GeoService.swift in Sources */, 334F3AE2264C199900A6AC00 /* CouponRequest.swift in Sources */, F3A8B9942A3A409C00E9C055 /* Validator.swift in Sources */, @@ -3313,7 +3612,6 @@ F3482F1D2A65DC11002A41EC /* CompositeInappMessageDelegate.swift in Sources */, 33072F3C2664C713001F1AB2 /* CustomerSegmentationsResponse.swift in Sources */, 33072F3A2664C5CB001F1AB2 /* ManufacturerResponse.swift in Sources */, - F331DD112A83CA7500222120 /* KeyedDecodingContainer+Extensions.swift in Sources */, F331DD312A84CCA800222120 /* CloseButtonElement.swift in Sources */, A1D017E92976CC1C00CD9F99 /* TargetingChecker.swift in Sources */, F397EEB52A44573600D48CEC /* Status.swift in Sources */, @@ -3529,6 +3827,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4766A8AE2C9325B0002D15A4 /* ABTestsConfigParsingTests.swift in Sources */, F3FEEA9F2C25AF39000E9D0F /* StubContainer.swift in Sources */, 840C38B325D133B000D50183 /* GuaranteedDeliveryTestCase.swift in Sources */, F32E537B2C3FDA30002C7CA0 /* DIMainModuleReplaceableTests.swift in Sources */, @@ -3540,6 +3839,7 @@ F3A8B95C2A389EAD00E9C055 /* GeoServiceTests.swift in Sources */, A17958992978E04600609E91 /* InAppStub.swift in Sources */, F39B67A72A3C6C6A005C0CCA /* SegmentationServiceTests.swift in Sources */, + 476689C72C85B6AE0066BB12 /* ShownInAppsIdsMigrationTests.swift in Sources */, F3D925AB2A120C0F00135C87 /* InAppImageDownloaderMock.swift in Sources */, F367301D2B7B8B6A00DD0039 /* NotificationFormatTests.swift in Sources */, A154E32E299E0D8900F8F074 /* SDKLogManagerTests.swift in Sources */, @@ -3547,8 +3847,11 @@ D2F7E2482BADB9EF00B24BB8 /* UserVisitManagerTests.swift in Sources */, BBAAC17C2BB2FC9100E1E25E /* MockEvent.swift in Sources */, 84B09FB42611C74400B0A06E /* MockDatabaseRepository.swift in Sources */, + 473A98262C918C3A005A3B94 /* ConfigParsingTests.swift in Sources */, F39B67B82A3FAA75005C0CCA /* ABTests.swift in Sources */, A1F3EE4A298BEE4B005FA828 /* OSLogWritterMock.swift in Sources */, + 473A98362C91A7AB005A3B94 /* GetConfigFunc.swift in Sources */, + 473A98332C91A4B3005A3B94 /* MonitoringConfigParsingTests.swift in Sources */, F3FEEAA62C25CB2E000E9D0F /* XCTestCase+Extensions.swift in Sources */, F31470822B9634E000E01E5C /* InAppTargetingRequestsTests.swift in Sources */, 84ECB42E25D27EF100DA8AC9 /* MockUNAuthorizationStatusProvider.swift in Sources */, @@ -3569,6 +3872,7 @@ A154E334299E110E00F8F074 /* EventRepositoryMock.swift in Sources */, 31ED2DEC25C444C400301FAD /* MBConfigurationTestCase.swift in Sources */, F3D925AD2A1236F400135C87 /* URLSessionImageDownloaderTests.swift in Sources */, + 473A982D2C91A38C005A3B94 /* SettingsConfigParsingTests.swift in Sources */, F3A8B9A02A3A52F400E9C055 /* ABTestValidatorTests.swift in Sources */, 9B9C953B292111A700BB29DA /* MockDateProvider.swift in Sources */, A17958972978D2B300609E91 /* InAppTargetingCheckerTests.swift in Sources */, diff --git a/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/CEF30695-C2F1-4619-AFBC-C5C002146E9E.plist b/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/CEF30695-C2F1-4619-AFBC-C5C002146E9E.plist new file mode 100644 index 00000000..4e400b8d --- /dev/null +++ b/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/CEF30695-C2F1-4619-AFBC-C5C002146E9E.plist @@ -0,0 +1,32 @@ + + + + + classNames + + MBLoggerCoreDataManagerTests + + test_measure_create() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.001905 + baselineIntegrationDisplayName + Local Baseline + + + test_measure_create_10_000() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 23.632117 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/Info.plist b/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/Info.plist index f50b2d98..e20570a2 100644 --- a/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/Info.plist +++ b/Mindbox.xcodeproj/xcshareddata/xcbaselines/313B233825ADEA0F00A1CB72.xcbaseline/Info.plist @@ -66,6 +66,37 @@ com.apple.platform.iphonesimulator + CEF30695-C2F1-4619-AFBC-C5C002146E9E + + localComputer + + busSpeedInMHz + 0 + cpuCount + 1 + cpuKind + Apple M1 Pro + cpuSpeedInMHz + 0 + logicalCPUCoresPerPackage + 10 + modelCode + MacBookPro18,3 + physicalCPUCoresPerPackage + 10 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + arm64 + targetDevice + + modelCode + iPhone16,1 + platformIdentifier + com.apple.platform.iphonesimulator + + diff --git a/Mindbox/DI/Injections/InjectReplaceable.swift b/Mindbox/DI/Injections/InjectReplaceable.swift index 9f570e92..f759618b 100644 --- a/Mindbox/DI/Injections/InjectReplaceable.swift +++ b/Mindbox/DI/Injections/InjectReplaceable.swift @@ -30,9 +30,7 @@ extension MBContainer { register(PersistenceStorage.self) { let utilitiesFetcher = DI.injectOrFail(UtilitiesFetcher.self) let defaults = UserDefaults(suiteName: utilitiesFetcher.applicationGroupIdentifier)! - let storage = MBPersistenceStorage(defaults: defaults) - storage.migrateShownInAppsIds() - return storage + return MBPersistenceStorage(defaults: defaults) } register(MBDatabaseRepository.self) { diff --git a/Mindbox/Extensions/KeyedDecodingContainer+Extensions.swift b/Mindbox/Extensions/KeyedDecodingContainer+Extensions.swift deleted file mode 100644 index 6aa38592..00000000 --- a/Mindbox/Extensions/KeyedDecodingContainer+Extensions.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// KeyedDecodingContainer+Extensions.swift -// Mindbox -// -// Created by vailence on 09.08.2023. -// - -import Foundation - -extension KeyedDecodingContainer { - public func decodeIfPresentSafely(_ type: T.Type, forKey key: KeyedDecodingContainer.Key) throws -> T? { - do { - return try decode(T.self, forKey: key) - } catch DecodingError.typeMismatch, DecodingError.keyNotFound { - return nil - } - } -} diff --git a/Mindbox/InAppMessages/Configuration/InAppConfigurationManager.swift b/Mindbox/InAppMessages/Configuration/InAppConfigurationManager.swift index b47f79a3..d014057b 100644 --- a/Mindbox/InAppMessages/Configuration/InAppConfigurationManager.swift +++ b/Mindbox/InAppMessages/Configuration/InAppConfigurationManager.swift @@ -28,7 +28,7 @@ class InAppConfigurationManager: InAppConfigurationManagerProtocol { private let jsonDecoder = JSONDecoder() private let queue = DispatchQueue(label: "com.Mindbox.configurationManager") private var inapp: InAppFormData? - private var rawConfigurationResponse: ConfigResponse! + private var rawConfigurationResponse: ConfigResponse? private let inAppConfigRepository: InAppConfigurationRepository private let inAppConfigurationMapper: InAppConfigurationMapperProtocol private let inAppConfigAPI: InAppConfigurationAPI @@ -90,7 +90,7 @@ class InAppConfigurationManager: InAppConfigurationManagerProtocol { setConfigPrepared(config) setupSettingsFromConfig(config.settings) if let monitoring = config.monitoring, let logsManager = DI.inject(SDKLogsManagerProtocol.self) { - logsManager.sendLogs(logs: monitoring.logs) + logsManager.sendLogs(logs: monitoring.logs.elements) } } catch { applyConfigFromCache() diff --git a/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InAppConfigurationDataFacade.swift b/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InAppConfigurationDataFacade.swift index fe176648..495ee5c4 100644 --- a/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InAppConfigurationDataFacade.swift +++ b/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InAppConfigurationDataFacade.swift @@ -36,6 +36,7 @@ class InAppConfigurationDataFacade: InAppConfigurationDataFacadeProtocol { } private let dispatchGroup = DispatchGroup() + private var fetchedProductIdsCache: [String: String] = [:] func fetchDependencies(model: InappOperationJSONModel?, _ completion: @escaping () -> Void) { fetchSegmentationIfNeeded() @@ -92,15 +93,26 @@ private extension InAppConfigurationDataFacade { } } } - + private func fetchProductSegmentationIfNeeded(products: ProductCategory?) { - if !SessionTemporaryStorage.shared.checkProductSegmentsRequestCompleted, - let products = products { - dispatchGroup.enter() - segmentationService.checkProductSegmentationRequest(products: products) { response in - self.targetingChecker.checkedProductSegmentations = response - self.dispatchGroup.leave() - } + guard let products = products else { + return + } + + let productIds = products.ids + let allMatch = productIds.allSatisfy { key, value in + fetchedProductIdsCache[key] == value + } + + if allMatch { + return + } + + dispatchGroup.enter() + segmentationService.checkProductSegmentationRequest(products: products) { response in + self.fetchedProductIdsCache = productIds + self.targetingChecker.checkedProductSegmentations = response + self.dispatchGroup.leave() } } } diff --git a/Mindbox/InAppMessages/Models/Config/ConfigResponse.swift b/Mindbox/InAppMessages/Models/Config/ConfigResponse.swift index f7406dcc..83011bf0 100644 --- a/Mindbox/InAppMessages/Models/Config/ConfigResponse.swift +++ b/Mindbox/InAppMessages/Models/Config/ConfigResponse.swift @@ -21,18 +21,18 @@ struct ConfigResponse: Decodable { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - inapps = try? container.decodeIfPresent(FailableDecodableArray.self, forKey: .inapps) - monitoring = ConfigResponse.decodeIfPresent(container, forKey: .monitoring, errorDesc: "Cannot decode Monitoring") - settings = ConfigResponse.decodeIfPresent(container, forKey: .settings, errorDesc: "Cannot decode Settings") + self.inapps = try? container.decodeIfPresent(FailableDecodableArray.self, forKey: .inapps) + self.monitoring = ConfigResponse.decodeIfPresent(container, forKey: .monitoring, errorDesc: "Cannot decode Monitoring") + self.settings = ConfigResponse.decodeIfPresent(container, forKey: .settings, errorDesc: "Cannot decode Settings") let abTestValidator = DI.injectOrFail(ABTestValidator.self) if let decodedAbtests: [ABTest] = ConfigResponse.decodeIfPresent(container, forKey: .abtests, errorDesc: "Cannot decode ABTests"), decodedAbtests.allSatisfy({ abTestValidator.isValid(item: $0) }) { - abtests = decodedAbtests + self.abtests = decodedAbtests } else { - abtests = nil + self.abtests = nil } } @@ -46,7 +46,9 @@ struct ConfigResponse: Decodable { return nil } } - +} + +extension ConfigResponse { init(inapps: FailableDecodableArray? = nil, monitoring: Monitoring? = nil, settings: Settings? = nil, abtests: [ABTest]? = nil) { self.inapps = inapps self.monitoring = monitoring diff --git a/Mindbox/InAppMessages/Models/Config/InappModel/InappFrequency/Types/PeriodicFrequency.swift b/Mindbox/InAppMessages/Models/Config/InappModel/InappFrequency/Types/PeriodicFrequency.swift index 5d7d32fb..3af84a17 100644 --- a/Mindbox/InAppMessages/Models/Config/InappModel/InappFrequency/Types/PeriodicFrequency.swift +++ b/Mindbox/InAppMessages/Models/Config/InappModel/InappFrequency/Types/PeriodicFrequency.swift @@ -11,4 +11,37 @@ import Foundation struct PeriodicFrequency: Decodable, Equatable { let unit: Unit let value: Int + + enum Unit: String, Decodable { + case seconds = "seconds" + case minutes = "minutes" + case hours = "hours" + case days = "days" + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let decodedString = try container.decode(String.self).lowercased() + + guard let value = Unit(rawValue: decodedString) else { + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Неизвестная единица времени") + } + + self = value + } + } +} + +extension PeriodicFrequency.Unit { + var calendarComponent: Calendar.Component { + switch self { + case .seconds: + return .second + case .minutes: + return .minute + case .hours: + return .hour + case .days: + return .day + } + } } diff --git a/Mindbox/InAppMessages/Models/Config/MonitoringModel.swift b/Mindbox/InAppMessages/Models/Config/MonitoringModel.swift index e8ba3a4e..6b619a13 100644 --- a/Mindbox/InAppMessages/Models/Config/MonitoringModel.swift +++ b/Mindbox/InAppMessages/Models/Config/MonitoringModel.swift @@ -9,8 +9,8 @@ import Foundation struct Monitoring: Decodable, Equatable { - let logs: [Logs] - + let logs: FailableDecodableArray + struct Logs: Decodable, Equatable { let requestId: String let deviceUUID: String diff --git a/Mindbox/InAppMessages/Models/Config/SettingsModel.swift b/Mindbox/InAppMessages/Models/Config/SettingsModel.swift index eca2ee65..fde610ff 100644 --- a/Mindbox/InAppMessages/Models/Config/SettingsModel.swift +++ b/Mindbox/InAppMessages/Models/Config/SettingsModel.swift @@ -12,51 +12,15 @@ struct Settings: Decodable, Equatable { let operations: SettingsOperations? let ttl: TimeToLive? - struct SettingsOperations: Decodable, Equatable { - - let viewProduct: Operation? - let viewCategory: Operation? - let setCart: Operation? - - struct Operation: Decodable, Equatable { - let systemName: String - } - } - - struct TimeToLive: Decodable, Equatable { - let inapps: String? + enum CodingKeys: CodingKey { + case operations, ttl } } -enum Unit: String, Decodable { - case seconds = "seconds" - case minutes = "minutes" - case hours = "hours" - case days = "days" - +extension Settings { init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let decodedString = try container.decode(String.self).lowercased() - - guard let value = Unit(rawValue: decodedString) else { - throw DecodingError.dataCorruptedError(in: container, debugDescription: "Неизвестная единица времени") - } - - self = value - } -} - -extension Unit { - var calendarComponent: Calendar.Component { - switch self { - case .seconds: - return .second - case .minutes: - return .minute - case .hours: - return .hour - case .days: - return .day - } + let container: KeyedDecodingContainer = try decoder.container(keyedBy: CodingKeys.self) + self.operations = try? container.decodeIfPresent(SettingsOperations.self, forKey: .operations) + self.ttl = try? container.decodeIfPresent(TimeToLive.self, forKey: .ttl) } } diff --git a/Mindbox/InAppMessages/Models/Config/SettingsOperationsModel.swift b/Mindbox/InAppMessages/Models/Config/SettingsOperationsModel.swift new file mode 100644 index 00000000..1ad16fd9 --- /dev/null +++ b/Mindbox/InAppMessages/Models/Config/SettingsOperationsModel.swift @@ -0,0 +1,42 @@ +// +// SettingsOperationsModel.swift +// Mindbox +// +// Created by Sergei Semko on 9/12/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import Foundation + +extension Settings { + struct SettingsOperations: Decodable, Equatable { + + let viewProduct: Operation? + let viewCategory: Operation? + let setCart: Operation? + + enum CodingKeys: CodingKey { + case viewProduct + case viewCategory + case setCart + } + + struct Operation: Decodable, Equatable { + let systemName: String + } + } +} + +extension Settings.SettingsOperations { + init(from decoder: any Decoder) throws { + let container: KeyedDecodingContainer = try decoder.container(keyedBy: CodingKeys.self) + self.viewProduct = try? container.decodeIfPresent(Operation.self, forKey: .viewProduct) + self.viewCategory = try? container.decodeIfPresent(Operation.self, forKey: .viewCategory) + self.setCart = try? container.decodeIfPresent(Operation.self, forKey: .setCart) + + if viewProduct == nil && viewCategory == nil && setCart == nil { + // Will never be caught because of `try?` in `Settings.init` + throw DecodingError.dataCorruptedError(forKey: .viewProduct, in: container, debugDescription: "The `operation` type could not be decoded because all operations are nil") + } + } +} diff --git a/Mindbox/InAppMessages/Models/Config/TimeToLiveModel.swift b/Mindbox/InAppMessages/Models/Config/TimeToLiveModel.swift new file mode 100644 index 00000000..29b9cd08 --- /dev/null +++ b/Mindbox/InAppMessages/Models/Config/TimeToLiveModel.swift @@ -0,0 +1,30 @@ +// +// TimeToLiveModel.swift +// Mindbox +// +// Created by Sergei Semko on 9/12/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import Foundation + +extension Settings { + struct TimeToLive: Decodable, Equatable { + let inapps: String? + + enum CodingKeys: CodingKey { + case inapps + } + } +} + +extension Settings.TimeToLive { + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let inapps = try? container.decodeIfPresent(String.self, forKey: .inapps) { + self.inapps = inapps + } else { + throw DecodingError.dataCorruptedError(forKey: .inapps, in: container, debugDescription: "Missing required key 'inapps'") + } + } +} diff --git a/Mindbox/Info.plist b/Mindbox/Info.plist index 5660e5dd..343f9b93 100644 --- a/Mindbox/Info.plist +++ b/Mindbox/Info.plist @@ -17,6 +17,6 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 5844 + 6100 diff --git a/Mindbox/MindboxLogger/SDKLogsManager.swift b/Mindbox/MindboxLogger/SDKLogsManager.swift index e4c35e10..13d25e0f 100644 --- a/Mindbox/MindboxLogger/SDKLogsManager.swift +++ b/Mindbox/MindboxLogger/SDKLogsManager.swift @@ -28,6 +28,7 @@ class SDKLogsManager: SDKLogsManagerProtocol { } func sendLogs(logs: [Monitoring.Logs]) { + guard !logs.isEmpty else { return } var handledLogsRequestIds = persistenceStorage.handledlogRequestIds ?? [] for log in logs { if !handledLogsRequestIds.contains(log.requestId) && persistenceStorage.deviceUUID == log.deviceUUID.uppercased() { diff --git a/Mindbox/PersistenceStorage/MBPersistenceStorage.swift b/Mindbox/PersistenceStorage/MBPersistenceStorage.swift index dcb11040..c12778b7 100644 --- a/Mindbox/PersistenceStorage/MBPersistenceStorage.swift +++ b/Mindbox/PersistenceStorage/MBPersistenceStorage.swift @@ -258,21 +258,6 @@ class MBPersistenceStorage: PersistenceStorage { MBPersistenceStorage.defaults.removeObject(forKey: "backgroundExecution") MBPersistenceStorage.defaults.synchronize() } - - func migrateShownInAppsIds() { - if let oldIds = shownInAppsIds, !oldIds.isEmpty { - Logger.common(message: "Starting migration of shownInAppsIds. Total IDs to migrate: \(oldIds.count)", level: .debug, category: .inAppMessages) - let migrationTimestamp = Date(timeIntervalSince1970: 0) - var newFormat: [String: Date] = [:] - - for id in oldIds { - newFormat[id] = migrationTimestamp - } - shownInappsDictionary = newFormat - shownInAppsIds = nil - Logger.common(message: "Migration completed successfully. All IDs are migrated and old IDs list is cleared.", level: .debug, category: .inAppMessages) - } - } } // MARK: - Functions for unit testing diff --git a/Mindbox/PersistenceStorage/PersistenceStorage.swift b/Mindbox/PersistenceStorage/PersistenceStorage.swift index c54bfd85..a8333007 100644 --- a/Mindbox/PersistenceStorage/PersistenceStorage.swift +++ b/Mindbox/PersistenceStorage/PersistenceStorage.swift @@ -43,8 +43,6 @@ protocol PersistenceStorage: AnyObject { func resetBackgroundExecutions() func storeToFileBackgroundExecution() - - func migrateShownInAppsIds() var onDidChange: (() -> Void)? { get set } diff --git a/Mindbox/Utilities/Migrations/ImplementationOfMigrations/ShownInAppsIdsMigration.swift b/Mindbox/Utilities/Migrations/ImplementationOfMigrations/ShownInAppsIdsMigration.swift new file mode 100644 index 00000000..78435e6d --- /dev/null +++ b/Mindbox/Utilities/Migrations/ImplementationOfMigrations/ShownInAppsIdsMigration.swift @@ -0,0 +1,42 @@ +// +// ShownInAppsIdsMigration.swift +// Mindbox +// +// Created by Sergei Semko on 8/29/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import Foundation + +final class MigrationShownInAppsIds: MigrationProtocol { + + private var persistenceStorage: PersistenceStorage = DI.injectOrFail(PersistenceStorage.self) + + var description: String { + "Migration shownInAppsIds to shownInappsDictionary. Starting with SDK 2.10.0." + } + + var isNeeded: Bool { + persistenceStorage.shownInAppsIds?.isEmpty == false + } + + var version: Int { + 0 + } + + func run() throws { + guard let oldShownInAppsIds = persistenceStorage.shownInAppsIds else { + return + } + + let migrationTimestamp = Date(timeIntervalSince1970: 0) + var newFormatShownInapps = [String: Date]() + + for id in oldShownInAppsIds { + newFormatShownInapps[id] = migrationTimestamp + } + + persistenceStorage.shownInappsDictionary = newFormatShownInapps + persistenceStorage.shownInAppsIds = nil + } +} diff --git a/Mindbox/Utilities/Migrations/MigrationManager/MigrationManager.swift b/Mindbox/Utilities/Migrations/MigrationManager/MigrationManager.swift index ad79ef00..2736fb82 100644 --- a/Mindbox/Utilities/Migrations/MigrationManager/MigrationManager.swift +++ b/Mindbox/Utilities/Migrations/MigrationManager/MigrationManager.swift @@ -51,7 +51,7 @@ final class MigrationManager { self.localSdkVersionCode = Constants.Migration.sdkVersionCode self.migrations = [ - + MigrationShownInAppsIds(), ] } } @@ -82,7 +82,7 @@ extension MigrationManager: MigrationManagerProtocol { migrationsStarted = true do { try migration.run() - let message = "[Migration] Run migration: \(migration.description), version: \(migration.version)" + let message = "[Migration] Run migration: '\(migration.description)', version: \(migration.version)" Logger.common(message: message, level: .info, category: .migration) } catch { let errorMessage = "[Migration] Migration \(migration.version) failed. Description: \(migrations.description). Error: \(error.localizedDescription)" @@ -115,7 +115,9 @@ extension MigrationManager { /// including migration state and other critical data. It provides methods /// for performing resets and managing configurations. /// - migrations: Array of new migrations. - /// - sdkVersionCode: version for comparison with `persistenceStorage.versionCodeForMigration` after all migrations have been performed. + /// - sdkVersionCode: version for comparison with `persistenceStorage.versionCodeForMigration` + /// after all migrations have been performed. + /// Used instead of `Constants.Migration.sdkVersionCode` convenience init( persistenceStorage: PersistenceStorage, migrations: [MigrationProtocol], diff --git a/Mindbox/Utilities/SessionTemporaryStorage.swift b/Mindbox/Utilities/SessionTemporaryStorage.swift index bbfffd3d..b936bcac 100644 --- a/Mindbox/Utilities/SessionTemporaryStorage.swift +++ b/Mindbox/Utilities/SessionTemporaryStorage.swift @@ -17,7 +17,6 @@ final class SessionTemporaryStorage { var operationsFromSettings: Set = [] var geoRequestCompleted = false var checkSegmentsRequestCompleted = false - var checkProductSegmentsRequestCompleted = false var isPresentingInAppMessage = false var pushPermissionStatus: UNAuthorizationStatus = .denied var sessionShownInApps: Set = [] @@ -43,7 +42,6 @@ final class SessionTemporaryStorage { operationsFromSettings = [] geoRequestCompleted = false checkSegmentsRequestCompleted = false - checkProductSegmentsRequestCompleted = false isPresentingInAppMessage = false sessionShownInApps = [] } diff --git a/MindboxLogger.podspec b/MindboxLogger.podspec index 55f06310..2193ad87 100644 --- a/MindboxLogger.podspec +++ b/MindboxLogger.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = "MindboxLogger" - spec.version = "2.11.0" + spec.version = "2.11.1" spec.summary = "SDK for utilities to work with Mindbox" spec.description = "-" spec.homepage = "https://github.com/mindbox-cloud/ios-sdk" diff --git a/MindboxLogger/Shared/Extensions/NSManagedObjectContext+Extension.swift b/MindboxLogger/Shared/Extensions/NSManagedObjectContext+Extension.swift index 842e1712..51f6725e 100644 --- a/MindboxLogger/Shared/Extensions/NSManagedObjectContext+Extension.swift +++ b/MindboxLogger/Shared/Extensions/NSManagedObjectContext+Extension.swift @@ -10,6 +10,15 @@ import Foundation import CoreData public extension NSManagedObjectContext { + + func executePerformAndWait(_ block: () throws -> Void) rethrows { + if #available(iOS 15, *) { + try self.performAndWait(block) + } else { + try mindboxPerformAndWait(block) + } + } + func mindboxPerformAndWait(_ block: () throws -> T) rethrows -> T { return try _performAndWaitHelper( fn: performAndWait, execute: block, rescue: { throw $0 } diff --git a/MindboxLogger/Shared/LoggerRepository/MBLoggerCoreDataManager.swift b/MindboxLogger/Shared/LoggerRepository/MBLoggerCoreDataManager.swift index f6f18874..1a846783 100644 --- a/MindboxLogger/Shared/LoggerRepository/MBLoggerCoreDataManager.swift +++ b/MindboxLogger/Shared/LoggerRepository/MBLoggerCoreDataManager.swift @@ -32,29 +32,34 @@ public class MBLoggerCoreDataManager { MBPersistentContainer.applicationGroupIdentifier = MBLoggerUtilitiesFetcher().applicationGroupIdentifier #if SWIFT_PACKAGE - let bundleURL = Bundle.module.url(forResource: Constants.model, withExtension: "momd") - let mom = NSManagedObjectModel(contentsOf: bundleURL!) - let container = MBPersistentContainer(name: Constants.model, managedObjectModel: mom!) + guard let bundleURL = Bundle.module.url(forResource: Constants.model, withExtension: "momd"), + let mom = NSManagedObjectModel(contentsOf: bundleURL) else { + fatalError("Failed to initialize NSManagedObjectModel for \(Constants.model)") + } + let container = MBPersistentContainer(name: Constants.model, managedObjectModel: mom) #else let podBundle = Bundle(for: MBLoggerCoreDataManager.self) let container: MBPersistentContainer - if let url = podBundle.url(forResource: "MindboxLogger", withExtension: "bundle") { - let bundle = Bundle(url: url) - let modelURL = bundle?.url(forResource: Constants.model, withExtension: "momd") - let mom = NSManagedObjectModel(contentsOf: modelURL!) - container = MBPersistentContainer(name: Constants.model, managedObjectModel: mom!) + if let url = podBundle.url(forResource: "MindboxLogger", withExtension: "bundle"), + let bundle = Bundle(url: url), + let modelURL = bundle.url(forResource: Constants.model, withExtension: "momd"), + let mom = NSManagedObjectModel(contentsOf: modelURL) { + container = MBPersistentContainer(name: Constants.model, managedObjectModel: mom) } else { container = MBPersistentContainer(name: Constants.model) } #endif let storeURL = FileManager.storeURL(for: MBLoggerUtilitiesFetcher().applicationGroupIdentifier, databaseName: Constants.model) + let storeDescription = NSPersistentStoreDescription(url: storeURL) storeDescription.setOption(FileProtectionType.none as NSObject, forKey: NSPersistentStoreFileProtectionKey) storeDescription.setValue("DELETE" as NSObject, forPragmaNamed: "journal_mode") // Disabling WAL journal container.persistentStoreDescriptions = [storeDescription] - container.loadPersistentStores { - (storeDescription, error) in + container.loadPersistentStores { (storeDescription, error) in + if let error = error { + fatalError("Failed to load persistent stores: \(error)") + } } return container @@ -69,71 +74,80 @@ public class MBLoggerCoreDataManager { }() // MARK: - CRUD Operations - public func create(message: String, timestamp: Date) throws { - let isTimeToDelete = writeCount == 0 - writeCount += 1 - if isTimeToDelete && getDBFileSize() > Constants.dbSizeLimitKB { - try delete() - } - - try self.context.mindboxPerformAndWait { - let entity = CDLogMessage(context: self.context) - entity.message = message - entity.timestamp = timestamp - try self.saveEvent(withContext: self.context) + public func create(message: String, timestamp: Date, completion: (() -> Void)? = nil) { + queue.async { + do { + let isTimeToDelete = self.writeCount == 0 + self.writeCount += 1 + if isTimeToDelete && self.getDBFileSize() > Constants.dbSizeLimitKB { + try self.delete() + } + + try self.context.executePerformAndWait { + let entity = CDLogMessage(context: self.context) + entity.message = message + entity.timestamp = timestamp + try self.saveEvent(withContext: self.context) + + completion?() + } + } catch { + + } } } public func getFirstLog() throws -> LogMessage? { - try context.mindboxPerformAndWait { + var fetchedLogMessage: LogMessage? = nil + try context.executePerformAndWait { let fetchRequest = NSFetchRequest(entityName: Constants.model) fetchRequest.predicate = NSPredicate(value: true) fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: true)] fetchRequest.fetchLimit = 1 let results = try context.fetch(fetchRequest) - var logMessage: LogMessage? + if let first = results.first { - logMessage = LogMessage(timestamp: first.timestamp, message: first.message) + fetchedLogMessage = LogMessage(timestamp: first.timestamp, message: first.message) } - - return logMessage } + + return fetchedLogMessage } public func getLastLog() throws -> LogMessage? { - try context.mindboxPerformAndWait { + var fetchedLogMessage: LogMessage? = nil + try context.executePerformAndWait { let fetchRequest = NSFetchRequest(entityName: Constants.model) fetchRequest.predicate = NSPredicate(value: true) fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timestamp", ascending: false)] fetchRequest.fetchLimit = 1 let results = try context.fetch(fetchRequest) - var logMessage: LogMessage? + if let last = results.last { - logMessage = LogMessage(timestamp: last.timestamp, message: last.message) + fetchedLogMessage = LogMessage(timestamp: last.timestamp, message: last.message) } - - return logMessage } + + return fetchedLogMessage } public func fetchPeriod(_ from: Date, _ to: Date) throws -> [LogMessage] { - try context.mindboxPerformAndWait { + var fetchedLogs: [LogMessage] = [] + + try context.executePerformAndWait { let fetchRequest = NSFetchRequest(entityName: Constants.model) fetchRequest.predicate = NSPredicate(format: "timestamp >= %@ AND timestamp <= %@", from as NSDate, to as NSDate) let logs = try context.fetch(fetchRequest) - var fetchedLogs: [LogMessage] = [] - logs.forEach { - fetchedLogs.append(LogMessage(timestamp: $0.timestamp, message: $0.message)) - } - - return fetchedLogs + fetchedLogs = logs.map { LogMessage(timestamp: $0.timestamp, message: $0.message) } } + + return fetchedLogs } public func delete() throws { - try context.mindboxPerformAndWait { + try context.executePerformAndWait { let request = NSFetchRequest(entityName: Constants.model) let count = try context.count(for: request) let limit: Double = (Double(count) * 0.1).rounded() // 10% percent of all records should be removed @@ -147,21 +161,17 @@ public class MBLoggerCoreDataManager { try saveEvent(withContext: context) Logger.common(message: "10% logs has been deleted", level: .debug, category: .general) -// queue.async { -// Logger.common(message: "10% logs has been deleted", level: .debug, category: .general) -// } } } public func deleteAll() throws { - try context.mindboxPerformAndWait { + try context.executePerformAndWait { let request = NSFetchRequest(entityName: Constants.model) request.includesPropertyValues = false let results = try context.fetch(request) results.compactMap { $0 as? NSManagedObject }.forEach { context.delete($0) } - try saveEvent(withContext: context) } } } @@ -194,3 +204,5 @@ private extension MBLoggerCoreDataManager { return Int(size) } } + + diff --git a/MindboxNotifications.podspec b/MindboxNotifications.podspec index ebdbcf62..d45f83e8 100644 --- a/MindboxNotifications.podspec +++ b/MindboxNotifications.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = "MindboxNotifications" - spec.version = "2.11.0" + spec.version = "2.11.1" spec.summary = "SDK for integration notifications with Mindbox" spec.description = "This library allows you to integrate notifications and transfer them to Mindbox Marketing Cloud" spec.homepage = "https://github.com/mindbox-cloud/ios-sdk" @@ -14,6 +14,6 @@ Pod::Spec.new do |spec| 'MindboxNotifications' => ['MindboxNotifications/**/*.xcprivacy'] } spec.swift_version = "5" - spec.dependency 'MindboxLogger', '2.11.0' + spec.dependency 'MindboxLogger', '2.11.1' end diff --git a/MindboxTests/ConfigParsing/ABTests/ABTestsConfigParsingTests.swift b/MindboxTests/ConfigParsing/ABTests/ABTestsConfigParsingTests.swift new file mode 100644 index 00000000..e2a96214 --- /dev/null +++ b/MindboxTests/ConfigParsing/ABTests/ABTestsConfigParsingTests.swift @@ -0,0 +1,110 @@ +// +// ABTestsConfigParsingTests.swift +// MindboxTests +// +// Created by Sergei Semko on 9/12/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import XCTest +@testable import Mindbox + +fileprivate enum ABTestsConfig: String, Configurable { + typealias DecodeType = [ABTest] + + case configWithABTests = "ABTestsConfig" // Correct config + + case abTestsIdConfigError = "ABTestsIdConfigError" // Key is `idTest` instead of `id` + case abTestsIdConfigTypeError = "ABTestsIdConfigTypeError" // Type of `id` is Int instead of String + + case abTestsSdkVersionConfigError = "ABTestsSdkVersionConfigError" // Key is `sdkVersionTest` instead of `sdkVersion` + case abTestsSdkVersionConfigTypeError = "ABTestsSdkVersionConfigTypeError" // Type of `sdkVersion` is Int instead of SdkVersion +} + +final class ABTestsConfigParsingTests: XCTestCase { + + func test_ABTestsConfig_shouldParseSuccessfully() throws { + // Correct config + let config = try ABTestsConfig.configWithABTests.getConfig() + XCTAssertEqual(config.count, 2) + + for abTest in config { + XCTContext.runActivity(named: "Check abTest \(abTest) is in `config`") { test in + XCTAssertNotNil(abTest.salt) + XCTAssertNotNil(abTest.sdkVersion) + XCTAssertNotNil(abTest.variants) + } + } + } + + func test_ABTestsConfig_withIdError_shouldThrowDecodingError() throws { + // Key is `idTest` instead of `id` + XCTAssertThrowsError(try ABTestsConfig.abTestsIdConfigError.getConfig()) { error in + if let decodingError = error as? DecodingError { + switch decodingError { + case .keyNotFound(let key, let context): + XCTAssertEqual(key.stringValue, "id") + XCTAssertEqual(context.debugDescription, "No value associated with key CodingKeys(stringValue: \"id\", intValue: nil) (\"id\").") + default: + XCTFail("Unexpected DecodingError: \(error)") + } + } else { + XCTFail("Unexpected error: \(error)") + } + } + } + + func test_ABTestsConfig_withIdTypeError_shouldThrowDecodingError() throws { + // Type of `id` is Int instead of String + XCTAssertThrowsError(try ABTestsConfig.abTestsIdConfigTypeError.getConfig()) { error in + if let decodingError = error as? DecodingError { + switch decodingError { + case .typeMismatch(let type, let context): + XCTAssertEqual(type is String.Type, true, "Expected type mismatch for String") + XCTAssertEqual(context.codingPath.map { $0.stringValue }.joined(separator: ", "), "Index 0, id") + XCTAssertEqual(context.debugDescription, "Expected to decode String but found number instead.") + default: + XCTFail("Unexpected DecodingError: \(error)") + } + } else { + XCTFail("Unexpected error: \(error)") + } + } + } + + func test_ABTestsConfig_withSdkVersionError_shouldSetToNilCorruptedData() throws { + // Key is `sdkVersionTest` instead of `sdkVersion` + let config = try ABTestsConfig.abTestsSdkVersionConfigError.getConfig() + XCTAssertEqual(config.count, 2) + + for abTest in config { + XCTContext.runActivity(named: "Check abTest \(abTest) is in `config`") { test in + if abTest.id == "94CD824A-59AA-4937-9E0E-089895A0DB6F" { + XCTAssertNil(abTest.sdkVersion) + } else { + XCTAssertNotNil(abTest.sdkVersion) + } + XCTAssertNotNil(abTest.salt) + XCTAssertNotNil(abTest.variants) + } + } + } + + func test_ABTestsConfig_withSdkVersionTypeError_shouldThrowDecodingError() throws { + // Type of `sdkVersion` is Int instead of SdkVersion + XCTAssertThrowsError(try ABTestsConfig.abTestsSdkVersionConfigTypeError.getConfig()) { error in + if let decodingError = error as? DecodingError { + switch decodingError { + case .typeMismatch(let type, let context): + XCTAssertEqual(type is Dictionary.Type, true, "Expected type mismatch for Dictionary") + XCTAssertEqual(context.codingPath.map { $0.stringValue }.joined(separator: ", "), "Index 0, sdkVersion") + XCTAssertEqual(context.debugDescription, "Expected to decode Dictionary but found number instead.") + default: + XCTFail("Unexpected DecodingError: \(error)") + } + } else { + XCTFail("Unexpected error: \(error)") + } + } + } +} diff --git a/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsConfig.json b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsConfig.json new file mode 100644 index 00000000..2b050cc7 --- /dev/null +++ b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsConfig.json @@ -0,0 +1,79 @@ +[ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsIdConfigError.json b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsIdConfigError.json new file mode 100644 index 00000000..2c7472c7 --- /dev/null +++ b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsIdConfigError.json @@ -0,0 +1,83 @@ +[ + { + + + "idTest": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + + + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsIdConfigTypeError.json b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsIdConfigTypeError.json new file mode 100644 index 00000000..a0858561 --- /dev/null +++ b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsIdConfigTypeError.json @@ -0,0 +1,83 @@ +[ + { + + + "id": 1, + + + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsSdkVersionConfigError.json b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsSdkVersionConfigError.json new file mode 100644 index 00000000..c04c2c9e --- /dev/null +++ b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsSdkVersionConfigError.json @@ -0,0 +1,83 @@ +[ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + + + "sdkVersionTest": { + + + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsSdkVersionConfigTypeError.json b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsSdkVersionConfigTypeError.json new file mode 100644 index 00000000..140681ba --- /dev/null +++ b/MindboxTests/ConfigParsing/ABTests/ABTestsJsonStubs/ABTestsSdkVersionConfigTypeError.json @@ -0,0 +1,80 @@ +[ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + + + "sdkVersion": 1, + + + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsError.json new file mode 100644 index 00000000..9426adde --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsError.json @@ -0,0 +1,409 @@ +{ + + + "abtestsTest": [ + + + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ], + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsOneElementError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsOneElementError.json new file mode 100644 index 00000000..cba5b832 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsOneElementError.json @@ -0,0 +1,409 @@ +{ + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + + + "saltTest": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + + + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ], + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsOneElementTypeError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsOneElementTypeError.json new file mode 100644 index 00000000..7240e229 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsOneElementTypeError.json @@ -0,0 +1,378 @@ +{ + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + + "variants": 1 + + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ], + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsTypeError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsTypeError.json new file mode 100644 index 00000000..0abd01d7 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigABTestsTypeError.json @@ -0,0 +1,332 @@ +{ + + + "abtests": 1, + + + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigInAppsError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigInAppsError.json new file mode 100644 index 00000000..1852bcf6 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigInAppsError.json @@ -0,0 +1,409 @@ +{ + + + "inappsTest": [ + + + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigInAppsTypeError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigInAppsTypeError.json new file mode 100644 index 00000000..5a760d80 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigInAppsTypeError.json @@ -0,0 +1,117 @@ +{ + + + "inapps": 1, + + + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigMonitoringError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigMonitoringError.json new file mode 100644 index 00000000..0db3a399 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigMonitoringError.json @@ -0,0 +1,409 @@ +{ + + + "monitoringTest": { + + + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigMonitoringTypeError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigMonitoringTypeError.json new file mode 100644 index 00000000..32c20cd7 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigMonitoringTypeError.json @@ -0,0 +1,394 @@ +{ + + + "monitoring": 1, + + + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigSettingsError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigSettingsError.json new file mode 100644 index 00000000..193bf680 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigSettingsError.json @@ -0,0 +1,409 @@ +{ + + + "settingsTests": { + + + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigSettingsTypeError.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigSettingsTypeError.json new file mode 100644 index 00000000..54e190a1 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigSettingsTypeError.json @@ -0,0 +1,394 @@ +{ + + + "settings": 1, + + + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigWithSettingsABTestsMonitoringInapps.json b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigWithSettingsABTestsMonitoringInapps.json new file mode 100644 index 00000000..d55d8152 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigJsonStub/ConfigWithSettingsABTestsMonitoringInapps.json @@ -0,0 +1,405 @@ +{ + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/MindboxTests/ConfigParsing/Config/ConfigParsingTests.swift b/MindboxTests/ConfigParsing/Config/ConfigParsingTests.swift new file mode 100644 index 00000000..23fc7611 --- /dev/null +++ b/MindboxTests/ConfigParsing/Config/ConfigParsingTests.swift @@ -0,0 +1,133 @@ +// +// ConfigParsingTests.swift +// MindboxTests +// +// Created by Sergei Semko on 9/11/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import XCTest +@testable import Mindbox + +fileprivate enum Config: String, Configurable { + typealias DecodeType = ConfigResponse + + case configWithSettingsABTestsMonitoringInapps = "ConfigWithSettingsABTestsMonitoringInapps" // Correct config + + case configSettingsError = "ConfigSettingsError" // Key is `settingsTest` instead of `settings` + case configSettingsTypeError = "ConfigSettingsTypeError" // Type of `settings` is Int instead of Settings + + case configMonitoringError = "ConfigMonitoringError" // Key is `monitoringTest` instead of `monitoring` + case configMonitoringTypeError = "ConfigMonitoringTypeError" // Type of `monitoring` is Int instead of Monitoring + + case configABTestsError = "ConfigABTestsError" // Key is `abtestsTest` instead of `abtests` + case configABTestsTypeError = "ConfigABTestsTypeError" // Type of `abtests` is Int instead of [ABTest] + + case configInAppsError = "ConfigInAppsError" // Key is `inappsTest` instead of `inapps` + case configInAppsTypeError = "ConfigInAppsTypeError" // Type of `inapps` is Int instead of FailableDecodableArray + + case configABTestsOneElementError = "ConfigABTestsOneElementError" // Key is `saltTest` instead of `salt` + case configABTestsOneElementTypeError = "ConfigABTestsOneElementTypeError" // Type of `variants` is Int instead of [ABTestVariant] +} + +final class ConfigParsingTests: XCTestCase { + + func test_Config_shouldParseSuccessfully() throws { + // Correct config + let config = try! Config.configWithSettingsABTestsMonitoringInapps.getConfig() + XCTAssertNotNil(config.inapps, "Must NOT be nil") + XCTAssertNotNil(config.abtests, "Must NOT be nil") + XCTAssertNotNil(config.settings, "Must NOT be nil") + XCTAssertNotNil(config.monitoring, "Must NOT be nil") + } + + func test_Config_withSettingsError_shouldSetSettingsToNil() { + // Key is `settingsTest` instead of `settings` + let config = try! Config.configSettingsError.getConfig() + XCTAssertNil(config.settings, "Settings must be `nil` if the key `settings` is not found") + XCTAssertNotNil(config.inapps) + XCTAssertNotNil(config.abtests) + XCTAssertNotNil(config.monitoring) + } + + func test_Config_withSettingsTypeError_shouldSetSettingsToNil() { + // Type of `settings` is Int instead of Settings + let config = try! Config.configSettingsTypeError.getConfig() + XCTAssertNil(config.settings, "Settings must be `nil` if the type of `settings` is not `Settings`") + XCTAssertNotNil(config.inapps) + XCTAssertNotNil(config.abtests) + XCTAssertNotNil(config.monitoring) + } + + func test_Config_withMonitoringError_shouldSetMonitoringToNil() { + // Key is `monitoringTest` instead of `monitoring` + let config = try! Config.configMonitoringError.getConfig() + XCTAssertNil(config.monitoring, "Monitoring must be `nil` if the key `monitoring` is not found") + XCTAssertNotNil(config.settings) + XCTAssertNotNil(config.inapps) + XCTAssertNotNil(config.abtests) + } + + func test_Config_withMonitoringTypeError_shouldSetMonitoringToNil() { + // Type of `monitoring` is Int instead of Monitoring + let config = try! Config.configMonitoringTypeError.getConfig() + XCTAssertNil(config.monitoring, "Monitoring must be `nil` if the type of `monitoring` is not `Monitoring`") + XCTAssertNotNil(config.settings) + XCTAssertNotNil(config.inapps) + XCTAssertNotNil(config.abtests) + } + + func test_Config_withABTestsError_shouldSetABTestsToNil() { + // Key is `abtestsTest` instead of `abtests` + let config = try! Config.configABTestsError.getConfig() + XCTAssertNil(config.abtests, "ABTests must be `nil` if the key `abtests` is not found") + XCTAssertNotNil(config.monitoring) + XCTAssertNotNil(config.settings) + XCTAssertNotNil(config.inapps) + } + + func test_Config_withABTestsTypeError_shouldSetABTestsToNil() { + // Type of `abtests` is Int instead of [ABTest] + let config = try! Config.configABTestsTypeError.getConfig() + XCTAssertNil(config.abtests, "ABTests must be `nil` if the type of `abtests` is not `[ABTest]`") + XCTAssertNotNil(config.monitoring) + XCTAssertNotNil(config.settings) + XCTAssertNotNil(config.inapps) + } + + func test_Config_withInAppsError_shouldSetInAppsToNil() { + // Key is `inappsTest` instead of `inapps` + let config = try! Config.configInAppsError.getConfig() + XCTAssertNil(config.inapps, "InApps must be `nil` if the key `inapps` is not found") + XCTAssertNotNil(config.abtests) + XCTAssertNotNil(config.monitoring) + XCTAssertNotNil(config.settings) + } + + func test_Config_withInAppsTypeError_shouldSetInAppsToNil() { + // Type of `inapps` is Int instead of FailableDecodableArray + let config = try! Config.configInAppsTypeError.getConfig() + XCTAssertNil(config.inapps, "InApps must be `nil` if the type of `inapps` is not `FailableDecodableArray`") + XCTAssertNotNil(config.abtests) + XCTAssertNotNil(config.monitoring) + XCTAssertNotNil(config.settings) + } + + func test_Config_withABTestsOneElementError_shouldSetABTestsToNil() { + // Key is `saltTest` instead of `salt` + let config = try! Config.configABTestsOneElementError.getConfig() + XCTAssertNil(config.abtests, "ABTests must be `nil` if even one element is corrupted") + XCTAssertNotNil(config.monitoring) + XCTAssertNotNil(config.settings) + XCTAssertNotNil(config.inapps) + } + + func test_Config_withABTestsOneElementTypeError_shouldSetABTestsToNil() { + // Type of `variants` is Int instead of [ABTestVariant] + let config = try! Config.configABTestsOneElementTypeError.getConfig() + XCTAssertNil(config.abtests, "ABTests must be `nil` if even one element is corrupted") + XCTAssertNotNil(config.monitoring) + XCTAssertNotNil(config.settings) + XCTAssertNotNil(config.inapps) + } +} diff --git a/MindboxTests/ConfigParsing/Helpers/GetConfigFunc.swift b/MindboxTests/ConfigParsing/Helpers/GetConfigFunc.swift new file mode 100644 index 00000000..a4d975e2 --- /dev/null +++ b/MindboxTests/ConfigParsing/Helpers/GetConfigFunc.swift @@ -0,0 +1,30 @@ +// +// GetConfigFunc.swift +// MindboxTests +// +// Created by Sergei Semko on 9/11/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import Foundation + +protocol Configurable: RawRepresentable where RawValue == String { + associatedtype DecodeType: Decodable + func getConfig() throws -> DecodeType +} + +extension Configurable { + func getConfig() throws -> DecodeType { + try decodeConfig(name: self.rawValue) as DecodeType + } +} + +// TODO: Replace the implementation in all places with Generic (Commented tests) +private func decodeConfig(name: String) throws -> T { + let bundle = Bundle(for: MindboxTests.self) + guard let fileURL = bundle.url(forResource: name, withExtension: "json") else { + fatalError("JSON file `\(name)` was not found") + } + let data = try Data(contentsOf: fileURL) + return try JSONDecoder().decode(T.self, from: data) +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringConfigParsingTests.swift b/MindboxTests/ConfigParsing/Monitoring/MonitoringConfigParsingTests.swift new file mode 100644 index 00000000..c055172f --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringConfigParsingTests.swift @@ -0,0 +1,117 @@ +// +// MonitoringConfigParsingTests.swift +// MindboxTests +// +// Created by Sergei Semko on 9/11/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import XCTest +@testable import Mindbox + +fileprivate enum MonitoringConfig: String, Configurable { + typealias DecodeType = Monitoring + + case configWithMonitoring = "MonitoringConfig" // Correct config + + case monitoringLogsError = "MonitoringLogsError" // Key is `logsTests` instead of `logs` + case monitoringLogsTypeError = "MonitoringLogsTypeError" // Type of `logs` is Int instead of FailableDecodableArray + + case monitoringLogsOneElementError = "MonitoringLogsOneElementError" // Key is `request` instead of `requestId` + case monitoringLogsTwoElementsError = "MonitoringLogsTwoElementsError" // Key is `request` instead of `requestId` and key is `device` instead of `deviceUUID` + + case monitoringLogsOneElementTypeError = "MonitoringLogsOneElementTypeError" // Type of `requestId` is Int instead of String + case monitoringLogsTwoElementsTypeError = "MonitoringLogsTwoElementsTypeError" // Type of `requestId` is Int instead of String and type of `from` is Object instead `String` + case monitoringLogsElementsMixedError = "MonitoringLogsElementsMixedError" // Type of `requestId` is Int instead of String and key is `fromTest` instead of `from` +} + +final class MonitoringConfigParsingTests: XCTestCase { + + func test_MonitoringConfig_shouldParseSuccessfully() { + // Correct config + let config = try! MonitoringConfig.configWithMonitoring.getConfig() + + XCTAssertEqual(config.logs.elements.count, 2) + + for log in config.logs.elements { + XCTContext.runActivity(named: "Check log \(log) is in `config.logs.elements`") { test in + XCTAssertNotNil(log.deviceUUID) + XCTAssertNotNil(log.requestId) + XCTAssertNotNil(log.from) + XCTAssertNotNil(log.to) + } + } + } + + func test_MonitoringConfig_withLogsError_shouldSetMonitoringToNil() { + // Key is `logsTests` instead of `logs` + let config = try? MonitoringConfig.monitoringLogsError.getConfig() + XCTAssertNil(config, "Monitoring must be `nil` if the key `logs` is not found") + XCTAssertNil(config?.logs, "Logs must be `nil` if the key `logs` is not found") + } + + func test_MonitoringConfig_withLogsTypeError_shouldSetMonitoringToNil() { + // Type of `logs` is Int instead of FailableDecodableArray + let config = try? MonitoringConfig.monitoringLogsTypeError.getConfig() + XCTAssertNil(config, "Monitoring must be `nil` if the type of `logs` is not a `FailableDecodableArray`") + XCTAssertNil(config?.logs, "Logs must be `nil` if the type of `logs` is not a `FailableDecodableArray`") + } + + func test_MonitoringConfig_withLogsOneElementError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String + let config = try? MonitoringConfig.monitoringLogsOneElementError.getConfig() + XCTAssertNotNil(config?.logs, "Monitoring must be parsed successfully") + + XCTAssertEqual(config?.logs.elements.count, 1) + + for log in config!.logs.elements { + XCTContext.runActivity(named: "Check log \(log) is in `config.logs.elements`") { test in + XCTAssertNotNil(log.deviceUUID) + XCTAssertNotNil(log.requestId) + XCTAssertNotNil(log.from) + XCTAssertNotNil(log.to) + } + } + } + + func test_MonitoringConfig_withLogsOneElementTypeError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String + let config = try? MonitoringConfig.monitoringLogsOneElementTypeError.getConfig() + XCTAssertNotNil(config?.logs, "Monitoring must be parsed successfully") + + XCTAssertEqual(config?.logs.elements.count, 1) + + for log in config!.logs.elements { + XCTContext.runActivity(named: "Check log \(log) is in `config.logs.elements`") { test in + XCTAssertNotNil(log.deviceUUID) + XCTAssertNotNil(log.requestId) + XCTAssertNotNil(log.from) + XCTAssertNotNil(log.to) + } + } + } + + func test_MonitoringConfig_withLogsTwoElementsError_shouldParseSuccessfullyRemainsElements() { + // Key is `request` instead `requestId` and key is `device` instead of `deviceUUID` + let config = try? MonitoringConfig.monitoringLogsTwoElementsError.getConfig() + XCTAssertNotNil(config?.logs, "Monitoring must be parsed successfully") + + XCTAssertEqual(config?.logs.elements.count, 0) + } + + func test_MonitoringConfig_withLogsTwoElementsTypeError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String and type of `from` is Object instead of `String` + let config = try? MonitoringConfig.monitoringLogsTwoElementsTypeError.getConfig() + XCTAssertNotNil(config?.logs, "Monitoring must be parsed successfully, but with empty array") + + XCTAssertEqual(config?.logs.elements.count, 0) + } + + func test_MonitoringConfig_withLogsTwoElementsMixedError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String and key is `fromTest` instead of `from` + let config = try? MonitoringConfig.monitoringLogsElementsMixedError.getConfig() + XCTAssertNotNil(config?.logs, "Monitoring must be parsed successfully, but with empty array") + + XCTAssertEqual(config?.logs.elements.count, 0) + } +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringConfig.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringConfig.json new file mode 100644 index 00000000..a9136d52 --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringConfig.json @@ -0,0 +1,16 @@ +{ + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsElementsMixedError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsElementsMixedError.json new file mode 100644 index 00000000..eaa70659 --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsElementsMixedError.json @@ -0,0 +1,24 @@ +{ + "logs": [ + { + + + "requestId": 1, + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + + + "fromTest": "2023-02-10T00:00:00", + + + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsError.json new file mode 100644 index 00000000..9213c9c1 --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsError.json @@ -0,0 +1,20 @@ +{ + + + "logsTests": [ + + + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsOneElementError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsOneElementError.json new file mode 100644 index 00000000..e263115b --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsOneElementError.json @@ -0,0 +1,20 @@ +{ + "logs": [ + { + + + "request": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsOneElementTypeError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsOneElementTypeError.json new file mode 100644 index 00000000..08307986 --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsOneElementTypeError.json @@ -0,0 +1,20 @@ +{ + "logs": [ + { + + + "requestId": 1, + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTwoElementsError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTwoElementsError.json new file mode 100644 index 00000000..145f8361 --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTwoElementsError.json @@ -0,0 +1,24 @@ +{ + "logs": [ + { + + + "request": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + + + "device": "126e6225-3170-4089-a6f0-3d1ed8f64153", + + + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTwoElementsTypeError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTwoElementsTypeError.json new file mode 100644 index 00000000..458743c1 --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTwoElementsTypeError.json @@ -0,0 +1,24 @@ +{ + "logs": [ + { + + + "requestId": 1, + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + + + "from": { }, + + + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTypeError.json b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTypeError.json new file mode 100644 index 00000000..f48076ed --- /dev/null +++ b/MindboxTests/ConfigParsing/Monitoring/MonitoringJsonStubs/MonitoringLogsTypeError.json @@ -0,0 +1,7 @@ +{ + + + "logs": 1 + + +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsConfigParsingTests.swift b/MindboxTests/ConfigParsing/Settings/SettingsConfigParsingTests.swift new file mode 100644 index 00000000..a3280474 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsConfigParsingTests.swift @@ -0,0 +1,269 @@ +// +// SettingsConfigParsingTests.swift +// MindboxTests +// +// Created by Sergei Semko on 9/11/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import XCTest +@testable import Mindbox + +fileprivate enum SettingsConfig: String, Configurable { + typealias DecodeType = Settings + + case configWithSettings = "SettingsConfig" // Correct config + + // Operations file names + + case settingsOperationsError = "SettingsOperationsError" // Key is `operationsTests` instead of `operations` + case settingsOperationsTypeError = "SettingsOperationsTypeError" // Type of `operations` is Int instead of `SettingsOperations` + + case settingsOperationsViewProductError = "SettingsOperationsViewProductError" // Key is `viewProductTest` instead of `viewProduct` + case settingsOperationsViewProductTypeError = "SettingsOperationsViewProductTypeError" // Type of `viewProduct` is Int instead of Operation + + case settingsOperationsViewProductSystemNameError = "SettingsOperationsViewProductSystemNameError" // Key is `systemNameTest` instead of `systemName` + case settingsOperationsViewProductSystemNameTypeError = "SettingsOperationsViewProductSystemNameTypeError" // Type of `systemName` is Int instead of String + + case settingsAllOperationsWithErrors = "SettingsAllOperationsWithErrors" // Keys are `viewProductTest`, `viewCategoryTest` and `setCartTest` instead of `viewProduct`, `viewCategory` and `setCart` + case settingsAllOperationsWithTypeErrors = "SettingsAllOperationsWithTypeErrors" // Types of `viewProduct`, `viewCategory` and `setCart` are Int instead of String + + case settingsOperationsViewCategoryAndSetCartError = "SettingsOperationsViewCategoryAndSetCartError" // Keys are `viewCategoryTest` and `setCartTest` instead of `viewCategory` and `setCart` + case settingsOperationsViewCategoryAndSetCartTypeError = "SettingsOperationsViewCategoryAndSetCartTypeError" // Types of `viewCategory` and `setCart` are Int instead of String + case settingsOperationsViewCategoryAndSetCartSystemNameError = "SettingsOperationsViewCategoryAndSetCartSystemNameError" // Keys are `systemNameTest` instead of `systemName` + case settingsOperationsViewCategoryAndSetCartSystemNameTypeError = "SettingsOperationsViewCategoryAndSetCartSystemNameTypeError" // Types of `systemName` are Int instead of String + case settingsOperationsViewCategoryAndSetCartSystemNameMixedError = "SettingsOperationsViewCategoryAndSetCartSystemNameMixedError" // Key of `viewCategory` is `systemNameTest` instead of `systemName` and type of `setCart`:`systemName` is Int instead of String + + // TTL file names + + case ttlError = "SettingsTtlError" // Key `ttlTest` instead of `ttl` + case ttlTypeError = "SettingsTtlTypeError" // Type of `ttl` is Int instead of TimeToLive + + case ttlInappsError = "SettingsTtlInappsError" // Key is `inappsTest` instead of `inapps` + case ttlInappsTypeError = "SettingsTtlInappsTypeError" // Type of `ttl` is Int instead of String +} + +final class SettingsConfigParsingTests: XCTestCase { + + // MARK: Settings + + func test_SettingsConfig_shouldParseSuccessfully() { + // Correct config + let config = try! SettingsConfig.configWithSettings.getConfig() + XCTAssertNotNil(config.operations) + XCTAssertNotNil(config.operations?.viewProduct) + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl) + XCTAssertNotNil(config.ttl?.inapps) + } + + // MARK: - Operations + + func test_SettingsConfig_withOperationsError_shouldSetOperationsToNil() { + // Key is `operationsTests` instead of `operations` + let config = try! SettingsConfig.settingsOperationsError.getConfig() + XCTAssertNil(config.operations, "Operations must be `nil` if the key `operations` is not found") + XCTAssertNil(config.operations?.viewProduct) + XCTAssertNil(config.operations?.viewCategory) + XCTAssertNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsTypeError_shouldSetOperationsToNil() { + // Type of `operations` is Int instead of `SettingsOperations` + let config = try! SettingsConfig.settingsOperationsTypeError.getConfig() + XCTAssertNil(config.operations, "Operations must be `nil` if the type of `operations` is not a `SettingsOperations`") + XCTAssertNil(config.operations?.viewProduct) + XCTAssertNil(config.operations?.viewCategory) + XCTAssertNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewProductError_shouldSetViewProductToNil() { + // Key is `viewProductTest` instead of `viewProduct` + let config = try! SettingsConfig.settingsOperationsViewProductError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNil(config.operations?.viewProduct, "ViewProduct must be `nil` if the key `viewProduct` is not found") + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewProductTypeError_shouldSetViewProductToNil() { + // Type of `viewProduct` is Int instead of Operation + let config = try! SettingsConfig.settingsOperationsViewProductTypeError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNil(config.operations?.viewProduct, "ViewProduct must be `nil` if the type of `viewProduct` is not an `Operation`") + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewProductSystemNameError_shouldSetViewProductToNil() { + // Key is `systemNameTest` instead of `systemName` + let config = try! SettingsConfig.settingsOperationsViewProductSystemNameError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNil(config.operations?.viewProduct, "ViewProduct must be `nil` if the key `systemName` is not found") + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewProductSystemNameTypeError_shouldSetViewProductToNil() { + // Type of `systemName` is Int instead of String + let config = try! SettingsConfig.settingsOperationsViewProductSystemNameTypeError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNil(config.operations?.viewProduct, "ViewProduct must be `nil` if the type of `systemName` is not a `String`") + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withAllOperationsWithErrors_shouldSetOperationsToNil() { + // Keys are `viewProductTest`, `viewCategoryTest` and `setCartTest` instead of `viewProduct`, `viewCategory` and `setCart` + let config = try! SettingsConfig.settingsAllOperationsWithErrors.getConfig() + XCTAssertNil(config.operations, "Operations must be `nil` if all three operations are `nil`") + XCTAssertNil(config.operations?.viewProduct) + XCTAssertNil(config.operations?.viewCategory) + XCTAssertNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withAllOperationsWithTypeErrors_shouldSetOperationsToNil() { + // Types of `viewProduct`, `viewCategory` and `setCart` are Int instead of String + let config = try! SettingsConfig.settingsAllOperationsWithTypeErrors.getConfig() + XCTAssertNil(config.operations, "Operations must be `nil` if all three operations are `nil`") + XCTAssertNil(config.operations?.viewProduct) + XCTAssertNil(config.operations?.viewCategory) + XCTAssertNil(config.operations?.setCart) + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewCategoryAndSetCartError_shouldSetViewCategoryAndSetCartToNil() { + // Keys are `viewCategoryTest` and `setCartTest` instead of `viewCategory` and `setCart` + let config = try! SettingsConfig.settingsOperationsViewCategoryAndSetCartError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct, "ViewProduct must be successfully parsed") + XCTAssertNil(config.operations?.viewCategory, "ViewCategory must be `nil` if the key `viewCategory` is not found") + XCTAssertNil(config.operations?.setCart, "setCart must be `nil` if the key `setCart` is not found") + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewCategoryAndSetCartTypeError_shouldSetViewCategoryAndSetCartToNil() { + // Types of `viewCategory` and `setCart` are Int instead of String + let config = try! SettingsConfig.settingsOperationsViewCategoryAndSetCartTypeError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct, "ViewProduct must be successfully parsed") + XCTAssertNil(config.operations?.viewCategory, "ViewCategory must be `nil` if the type of `ViewCategory` is not a `SettingsOperations`") + XCTAssertNil(config.operations?.setCart, "setCart must be `nil` if the type `setCart` is not a `SettingsOperations`") + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewCategoryAndSetCartSystemNameError_shouldSetViewCategoryAndSetCartToNil() { + // Keys are `systemNameTest` instead of `systemName` + let config = try! SettingsConfig.settingsOperationsViewCategoryAndSetCartSystemNameError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct, "ViewProduct must be successfully parsed") + XCTAssertNil(config.operations?.viewCategory, "ViewCategory must be `nil` if the key `systemName` is not found") + XCTAssertNil(config.operations?.setCart, "setCart must be `nil` if the key `systemName` is not found") + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewCategoryAndSetCartSystemNameTypeError_shouldSetViewCategoryAndSetCartToNil() { + // Types of `systemName` are Int instead of String + let config = try! SettingsConfig.settingsOperationsViewCategoryAndSetCartSystemNameTypeError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct, "ViewProduct must be successfully parsed") + XCTAssertNil(config.operations?.viewCategory, "ViewCategory must be `nil` if the type of `systemName` is not a `String`") + XCTAssertNil(config.operations?.setCart, "setCart must be `nil` if the type `systemName` is not a `String`") + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + func test_SettingsConfig_withOperationsViewCategoryAndSetCartSystemNameMixedError_shouldSetViewCategoryAndSetCartToNil() { + // Key of `viewCategory` is `systemNameTest` instead of `systemName` and type of `setCart`:`systemName` is Int instead of String + let config = try! SettingsConfig.settingsOperationsViewCategoryAndSetCartSystemNameMixedError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct, "ViewProduct must be successfully parsed") + XCTAssertNil(config.operations?.viewCategory, "ViewCategory must be `nil` if the key `systemName` is not found") + XCTAssertNil(config.operations?.setCart, "setCart must be `nil` if the type `systemName` is not a `String`") + + XCTAssertNotNil(config.ttl, "TTL must be successfully parsed") + XCTAssertNotNil(config.ttl?.inapps, "TTL must be successfully parsed") + } + + // MARK: - TTL + + func test_SettingsConfig_withTtlError_shouldSetTtlToNil() { + // Key `ttlTest` instead of `ttl` + let config = try! SettingsConfig.ttlError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct) + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNil(config.ttl, "TTL must be `nil` if the key `ttl` is not found") + XCTAssertNil(config.ttl?.inapps, "TTL must be nil") + } + + func test_SettingsConfig_withTtlTypeError_shouldSetTtlToNil() { + // Type of `ttl` is Int instead of TimeToLive + let config = try! SettingsConfig.ttlTypeError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct) + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNil(config.ttl, "TTL must be `nil` if the type of `inapps` is not a `TimeToLive`") + XCTAssertNil(config.ttl?.inapps, "TTL must be nil") + } + + func test_SettingsConfig_withTtlInappsError_shouldSetTtlToNil() { + // Key is `inappsTest` instead of `inapps` + let config = try! SettingsConfig.ttlInappsError.getConfig() + XCTAssertNotNil(config.operations, "Operations must be successfully parsed") + XCTAssertNotNil(config.operations?.viewProduct) + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNil(config.ttl, "TTL must be `nil` if the key `inapps` is not found") + XCTAssertNil(config.ttl?.inapps, "TTL must be nil") + } + + func test_SettingsConfig_withTtlInappsTypeError_shouldSetTtlToNil() { + // Type of `ttl` is Int instead of String + let config = try! SettingsConfig.ttlInappsTypeError.getConfig() + XCTAssertNotNil(config.operations) + XCTAssertNotNil(config.operations?.viewProduct) + XCTAssertNotNil(config.operations?.viewCategory) + XCTAssertNotNil(config.operations?.setCart) + + XCTAssertNil(config.ttl, "TTL must be `nil` if the key `inapps` is not a `String`") + XCTAssertNil(config.ttl?.inapps, "TTL must be `nil` if the key `inapps` is not a `String`") + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsAllOperationsWithErrors.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsAllOperationsWithErrors.json new file mode 100644 index 00000000..8a31d185 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsAllOperationsWithErrors.json @@ -0,0 +1,20 @@ +{ + "operations": { + + + "viewProductTest": { + "systemName": "ViewProduct" + }, + "viewCategoryTest": { + "systemName": "ViewCategory" + }, + "setCartTest": { + "systemName": "SetCart" + } + + + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsAllOperationsWithTypeErrors.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsAllOperationsWithTypeErrors.json new file mode 100644 index 00000000..4dcc17bc --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsAllOperationsWithTypeErrors.json @@ -0,0 +1,14 @@ +{ + "operations": { + + + "viewProduct": 1, + "viewCategory": 2, + "setCart": 2 + + + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsError.json new file mode 100644 index 00000000..b28b33f5 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsError.json @@ -0,0 +1,20 @@ +{ + + + "operationsTests": { + + + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsTypeError.json new file mode 100644 index 00000000..ca9f886d --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsTypeError.json @@ -0,0 +1,10 @@ +{ + + + "operations": 1, + + + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json new file mode 100644 index 00000000..bf0d8b79 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + + + "viewCategoryTest": { + "systemName": "ViewCategory" + }, + "setCartTest": { + + + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json new file mode 100644 index 00000000..2d4a8709 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + + + "viewCategory": { + "systemNameTest": "ViewCategory" + }, + "setCart": { + "systemNameTest": "SetCart" + } + + + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json new file mode 100644 index 00000000..e3e5749d --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + + + "viewCategory": { + "systemNameTest": "ViewCategory" + }, + "setCart": { + "systemName": 123 + } + + + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json new file mode 100644 index 00000000..d393fd1a --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + + + "viewCategory": { + "systemName": 123 + }, + "setCart": { + "systemName": 321 + } + + + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json new file mode 100644 index 00000000..dc488847 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + + + "viewCategory": 1, + "setCart": 2 + + + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductError.json new file mode 100644 index 00000000..ac922a4a --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductError.json @@ -0,0 +1,20 @@ +{ + "operations": { + + + "viewProductTest": { + + + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductSystemNameError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductSystemNameError.json new file mode 100644 index 00000000..f2c6859e --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductSystemNameError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + + + "systemNameTest": "ViewProduct" + + + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json new file mode 100644 index 00000000..1f1a7a35 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + + + "systemName": 123 + + + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductTypeError.json new file mode 100644 index 00000000..3942b921 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/OperationsErrors/SettingsOperationsViewProductTypeError.json @@ -0,0 +1,18 @@ +{ + "operations": { + + + "viewProduct": 123, + + + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/SettingsConfig.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/SettingsConfig.json new file mode 100644 index 00000000..ea62a96c --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/SettingsConfig.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlError.json new file mode 100644 index 00000000..37b09ba9 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + + + "ttlTest": { + + + "inapps": "1.00:00:00" + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlInappsError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlInappsError.json new file mode 100644 index 00000000..5b896b82 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlInappsError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + + + "inappsTest": "1.00:00:00" + + + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlInappsTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlInappsTypeError.json new file mode 100644 index 00000000..1bf35291 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlInappsTypeError.json @@ -0,0 +1,20 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + + + "inapps": 123 + + + } +} diff --git a/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlTypeError.json b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlTypeError.json new file mode 100644 index 00000000..50529ff0 --- /dev/null +++ b/MindboxTests/ConfigParsing/Settings/SettingsJsonStubs/TtlErrors/SettingsTtlTypeError.json @@ -0,0 +1,18 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + + + "ttl": 123 + + +} diff --git a/MindboxTests/MigrationsTests/MigrationManagerTests.swift b/MindboxTests/MigrationsTests/MigrationManagerTests.swift index bbf39603..4dc3c4dd 100644 --- a/MindboxTests/MigrationsTests/MigrationManagerTests.swift +++ b/MindboxTests/MigrationsTests/MigrationManagerTests.swift @@ -50,6 +50,9 @@ final class MigrationManagerTests: XCTestCase { migrationManager.migrate() XCTAssertTrue(persistenceStorageMock.versionCodeForMigration == Constants.Migration.sdkVersionCode) XCTAssertNotNil(persistenceStorageMock.configDownloadDate, "Must NOT `softReset()` `persistenceStorage`") + + XCTAssertNotNil(persistenceStorageMock.shownInappsDictionary, "shownInAppDictionary must NOT be nil after MigrationShownInAppIds") + XCTAssertNil(persistenceStorageMock.shownInAppsIds, "shownInAppsIds must be nil after MigrationShownInAppIds") } func testPerformTestMigrationsButFirstInstallationAndSkipMigrations() { diff --git a/MindboxTests/MigrationsTests/ShownInAppsIdsMigrationTests.swift b/MindboxTests/MigrationsTests/ShownInAppsIdsMigrationTests.swift new file mode 100644 index 00000000..d34a4dfd --- /dev/null +++ b/MindboxTests/MigrationsTests/ShownInAppsIdsMigrationTests.swift @@ -0,0 +1,154 @@ +// +// ShownInAppsIdsMigrationTests.swift +// MindboxTests +// +// Created by Sergei Semko on 9/2/24. +// Copyright © 2024 Mindbox. All rights reserved. +// + +import XCTest +@testable import Mindbox +@testable import MindboxLogger + +final class ShownInAppsIdsMigrationTests: XCTestCase { + + private var shownInAppsIdsMigration: MigrationProtocol! + private var migrationManager: MigrationManagerProtocol! + private var persistenceStorageMock: PersistenceStorage! + + private var mbLoggerCDManager: MBLoggerCoreDataManager! + + private let shownInAppsIdsBeforeMigration: [String] = [ + "36920d7e-3c42-4194-9a11-b0b5c550460c", + "37bed734-aa34-4c10-918b-873f67505d46" + ] + + override func setUp() { + super.setUp() + shownInAppsIdsMigration = MigrationShownInAppsIds() + + mbLoggerCDManager = MBLoggerCoreDataManager() + + persistenceStorageMock = DI.injectOrFail(PersistenceStorage.self) + persistenceStorageMock.deviceUUID = "00000000-0000-0000-0000-000000000000" + persistenceStorageMock.installationDate = Date() + persistenceStorageMock.shownInappsDictionary = nil + persistenceStorageMock.shownInAppsIds = shownInAppsIdsBeforeMigration + + let testMigrations: [MigrationProtocol] = [ + shownInAppsIdsMigration + ] + + migrationManager = MigrationManager( + persistenceStorage: persistenceStorageMock, + migrations: testMigrations, + sdkVersionCode: 0 + ) + } + + override func tearDown() { + shownInAppsIdsMigration = nil + mbLoggerCDManager = nil + migrationManager = nil + persistenceStorageMock = nil + super.tearDown() + } + + func test_ShownInAppsIdsMigration_withIsNeededTrue_shouldPerfromSuccessfully() throws { + try mbLoggerCDManager.deleteAll() + + let migrationExpectation = XCTestExpectation(description: "Migration completed") + migrationManager.migrate() + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + XCTAssertNotNil(self.persistenceStorageMock.shownInappsDictionary, "shownInAppDictionary must NOT be nil after MigrationShownInAppIds") + XCTAssertNil(self.persistenceStorageMock.shownInAppsIds, "shownInAppsIds must be nil after MigrationShownInAppIds") + XCTAssertEqual(self.shownInAppsIdsBeforeMigration.count, self.persistenceStorageMock.shownInappsDictionary?.count, "Count must be equal") + + for shownInAppsIdBeforeMigration in self.shownInAppsIdsBeforeMigration { + XCTContext.runActivity(named: "Check shownInAppsId \(shownInAppsIdBeforeMigration) is in shownInappsDictionary") { test in + let contains = self.persistenceStorageMock.shownInappsDictionary?.keys.contains(shownInAppsIdBeforeMigration) ?? false + XCTAssertTrue(contains, "The shownInAppsId \(shownInAppsIdBeforeMigration) should be in shownInappsDictionary") + } + } + + migrationExpectation.fulfill() + } + + wait(for: [migrationExpectation], timeout: 5) + + let lastLog = try mbLoggerCDManager.getLastLog() + let expectedLogMessage = "[Migrations] Migrations have been successful\n" + XCTAssertEqual(lastLog?.message, expectedLogMessage) + } + + func test_ShownInAppsIdsMigration_withIsNeededFalse_shouldHaveBeenSkipped() throws { + try mbLoggerCDManager.deleteAll() + + let migrationExpectation = XCTestExpectation(description: "Migration completed") + + let testMigrations: [MigrationProtocol] = [ + shownInAppsIdsMigration + ] + + let shownInappsDictionary: [String: Date] = [ + "36920d7e-3c42-4194-9a11-b0b5c550460c": Date(), + "37bed734-aa34-4c10-918b-873f67505d46": Date() + ] + + persistenceStorageMock.shownInappsDictionary = shownInappsDictionary + persistenceStorageMock.shownInAppsIds = nil + + migrationManager = MigrationManager(persistenceStorage: persistenceStorageMock, + migrations: testMigrations, sdkVersionCode: 0) + + migrationManager.migrate() + + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + XCTAssertNotNil(self.persistenceStorageMock.shownInappsDictionary, "shownInAppDictionary must NOT be nil") + XCTAssertNil(self.persistenceStorageMock.shownInAppsIds, "shownInAppsIds must be nil") + XCTAssertEqual(shownInappsDictionary, self.persistenceStorageMock.shownInappsDictionary, "Must be equal") + + let defaultSetDateAfterMigration = Date(timeIntervalSince1970: 0) + for (_, value) in self.persistenceStorageMock.shownInappsDictionary! { + XCTAssertNotEqual(value, defaultSetDateAfterMigration) + } + + migrationExpectation.fulfill() + } + + wait(for: [migrationExpectation], timeout: 5) + + let lastLog = try mbLoggerCDManager.getLastLog() + let expectedLogMessage = "[Migrations] Migrations have been skipped\n" + XCTAssertEqual(lastLog?.message, expectedLogMessage) + } + + func test_ShownInAppsIdsMigration_withDoubleCall_shouldBePerformedOnlyTheFirstTime() throws { + try mbLoggerCDManager.deleteAll() + + migrationManager.migrate() + let migrationExpectation = XCTestExpectation(description: "Migration completed") + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + migrationExpectation.fulfill() + } + + wait(for: [migrationExpectation], timeout: 5) + + var lastLog = try! mbLoggerCDManager.getLastLog()?.message + var expectedLogMessage = "[Migrations] Migrations have been successful\n" + XCTAssertEqual(lastLog, expectedLogMessage) + + migrationManager.migrate() + + let migrationExpectationTwo = XCTestExpectation(description: "Migration 2 completed") + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + migrationExpectationTwo.fulfill() + } + + wait(for: [migrationExpectationTwo], timeout: 5) + lastLog = try! mbLoggerCDManager.getLastLog()?.message + expectedLogMessage = "[Migrations] Migrations have been skipped\n" + XCTAssertEqual(lastLog, expectedLogMessage) + } +} + diff --git a/MindboxTests/MigrationsTests/TestMigrations/TestBaseMigrations.swift b/MindboxTests/MigrationsTests/TestsMigrations/TestBaseMigrations.swift similarity index 100% rename from MindboxTests/MigrationsTests/TestMigrations/TestBaseMigrations.swift rename to MindboxTests/MigrationsTests/TestsMigrations/TestBaseMigrations.swift diff --git a/MindboxTests/MigrationsTests/TestMigrations/TestProtocolMigrations.swift b/MindboxTests/MigrationsTests/TestsMigrations/TestProtocolMigrations.swift similarity index 100% rename from MindboxTests/MigrationsTests/TestMigrations/TestProtocolMigrations.swift rename to MindboxTests/MigrationsTests/TestsMigrations/TestProtocolMigrations.swift diff --git a/MindboxTests/MindboxLogger/MBLoggerCoreDataManagerTests.swift b/MindboxTests/MindboxLogger/MBLoggerCoreDataManagerTests.swift index a733a4ee..2acbe92d 100644 --- a/MindboxTests/MindboxLogger/MBLoggerCoreDataManagerTests.swift +++ b/MindboxTests/MindboxLogger/MBLoggerCoreDataManagerTests.swift @@ -19,69 +19,145 @@ final class MBLoggerCoreDataManagerTests: XCTestCase { } override func tearDown() { - do { - try manager.deleteAll() - } catch { } manager = nil super.tearDown() } + + func test_measure_create() throws { + try manager.deleteAll() + measure { + let fetchExpectation = XCTestExpectation(description: "Fetch created log") + let message = "Test message" + let timestamp = Date() + manager.create(message: message, timestamp: timestamp) { + fetchExpectation.fulfill() + } + wait(for: [fetchExpectation], timeout: 2.0) + } + } + + func test_measure_create_10_000() throws { + try manager.deleteAll() + measure { + let logsCount = 10_000 + let fetchExpectation = XCTestExpectation(description: "Fetch created log") + fetchExpectation.expectedFulfillmentCount = logsCount + let message = "Test message" + let timestamp = Date() + for i in 0..