From 2ceaf0e4ddc3f3987be70381e114b1771e1d08c1 Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Fri, 14 Jun 2024 16:25:21 -0400 Subject: [PATCH 1/8] added unit test --- Sources/Public/SDK/ATTNSDK.swift | 83 ++++++++++++------- .../ATTNCreativeUrlProvider.swift | 40 ++++----- .../Configs/ATTNCreativeUrlConfig.swift | 16 ++++ .../Spies/ATTNCreativeUrlProviderSpy.swift | 4 +- .../ATTNCreativeUrlFormatterTests.swift | 78 +++++++++++++++-- attentive-ios-sdk.xcodeproj/project.pbxproj | 12 +++ .../xcshareddata/swiftpm/Package.resolved | 4 +- 7 files changed, 176 insertions(+), 61 deletions(-) create mode 100644 Sources/URLProviders/Configs/ATTNCreativeUrlConfig.swift diff --git a/Sources/Public/SDK/ATTNSDK.swift b/Sources/Public/SDK/ATTNSDK.swift index dffc4a7..b6b5d72 100644 --- a/Sources/Public/SDK/ATTNSDK.swift +++ b/Sources/Public/SDK/ATTNSDK.swift @@ -51,6 +51,8 @@ public final class ATTNSDK: NSObject { private var mode: ATTNSDKMode private var urlBuilder: ATTNCreativeUrlProviding = ATTNCreativeUrlProvider() + public var skipFatigueOnCreatives: Bool = false + public init(domain: String, mode: ATTNSDKMode) { NSLog("init attentive_ios_sdk v%@", ATTNConstants.sdkVersion) self.domain = domain @@ -84,11 +86,52 @@ public final class ATTNSDK: NSObject { @objc(trigger:) public func trigger(_ view: UIView) { - trigger(view, handler: nil) + launchCreative(parentView: view) } @objc(trigger:handler:) public func trigger(_ view: UIView, handler: ATTNCreativeTriggerCompletionHandler?) { + launchCreative(parentView: view, handler: handler) + } + + @objc(trigger:creativeId:handler:) + public func trigger(_ view: UIView, creativeId: String, handler: ATTNCreativeTriggerCompletionHandler?) { + launchCreative(parentView: view, creativeId: creativeId, handler: handler) + } + + @objc(clearUser) + public func clearUser() { + userIdentity.clearUser() + } + + @objc(updateDomain:) + public func update(domain: String) { + guard self.domain != domain else { return } + self.domain = domain + api.update(domain: domain) + api.send(userIdentity: userIdentity) + } +} + +// MARK: Private Helpers +fileprivate extension ATTNSDK { + func sendInfoEvent() { + api.send(event: ATTNInfoEvent(), userIdentity: userIdentity) + } + + func closeCreative() { + webView?.removeFromSuperview() + webView = nil + ATTNSDK.isCreativeOpen = false + triggerHandler?(ATTNCreativeTriggerStatus.closed) + NSLog("Successfully closed creative") + } + + func launchCreative( + parentView view: UIView, + creativeId: String? = nil, + handler: ATTNCreativeTriggerCompletionHandler? = nil + ) { parentView = view triggerHandler = handler @@ -107,9 +150,13 @@ public final class ATTNSDK: NSObject { NSLog("The iOS version is new enough, continuing to show the Attentive creative.") let creativePageUrl = urlBuilder.buildCompanyCreativeUrl( - forDomain: domain, - mode: mode.rawValue, - userIdentity: userIdentity + configuration: ATTNCreativeUrlConfig( + domain: domain, + creativeId: creativeId, + skipFatigue: skipFatigueOnCreatives, + mode: mode.rawValue, + userIdentity: userIdentity + ) ) NSLog("Requesting creative page url: %@", creativePageUrl) @@ -142,34 +189,6 @@ public final class ATTNSDK: NSObject { webView.backgroundColor = .clear } } - - @objc(clearUser) - public func clearUser() { - userIdentity.clearUser() - } - - @objc(updateDomain:) - public func update(domain: String) { - guard self.domain != domain else { return } - self.domain = domain - api.update(domain: domain) - api.send(userIdentity: userIdentity) - } -} - -// MARK: Private Helpers -fileprivate extension ATTNSDK { - func sendInfoEvent() { - api.send(event: ATTNInfoEvent(), userIdentity: userIdentity) - } - - func closeCreative() { - webView?.removeFromSuperview() - webView = nil - ATTNSDK.isCreativeOpen = false - triggerHandler?(ATTNCreativeTriggerStatus.closed) - NSLog("Successfully closed creative") - } } // MARK: WKScriptMessageHandler diff --git a/Sources/URLProviders/ATTNCreativeUrlProvider.swift b/Sources/URLProviders/ATTNCreativeUrlProvider.swift index c7307ee..dad6c55 100644 --- a/Sources/URLProviders/ATTNCreativeUrlProvider.swift +++ b/Sources/URLProviders/ATTNCreativeUrlProvider.swift @@ -8,11 +8,7 @@ import Foundation protocol ATTNCreativeUrlProviding { - func buildCompanyCreativeUrl( - forDomain domain: String, - mode: String, - userIdentity: ATTNUserIdentity - ) -> String + func buildCompanyCreativeUrl(configuration: ATTNCreativeUrlConfig) -> String } struct ATTNCreativeUrlProvider: ATTNCreativeUrlProviding { @@ -28,47 +24,43 @@ struct ATTNCreativeUrlProvider: ATTNCreativeUrlProviding { self.appInfo = appInfo } - func buildCompanyCreativeUrl( - forDomain domain: String, - mode: String, - userIdentity: ATTNUserIdentity - ) -> String { + func buildCompanyCreativeUrl(configuration: ATTNCreativeUrlConfig) -> String { var components = URLComponents() components.scheme = Constants.scheme components.host = Constants.host components.path = Constants.path var queryItems = [ - URLQueryItem(name: "domain", value: domain) + URLQueryItem(name: "domain", value: configuration.domain) ] - if mode == "debug" { - queryItems.append(URLQueryItem(name: mode, value: "matter-trip-grass-symbol")) + if configuration.mode == "debug" { + queryItems.append(URLQueryItem(name: configuration.mode, value: "matter-trip-grass-symbol")) } - queryItems.append(URLQueryItem(name: "vid", value: userIdentity.visitorId)) + queryItems.append(URLQueryItem(name: "vid", value: configuration.userIdentity.visitorId)) - if let clientUserId = userIdentity.identifiers[ATTNIdentifierType.clientUserId] as? String { + if let clientUserId = configuration.userIdentity.identifiers[ATTNIdentifierType.clientUserId] as? String { queryItems.append(URLQueryItem(name: "cuid", value: clientUserId)) } - if let phone = userIdentity.identifiers[ATTNIdentifierType.phone] as? String { + if let phone = configuration.userIdentity.identifiers[ATTNIdentifierType.phone] as? String { queryItems.append(URLQueryItem(name: "p", value: phone)) } - if let email = userIdentity.identifiers[ATTNIdentifierType.email] as? String { + if let email = configuration.userIdentity.identifiers[ATTNIdentifierType.email] as? String { queryItems.append(URLQueryItem(name: "e", value: email)) } - if let klaviyoId = userIdentity.identifiers[ATTNIdentifierType.klaviyoId] as? String { + if let klaviyoId = configuration.userIdentity.identifiers[ATTNIdentifierType.klaviyoId] as? String { queryItems.append(URLQueryItem(name: "kid", value: klaviyoId)) } - if let shopifyId = userIdentity.identifiers[ATTNIdentifierType.shopifyId] as? String { + if let shopifyId = configuration.userIdentity.identifiers[ATTNIdentifierType.shopifyId] as? String { queryItems.append(URLQueryItem(name: "sid", value: shopifyId)) } - if let customIdentifiersJson = getCustomIdentifiersJson(userIdentity: userIdentity) { + if let customIdentifiersJson = getCustomIdentifiersJson(userIdentity: configuration.userIdentity) { queryItems.append(URLQueryItem(name: "cstm", value: customIdentifiersJson)) } @@ -76,6 +68,14 @@ struct ATTNCreativeUrlProvider: ATTNCreativeUrlProviding { queryItems.append(URLQueryItem(name: "sdkVersion", value: appInfo.getSdkVersion())) queryItems.append(URLQueryItem(name: "sdkName", value: appInfo.getSdkName())) + if configuration.skipFatigue { + queryItems.append(URLQueryItem(name: "skipFatigue", value: "true")) + } + + if let creativeId = configuration.creativeId { + queryItems.append(URLQueryItem(name: "attn_creative_id", value: creativeId)) + } + components.queryItems = queryItems return components.string ?? "" diff --git a/Sources/URLProviders/Configs/ATTNCreativeUrlConfig.swift b/Sources/URLProviders/Configs/ATTNCreativeUrlConfig.swift new file mode 100644 index 0000000..eab66c5 --- /dev/null +++ b/Sources/URLProviders/Configs/ATTNCreativeUrlConfig.swift @@ -0,0 +1,16 @@ +// +// ATTNCreativeUrlConfig.swift +// attentive-ios-sdk-framework +// +// Created by Vladimir - Work on 2024-06-14. +// + +import Foundation + +struct ATTNCreativeUrlConfig { + let domain: String + let creativeId: String? + let skipFatigue: Bool + let mode: String + let userIdentity: ATTNUserIdentity +} diff --git a/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift b/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift index eea8460..9791fed 100644 --- a/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift +++ b/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift @@ -12,9 +12,9 @@ final class ATTNCreativeUrlProviderSpy: ATTNCreativeUrlProviding { private(set) var buildCompanyCreativeUrlWasCalled = false private(set) var usedDomain: String? - func buildCompanyCreativeUrl(forDomain domain: String, mode: String, userIdentity: ATTNSDKFramework.ATTNUserIdentity) -> String { + func buildCompanyCreativeUrl(configuration: ATTNSDKFramework.ATTNCreativeUrlConfig) -> String { buildCompanyCreativeUrlWasCalled = true - usedDomain = domain + usedDomain = configuration.domain return "" } } diff --git a/Tests/TestCases/ATTNCreativeUrlFormatterTests.swift b/Tests/TestCases/ATTNCreativeUrlFormatterTests.swift index 40fd3fe..7834b7d 100644 --- a/Tests/TestCases/ATTNCreativeUrlFormatterTests.swift +++ b/Tests/TestCases/ATTNCreativeUrlFormatterTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import ATTNSDKFramework final class ATTNCreativeUrlFormatterTests: XCTestCase { - private let TEST_DOMAIN = "testDomain" + private let testDomain = "testDomain" private var sut: ATTNCreativeUrlProvider! private var appInfo: ATTNAppInfo! @@ -27,7 +27,15 @@ final class ATTNCreativeUrlFormatterTests: XCTestCase { func testBuildCompanyCreativeUrlForDomain_productionMode_buildsProdUrl() { let userIdentity = ATTNUserIdentity(identifiers: [:]) - let url = sut.buildCompanyCreativeUrl(forDomain: TEST_DOMAIN, mode: "production", userIdentity: userIdentity) + let config = ATTNCreativeUrlConfig( + domain: testDomain, + creativeId: nil, + skipFatigue: false, + mode: "production", + userIdentity: userIdentity + ) + + let url = sut.buildCompanyCreativeUrl(configuration: config) let expectedUrl = "https://creatives.attn.tv/mobile-apps/index.html?domain=testDomain&vid=\(userIdentity.visitorId)&sdkVersion=\(appInfo.getSdkVersion())&sdkName=attentive-ios-sdk" @@ -36,7 +44,15 @@ final class ATTNCreativeUrlFormatterTests: XCTestCase { func testBuildCompanyCreativeUrlForDomain_productionMode_buildsDebugUrl() { let userIdentity = ATTNUserIdentity(identifiers: [:]) - let url = sut.buildCompanyCreativeUrl(forDomain: TEST_DOMAIN, mode: "debug", userIdentity: userIdentity) + let config = ATTNCreativeUrlConfig( + domain: testDomain, + creativeId: nil, + skipFatigue: false, + mode: "debug", + userIdentity: userIdentity + ) + + let url = sut.buildCompanyCreativeUrl(configuration: config) let expectedUrl = "https://creatives.attn.tv/mobile-apps/index.html?domain=testDomain&debug=matter-trip-grass-symbol&vid=\(userIdentity.visitorId)&sdkVersion=\(appInfo.getSdkVersion())&sdkName=attentive-ios-sdk" @@ -45,7 +61,15 @@ final class ATTNCreativeUrlFormatterTests: XCTestCase { func testBuildCompanyCreativeUrlForDomain_withUserIdentifiers_buildsUrlWithIdentifierQueryParams() { let userIdentity = ATTNTestEventUtils.buildUserIdentity() - let url = sut.buildCompanyCreativeUrl(forDomain: TEST_DOMAIN, mode: "production", userIdentity: userIdentity) + let config = ATTNCreativeUrlConfig( + domain: testDomain, + creativeId: nil, + skipFatigue: false, + mode: "production", + userIdentity: userIdentity + ) + + let url = sut.buildCompanyCreativeUrl(configuration: config) let expectedUrl = "https://creatives.attn.tv/mobile-apps/index.html?domain=testDomain&vid=\(userIdentity.visitorId)&cuid=someClientUserId&p=+14156667777&e=someEmail@email.com&kid=someKlaviyoId&sid=someShopifyId&cstm=%7B%22customId%22:%22customIdValue%22%7D&sdkVersion=\(appInfo.getSdkVersion())&sdkName=attentive-ios-sdk" @@ -55,10 +79,54 @@ final class ATTNCreativeUrlFormatterTests: XCTestCase { func testBuildCompanyCreativeUrlForDomain_productionMode_buildsUrlWithSdkDetails() { let userIdentity = ATTNUserIdentity(identifiers: [:]) - let url = sut.buildCompanyCreativeUrl(forDomain: TEST_DOMAIN, mode: "production", userIdentity: userIdentity) + let config = ATTNCreativeUrlConfig( + domain: testDomain, + creativeId: nil, + skipFatigue: false, + mode: "production", + userIdentity: userIdentity + ) + + let url = sut.buildCompanyCreativeUrl(configuration: config) let expectedUrl = "https://creatives.attn.tv/mobile-apps/index.html?domain=testDomain&vid=\(userIdentity.visitorId)&sdkVersion=\(ATTNConstants.sdkVersion)&sdkName=attentive-ios-sdk" XCTAssertEqual(expectedUrl, url) } + + func testBuildCompanyCreativeUrlForDomain_withSkipFatigue_buildsUrlWithSkipFatigue() { + let userIdentity = ATTNUserIdentity(identifiers: [:]) + + let config = ATTNCreativeUrlConfig( + domain: testDomain, + creativeId: nil, + skipFatigue: true, + mode: "production", + userIdentity: userIdentity + ) + + let url = sut.buildCompanyCreativeUrl(configuration: config) + + let expectedUrl = "https://creatives.attn.tv/mobile-apps/index.html?domain=testDomain&vid=\(userIdentity.visitorId)&sdkVersion=\(ATTNConstants.sdkVersion)&sdkName=attentive-ios-sdk&skipFatigue=true" + + XCTAssertEqual(expectedUrl, url) + } + + func testBuildCompanyCreativeUrlForDomain_withCreativeId_buildsUrlWithCreativeId() { + let userIdentity = ATTNUserIdentity(identifiers: [:]) + + let config = ATTNCreativeUrlConfig( + domain: testDomain, + creativeId: "1234567", + skipFatigue: false, + mode: "production", + userIdentity: userIdentity + ) + + let url = sut.buildCompanyCreativeUrl(configuration: config) + + let expectedUrl = "https://creatives.attn.tv/mobile-apps/index.html?domain=testDomain&vid=\(userIdentity.visitorId)&sdkVersion=\(ATTNConstants.sdkVersion)&sdkName=attentive-ios-sdk&attn_creative_id=1234567" + + XCTAssertEqual(expectedUrl, url) + } } diff --git a/attentive-ios-sdk.xcodeproj/project.pbxproj b/attentive-ios-sdk.xcodeproj/project.pbxproj index 8a3d068..a162b08 100644 --- a/attentive-ios-sdk.xcodeproj/project.pbxproj +++ b/attentive-ios-sdk.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 58D52E1D292EC52B00CF32DE /* ATTNSDKFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58332EC3292EC18800B1ECF3 /* ATTNSDKFramework.framework */; }; FB080C712C1C755A00834BAA /* ATTNAPISpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB65536D2C1B7747008DB3B1 /* ATTNAPISpy.swift */; }; FB080C722C1C755F00834BAA /* ATTNCreativeUrlProviderSpy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB080C6F2C1C752E00834BAA /* ATTNCreativeUrlProviderSpy.swift */; }; + FB080C7F2C1CC9E500834BAA /* ATTNCreativeUrlConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB080C7E2C1CC9E500834BAA /* ATTNCreativeUrlConfig.swift */; }; FB2983E42C0F73990039759C /* ATTNAppInfoMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB2983D02C0F73990039759C /* ATTNAppInfoMock.swift */; }; FB2983E52C0F73990039759C /* ATTNUserAgentBuilderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB2983D12C0F73990039759C /* ATTNUserAgentBuilderMock.swift */; }; FB2983F42C0F759D0039759C /* ATTNVisitorServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB2983F32C0F759D0039759C /* ATTNVisitorServiceTests.swift */; }; @@ -108,6 +109,7 @@ 58B01AC4294D44140001CEBF /* OCMArg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMArg.h; sourceTree = ""; }; 58D52E19292EC52B00CF32DE /* attentive-ios-sdk Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "attentive-ios-sdk Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; FB080C6F2C1C752E00834BAA /* ATTNCreativeUrlProviderSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTNCreativeUrlProviderSpy.swift; sourceTree = ""; }; + FB080C7E2C1CC9E500834BAA /* ATTNCreativeUrlConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTNCreativeUrlConfig.swift; sourceTree = ""; }; FB0E49E52BFBB1900025E281 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; FB2983D02C0F73990039759C /* ATTNAppInfoMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ATTNAppInfoMock.swift; sourceTree = ""; }; FB2983D12C0F73990039759C /* ATTNUserAgentBuilderMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ATTNUserAgentBuilderMock.swift; sourceTree = ""; }; @@ -266,6 +268,14 @@ path = OCMock; sourceTree = ""; }; + FB080C7D2C1CC9C000834BAA /* Configs */ = { + isa = PBXGroup; + children = ( + FB080C7E2C1CC9E500834BAA /* ATTNCreativeUrlConfig.swift */, + ); + path = Configs; + sourceTree = ""; + }; FB2983D22C0F73990039759C /* Mocks */ = { isa = PBXGroup; children = ( @@ -335,6 +345,7 @@ FB60AF092C12119F00C61537 /* URLProviders */ = { isa = PBXGroup; children = ( + FB080C7D2C1CC9C000834BAA /* Configs */, FBA9F9EA2C0A77AB00C65024 /* ATTNCreativeUrlProvider.swift */, FB60AF0A2C1211C700C61537 /* ATTNEventURLProvider.swift */, ); @@ -602,6 +613,7 @@ FBA9FA122C0A77AB00C65024 /* ATTNCustomEvent.swift in Sources */, FB35C1992C0E5365009FA048 /* ATTNInfoEvent+Extension.swift in Sources */, FB35C1892C0E3AF8009FA048 /* ATTNExternalVendorTypes.swift in Sources */, + FB080C7F2C1CC9E500834BAA /* ATTNCreativeUrlConfig.swift in Sources */, FBA9FA092C0A77AB00C65024 /* ATTNAppInfo.swift in Sources */, FB35C1792C0E030E009FA048 /* ATTNCreativeTriggerStatus.swift in Sources */, FBA9FA1B2C0A77AB00C65024 /* ATTNSDKMode.swift in Sources */, diff --git a/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved b/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved index 893c9fc..f8cbe5b 100644 --- a/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,10 +1,10 @@ { - "originHash" : "62dc5f9606142e259275d938027b59c944959560f934dd2210d0e0cc4420a08d", + "originHash" : "6b3de92165125b4410ec54f34acb3ca6e0b8fc849f4bd109516c1eddb59f6bf0", "pins" : [ { "identity" : "attentive-ios-sdk", "kind" : "remoteSourceControl", - "location" : "https://github.com/attentive-mobile/attentive-ios-sdk", + "location" : "https://github.com/vespinola/attentive-ios-sdk.git", "state" : { "branch" : "main", "revision" : "16ea6c5924b6431d996f38d057b9a55e6639ed03" From b78d35fa56e4d392ca1798eb2f4cb395e6d4c999 Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Mon, 17 Jun 2024 11:58:24 -0400 Subject: [PATCH 2/8] added capability to set skip fatigue as an environment value --- Sources/ATTNConstants.swift | 3 ++ .../Helpers/Extension/ATTNSDK+Extension.swift | 22 ++++++++++++ .../Helpers/Extension/Boolean+Extension.swift | 14 ++++++++ .../Helpers/Extension/String+Extension.swift | 14 ++++++++ Sources/Public/SDK/ATTNSDK.swift | 10 +++--- .../ATTNCreativeUrlProvider.swift | 2 +- .../Spies/ATTNCreativeUrlProviderSpy.swift | 2 ++ Tests/Extensions/ProcessInfo+Extension.swift | 36 +++++++++++++++++++ Tests/TestCases/ATTNSDKTests.swift | 23 ++++++++++++ attentive-ios-sdk.xcodeproj/project.pbxproj | 24 +++++++++++++ .../xcshareddata/swiftpm/Package.resolved | 4 +-- 11 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 Sources/Helpers/Extension/ATTNSDK+Extension.swift create mode 100644 Sources/Helpers/Extension/Boolean+Extension.swift create mode 100644 Sources/Helpers/Extension/String+Extension.swift create mode 100644 Tests/Extensions/ProcessInfo+Extension.swift diff --git a/Sources/ATTNConstants.swift b/Sources/ATTNConstants.swift index 5722bae..3ad804d 100644 --- a/Sources/ATTNConstants.swift +++ b/Sources/ATTNConstants.swift @@ -8,5 +8,8 @@ import Foundation struct ATTNConstants { + private init() { } + static let sdkVersion = "0.6.0" + static let skipFatigueEnvKey = "SKIP_FATIGUE_ON_CREATIVE" } diff --git a/Sources/Helpers/Extension/ATTNSDK+Extension.swift b/Sources/Helpers/Extension/ATTNSDK+Extension.swift new file mode 100644 index 0000000..795b9a6 --- /dev/null +++ b/Sources/Helpers/Extension/ATTNSDK+Extension.swift @@ -0,0 +1,22 @@ +// +// ATTNSDK+Extension.swift +// attentive-ios-sdk-framework +// +// Created by Vladimir - Work on 2024-06-17. +// + +import Foundation + +extension ATTNSDK { + func send(event: ATTNEvent) { + api.send(event: event, userIdentity: userIdentity) + } + + func initializeSkipFatigueOnCreatives() { + if let skipFatigueValue = ProcessInfo.processInfo.environment[ATTNConstants.skipFatigueEnvKey] { + self.skipFatigueOnCreative = skipFatigueValue.booleanValue + } else { + self.skipFatigueOnCreative = false + } + } +} diff --git a/Sources/Helpers/Extension/Boolean+Extension.swift b/Sources/Helpers/Extension/Boolean+Extension.swift new file mode 100644 index 0000000..a529ec0 --- /dev/null +++ b/Sources/Helpers/Extension/Boolean+Extension.swift @@ -0,0 +1,14 @@ +// +// Boolean+Extension.swift +// attentive-ios-sdk-framework +// +// Created by Vladimir - Work on 2024-06-17. +// + +import Foundation + +extension Bool { + var stringValue: String { + self ? "true" : "false" + } +} diff --git a/Sources/Helpers/Extension/String+Extension.swift b/Sources/Helpers/Extension/String+Extension.swift new file mode 100644 index 0000000..6338da4 --- /dev/null +++ b/Sources/Helpers/Extension/String+Extension.swift @@ -0,0 +1,14 @@ +// +// String+Extension.swift +// attentive-ios-sdk-framework +// +// Created by Vladimir - Work on 2024-06-17. +// + +import Foundation + +extension String { + var booleanValue: Bool { + self == "true" + } +} diff --git a/Sources/Public/SDK/ATTNSDK.swift b/Sources/Public/SDK/ATTNSDK.swift index b6b5d72..cda725a 100644 --- a/Sources/Public/SDK/ATTNSDK.swift +++ b/Sources/Public/SDK/ATTNSDK.swift @@ -51,7 +51,8 @@ public final class ATTNSDK: NSObject { private var mode: ATTNSDKMode private var urlBuilder: ATTNCreativeUrlProviding = ATTNCreativeUrlProvider() - public var skipFatigueOnCreatives: Bool = false + /// Determins if fatigue rules are evaluated + public var skipFatigueOnCreative: Bool = false public init(domain: String, mode: ATTNSDKMode) { NSLog("init attentive_ios_sdk v%@", ATTNConstants.sdkVersion) @@ -64,6 +65,7 @@ public final class ATTNSDK: NSObject { super.init() self.sendInfoEvent() + self.initializeSkipFatigueOnCreatives() } @objc(initWithDomain:) @@ -153,7 +155,7 @@ fileprivate extension ATTNSDK { configuration: ATTNCreativeUrlConfig( domain: domain, creativeId: creativeId, - skipFatigue: skipFatigueOnCreatives, + skipFatigue: skipFatigueOnCreative, mode: mode.rawValue, userIdentity: userIdentity ) @@ -289,10 +291,6 @@ extension ATTNSDK: WKNavigationDelegate { // MARK: Internal Helpers extension ATTNSDK { - func send(event: ATTNEvent) { - api.send(event: event, userIdentity: userIdentity) - } - convenience init(domain: String, mode: ATTNSDKMode, urlBuilder: ATTNCreativeUrlProviding) { self.init(domain: domain, mode: mode) self.urlBuilder = urlBuilder diff --git a/Sources/URLProviders/ATTNCreativeUrlProvider.swift b/Sources/URLProviders/ATTNCreativeUrlProvider.swift index dad6c55..8c7f28c 100644 --- a/Sources/URLProviders/ATTNCreativeUrlProvider.swift +++ b/Sources/URLProviders/ATTNCreativeUrlProvider.swift @@ -69,7 +69,7 @@ struct ATTNCreativeUrlProvider: ATTNCreativeUrlProviding { queryItems.append(URLQueryItem(name: "sdkName", value: appInfo.getSdkName())) if configuration.skipFatigue { - queryItems.append(URLQueryItem(name: "skipFatigue", value: "true")) + queryItems.append(URLQueryItem(name: "skipFatigue", value: configuration.skipFatigue.stringValue)) } if let creativeId = configuration.creativeId { diff --git a/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift b/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift index 9791fed..9dfee68 100644 --- a/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift +++ b/Tests/Doubles/Spies/ATTNCreativeUrlProviderSpy.swift @@ -11,10 +11,12 @@ import Foundation final class ATTNCreativeUrlProviderSpy: ATTNCreativeUrlProviding { private(set) var buildCompanyCreativeUrlWasCalled = false private(set) var usedDomain: String? + private(set) var usedCreativeId: String? func buildCompanyCreativeUrl(configuration: ATTNSDKFramework.ATTNCreativeUrlConfig) -> String { buildCompanyCreativeUrlWasCalled = true usedDomain = configuration.domain + usedCreativeId = configuration.creativeId return "" } } diff --git a/Tests/Extensions/ProcessInfo+Extension.swift b/Tests/Extensions/ProcessInfo+Extension.swift new file mode 100644 index 0000000..a92704b --- /dev/null +++ b/Tests/Extensions/ProcessInfo+Extension.swift @@ -0,0 +1,36 @@ +// +// ProcessInfo+Extension.swift +// attentive-ios-sdk Tests +// +// Created by Vladimir - Work on 2024-06-17. +// + +import Foundation + +extension ProcessInfo { + private static func swizzleEnvironmentImplementation(needsReset: Bool = false) { + let originalSelector = #selector(getter: ProcessInfo.environment) + let swizzledSelector = #selector(getter: ProcessInfo.mock_environment) + + guard let originalMethod = class_getInstanceMethod(ProcessInfo.self, originalSelector), + let swizzledMethod = class_getInstanceMethod(ProcessInfo.self, swizzledSelector) else { return } + + if needsReset { + method_exchangeImplementations(swizzledMethod, originalMethod) + } else { + method_exchangeImplementations(originalMethod, swizzledMethod) + } + } + + @objc var mock_environment: [String: String] { + return ["SKIP_FATIGUE_ON_CREATIVE": "true"] + } + + static func swizzleEnvironment() { + self.swizzleEnvironmentImplementation() + } + + static func restoreOriginalEnvironment() { + self.swizzleEnvironmentImplementation(needsReset: true) + } +} diff --git a/Tests/TestCases/ATTNSDKTests.swift b/Tests/TestCases/ATTNSDKTests.swift index 151674b..24335f3 100644 --- a/Tests/TestCases/ATTNSDKTests.swift +++ b/Tests/TestCases/ATTNSDKTests.swift @@ -26,6 +26,8 @@ final class ATTNSDKTests: XCTestCase { override func tearDown() { ATTNEventTracker.destroy() + ProcessInfo.restoreOriginalEnvironment() + creativeUrlProviderSpy = nil sut = nil apiSpy = nil @@ -85,5 +87,26 @@ final class ATTNSDKTests: XCTestCase { XCTAssertEqual(sdk?.getDomain(), newDomain) } + + func testSkipFatigue_whenTrue_willUpdateUrl() { + let creativeId = "123456" + sut.skipFatigueOnCreative = true + + sut.trigger(UIView(), creativeId: creativeId, handler: nil) + + XCTAssertTrue(creativeUrlProviderSpy.buildCompanyCreativeUrlWasCalled) + XCTAssertEqual(creativeUrlProviderSpy.usedCreativeId, creativeId) + } + + func testSkipFatigue_whenEnvValueIsPassed_ShouldBeTrue() { + ProcessInfo.swizzleEnvironment() + let creativeId = "123456" + sut = ATTNSDK(api: apiSpy, urlBuilder: creativeUrlProviderSpy) + + sut.trigger(UIView(), creativeId: creativeId, handler: nil) + + XCTAssertTrue(creativeUrlProviderSpy.buildCompanyCreativeUrlWasCalled) + XCTAssertEqual(creativeUrlProviderSpy.usedCreativeId, creativeId) + } } diff --git a/attentive-ios-sdk.xcodeproj/project.pbxproj b/attentive-ios-sdk.xcodeproj/project.pbxproj index a162b08..7f277f7 100644 --- a/attentive-ios-sdk.xcodeproj/project.pbxproj +++ b/attentive-ios-sdk.xcodeproj/project.pbxproj @@ -43,6 +43,10 @@ FB35C1972C0E52F3009FA048 /* ATTNProductViewEvent+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB35C1962C0E52F3009FA048 /* ATTNProductViewEvent+Extension.swift */; }; FB35C1992C0E5365009FA048 /* ATTNInfoEvent+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB35C1982C0E5365009FA048 /* ATTNInfoEvent+Extension.swift */; }; FB35C19B2C0E53F9009FA048 /* ATTNCustomEvent+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB35C19A2C0E53F9009FA048 /* ATTNCustomEvent+Extension.swift */; }; + FB56D4DA2C208BAD00AF7530 /* ATTNSDK+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB56D4D92C208BAD00AF7530 /* ATTNSDK+Extension.swift */; }; + FB56D4DC2C208D6100AF7530 /* Boolean+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB56D4DB2C208D6100AF7530 /* Boolean+Extension.swift */; }; + FB56D4DE2C208DC100AF7530 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB56D4DD2C208DC100AF7530 /* String+Extension.swift */; }; + FB56D4E12C20925500AF7530 /* ProcessInfo+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB56D4E02C20925500AF7530 /* ProcessInfo+Extension.swift */; }; FB60AF0B2C1211C700C61537 /* ATTNEventURLProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB60AF0A2C1211C700C61537 /* ATTNEventURLProvider.swift */; }; FB65536A2C1B72D4008DB3B1 /* ATTNSDKTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB6553692C1B72D4008DB3B1 /* ATTNSDKTests.swift */; }; FB65536C2C1B74A9008DB3B1 /* ATTNAPIProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB65536B2C1B74A9008DB3B1 /* ATTNAPIProtocol.swift */; }; @@ -139,6 +143,10 @@ FB35C1962C0E52F3009FA048 /* ATTNProductViewEvent+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ATTNProductViewEvent+Extension.swift"; sourceTree = ""; }; FB35C1982C0E5365009FA048 /* ATTNInfoEvent+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ATTNInfoEvent+Extension.swift"; sourceTree = ""; }; FB35C19A2C0E53F9009FA048 /* ATTNCustomEvent+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ATTNCustomEvent+Extension.swift"; sourceTree = ""; }; + FB56D4D92C208BAD00AF7530 /* ATTNSDK+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ATTNSDK+Extension.swift"; sourceTree = ""; }; + FB56D4DB2C208D6100AF7530 /* Boolean+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Boolean+Extension.swift"; sourceTree = ""; }; + FB56D4DD2C208DC100AF7530 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; + FB56D4E02C20925500AF7530 /* ProcessInfo+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+Extension.swift"; sourceTree = ""; }; FB60AF0A2C1211C700C61537 /* ATTNEventURLProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTNEventURLProvider.swift; sourceTree = ""; }; FB6553692C1B72D4008DB3B1 /* ATTNSDKTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTNSDKTests.swift; sourceTree = ""; }; FB65536B2C1B74A9008DB3B1 /* ATTNAPIProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ATTNAPIProtocol.swift; sourceTree = ""; }; @@ -302,6 +310,7 @@ FB2983F22C0F75600039759C /* TestCases */, FB2983D32C0F73990039759C /* Doubles */, FB2984032C0F9D650039759C /* ATTNTestEventUtils.swift */, + FB56D4DF2C20923800AF7530 /* Extensions */, ); path = Tests; sourceTree = SOURCE_ROOT; @@ -342,6 +351,14 @@ path = Protocols; sourceTree = ""; }; + FB56D4DF2C20923800AF7530 /* Extensions */ = { + isa = PBXGroup; + children = ( + FB56D4E02C20925500AF7530 /* ProcessInfo+Extension.swift */, + ); + path = Extensions; + sourceTree = ""; + }; FB60AF092C12119F00C61537 /* URLProviders */ = { isa = PBXGroup; children = ( @@ -385,6 +402,8 @@ FBA9F9E82C0A77AB00C65024 /* Extension */ = { isa = PBXGroup; children = ( + FB56D4DD2C208DC100AF7530 /* String+Extension.swift */, + FB56D4DB2C208D6100AF7530 /* Boolean+Extension.swift */, FBA9F9E72C0A77AB00C65024 /* Dictionary+Extension.swift */, FB35C1822C0E1FD7009FA048 /* URLSession+Extension.swift */, FB35C18A2C0E3F27009FA048 /* ATTNEvent+Extension.swift */, @@ -394,6 +413,7 @@ FB35C1962C0E52F3009FA048 /* ATTNProductViewEvent+Extension.swift */, FB35C1982C0E5365009FA048 /* ATTNInfoEvent+Extension.swift */, FB35C19A2C0E53F9009FA048 /* ATTNCustomEvent+Extension.swift */, + FB56D4D92C208BAD00AF7530 /* ATTNSDK+Extension.swift */, ); path = Extension; sourceTree = ""; @@ -638,6 +658,8 @@ FBA9FA0D2C0A77AB00C65024 /* ATTNPersistentStorage.swift in Sources */, FBA9FA0B2C0A77AB00C65024 /* ATTNInfoEvent.swift in Sources */, FBA9FA0F2C0A77AB00C65024 /* ATTNVisitorService.swift in Sources */, + FB56D4DE2C208DC100AF7530 /* String+Extension.swift in Sources */, + FB56D4DA2C208BAD00AF7530 /* ATTNSDK+Extension.swift in Sources */, FBA9FA172C0A77AB00C65024 /* ATTNProductViewEvent.swift in Sources */, FB35C19B2C0E53F9009FA048 /* ATTNCustomEvent+Extension.swift in Sources */, FB35C1952C0E5292009FA048 /* ATTNAddToCartEvent+Extension.swift in Sources */, @@ -647,6 +669,7 @@ FBA9FA0A2C0A77AB00C65024 /* ATTNCreativeUrlProvider.swift in Sources */, FB65536C2C1B74A9008DB3B1 /* ATTNAPIProtocol.swift in Sources */, FB35C17D2C0E039E009FA048 /* ATTNConstants.swift in Sources */, + FB56D4DC2C208D6100AF7530 /* Boolean+Extension.swift in Sources */, FBA9FA082C0A77AB00C65024 /* Dictionary+Extension.swift in Sources */, FBA9FA152C0A77AB00C65024 /* ATTNOrder.swift in Sources */, FBA9FA1A2C0A77AB00C65024 /* ATTNSDK.swift in Sources */, @@ -659,6 +682,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + FB56D4E12C20925500AF7530 /* ProcessInfo+Extension.swift in Sources */, FB080C712C1C755A00834BAA /* ATTNAPISpy.swift in Sources */, FB90EF0B2C109CB4004DFC4A /* ATTNAPIITTests.swift in Sources */, FB90EF0F2C10A81E004DFC4A /* NSURLSessionMock.swift in Sources */, diff --git a/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved b/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved index f8cbe5b..893c9fc 100644 --- a/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/attentive-ios-sdk.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,10 +1,10 @@ { - "originHash" : "6b3de92165125b4410ec54f34acb3ca6e0b8fc849f4bd109516c1eddb59f6bf0", + "originHash" : "62dc5f9606142e259275d938027b59c944959560f934dd2210d0e0cc4420a08d", "pins" : [ { "identity" : "attentive-ios-sdk", "kind" : "remoteSourceControl", - "location" : "https://github.com/vespinola/attentive-ios-sdk.git", + "location" : "https://github.com/attentive-mobile/attentive-ios-sdk", "state" : { "branch" : "main", "revision" : "16ea6c5924b6431d996f38d057b9a55e6639ed03" From 2424190f912bff4231d11bf58f6ab7a8ca97f262 Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Mon, 17 Jun 2024 14:48:25 -0400 Subject: [PATCH 3/8] added one more signature for trigger to pass parentview and creative id --- Sources/Public/SDK/ATTNSDK.swift | 5 +++++ Tests/TestCases/ATTNSDKTests.swift | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/Public/SDK/ATTNSDK.swift b/Sources/Public/SDK/ATTNSDK.swift index cda725a..f33ee3c 100644 --- a/Sources/Public/SDK/ATTNSDK.swift +++ b/Sources/Public/SDK/ATTNSDK.swift @@ -96,6 +96,11 @@ public final class ATTNSDK: NSObject { launchCreative(parentView: view, handler: handler) } + @objc(trigger:creativeId:) + public func trigger(_ view: UIView, creativeId: String) { + launchCreative(parentView: view, creativeId: creativeId, handler: nil) + } + @objc(trigger:creativeId:handler:) public func trigger(_ view: UIView, creativeId: String, handler: ATTNCreativeTriggerCompletionHandler?) { launchCreative(parentView: view, creativeId: creativeId, handler: handler) diff --git a/Tests/TestCases/ATTNSDKTests.swift b/Tests/TestCases/ATTNSDKTests.swift index 24335f3..0e3c6b2 100644 --- a/Tests/TestCases/ATTNSDKTests.swift +++ b/Tests/TestCases/ATTNSDKTests.swift @@ -103,7 +103,7 @@ final class ATTNSDKTests: XCTestCase { let creativeId = "123456" sut = ATTNSDK(api: apiSpy, urlBuilder: creativeUrlProviderSpy) - sut.trigger(UIView(), creativeId: creativeId, handler: nil) + sut.trigger(UIView(), creativeId: creativeId) XCTAssertTrue(creativeUrlProviderSpy.buildCompanyCreativeUrlWasCalled) XCTAssertEqual(creativeUrlProviderSpy.usedCreativeId, creativeId) From 95a899c0cd0bfc80be1e5f3d79963a1f600af7f9 Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Mon, 17 Jun 2024 15:40:20 -0400 Subject: [PATCH 4/8] updated launch signature to accept extra env configs --- Example/CreativeUITest/CreativeUITest.swift | 4 +++- Example/CreativeUITest/Protocols/BaseXCTestCase.swift | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Example/CreativeUITest/CreativeUITest.swift b/Example/CreativeUITest/CreativeUITest.swift index 8af0c3f..0a1dc6c 100644 --- a/Example/CreativeUITest/CreativeUITest.swift +++ b/Example/CreativeUITest/CreativeUITest.swift @@ -26,7 +26,9 @@ final class CreativeUITest: XCTestCase, BaseXCTestCase { } func testLoadCreative_clickClose_closesCreative() { - launch(with: .production) + launch(with: .production, extras: [ + "SKIP_FATIGUE_ON_CREATIVE": "true" + ]) HomePage .tapOnPushMeToCreative() diff --git a/Example/CreativeUITest/Protocols/BaseXCTestCase.swift b/Example/CreativeUITest/Protocols/BaseXCTestCase.swift index 3b9f2c1..a9bc462 100644 --- a/Example/CreativeUITest/Protocols/BaseXCTestCase.swift +++ b/Example/CreativeUITest/Protocols/BaseXCTestCase.swift @@ -33,12 +33,21 @@ extension BaseXCTestCase { } func launch(with mode: Mode) { + launch(with: mode, extras: [:]) + } + + func launch(with mode: Mode, extras: [String: String] = [:]) { let app = XCUIApplication() app.launchEnvironment = [ "COM_ATTENTIVE_EXAMPLE_DOMAIN" : "mobileapps", "COM_ATTENTIVE_EXAMPLE_MODE" : mode.rawValue, "COM_ATTENTIVE_EXAMPLE_IS_UI_TEST" : "YES", ] + + if !extras.isEmpty { + app.launchEnvironment.merge(extras) { _, new in new } + } + app.launch() } From e468c4560b8c2144cdc9516f924898c4e675774c Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Mon, 17 Jun 2024 15:56:48 -0400 Subject: [PATCH 5/8] added missing objc keyboard to new property --- Sources/Public/SDK/ATTNSDK.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Public/SDK/ATTNSDK.swift b/Sources/Public/SDK/ATTNSDK.swift index f33ee3c..730fb14 100644 --- a/Sources/Public/SDK/ATTNSDK.swift +++ b/Sources/Public/SDK/ATTNSDK.swift @@ -52,7 +52,7 @@ public final class ATTNSDK: NSObject { private var urlBuilder: ATTNCreativeUrlProviding = ATTNCreativeUrlProvider() /// Determins if fatigue rules are evaluated - public var skipFatigueOnCreative: Bool = false + @objc public var skipFatigueOnCreative: Bool = false public init(domain: String, mode: ATTNSDKMode) { NSLog("init attentive_ios_sdk v%@", ATTNConstants.sdkVersion) From b77e2fb5ae10eb98020cbcf1b444e03afab5e09a Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Mon, 17 Jun 2024 16:12:06 -0400 Subject: [PATCH 6/8] updated README --- README.md | 18 ++++++++++++++++++ Sources/Public/SDK/ATTNSDK.swift | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 49f6718..3319a5b 100644 --- a/README.md +++ b/README.md @@ -242,6 +242,24 @@ ATTNSDK *sdk = [[ATTNSDK alloc] initWithDomain:@"domain"]; [sdk updateDomain: @"differentDomain"]; ``` +### Skip Fatique on Creative + +Determinates if fatigue rules evaluation will be skipped for Creative. Default value is `false`. + +#### Swift + +```swift +let sdk = ATTNSDK(domain: "domain") +sdk.skipFatigueOnCreative = true +``` + +#### Objective-C + +```objective-c +ATTNSDK *sdk = [[ATTNSDK alloc] initWithDomain:@"domain"]; +sdk.skipFatigueOnCreative = YES; +``` + ### Clear the current user If the user logs out then the current user identifiers should be deleted: diff --git a/Sources/Public/SDK/ATTNSDK.swift b/Sources/Public/SDK/ATTNSDK.swift index 730fb14..64ae80a 100644 --- a/Sources/Public/SDK/ATTNSDK.swift +++ b/Sources/Public/SDK/ATTNSDK.swift @@ -51,7 +51,7 @@ public final class ATTNSDK: NSObject { private var mode: ATTNSDKMode private var urlBuilder: ATTNCreativeUrlProviding = ATTNCreativeUrlProvider() - /// Determins if fatigue rules are evaluated + /// Determinates if fatigue rules evaluation will be skipped for Creative. Default value is false. @objc public var skipFatigueOnCreative: Bool = false public init(domain: String, mode: ATTNSDKMode) { From 2ebb1425cfbb31020bff379a2a24d048749f1093 Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Tue, 18 Jun 2024 09:15:43 -0400 Subject: [PATCH 7/8] included doc for skip fatique as an environment object --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3319a5b..f905393 100644 --- a/README.md +++ b/README.md @@ -260,6 +260,10 @@ ATTNSDK *sdk = [[ATTNSDK alloc] initWithDomain:@"domain"]; sdk.skipFatigueOnCreative = YES; ``` +Alternatively, `SKIP_FATIGUE_ON_CREATIVE` can be added as an environment value in the project scheme or even included in CI files. + +Environment value can be a string with value `"true"` or `"false"`. + ### Clear the current user If the user logs out then the current user identifiers should be deleted: From 368ae877166471a90444d9773ef3acb489b01d48 Mon Sep 17 00:00:00 2001 From: Vladimir Espinola Date: Tue, 18 Jun 2024 09:20:28 -0400 Subject: [PATCH 8/8] fixed typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f905393..e51d761 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ ATTNSDK *sdk = [[ATTNSDK alloc] initWithDomain:@"domain"]; [sdk updateDomain: @"differentDomain"]; ``` -### Skip Fatique on Creative +### Skip Fatigue on Creative Determinates if fatigue rules evaluation will be skipped for Creative. Default value is `false`.