From 2493e3d684d851f2e9aa168b54bc98d78d7023d9 Mon Sep 17 00:00:00 2001 From: Tuan Pham Date: Tue, 3 Sep 2024 11:32:09 -0500 Subject: [PATCH 1/4] chore(analytics): resolve swiftformat errors and warnings --- ...npointAnalyticsPlugin+ClientBehavior.swift | 24 ++++---- ...AWSPinpointAnalyticsPlugin+Configure.swift | 11 ++-- .../AWSPinpointAnalyticsPlugin+Options.swift | 10 +-- .../AWSPinpointAnalyticsPlugin+Reset.swift | 4 +- ...PinpointAnalyticsPluginConfiguration.swift | 24 ++++---- .../Constants/AnalyticsErrorConstants.swift | 2 +- .../PinpointEvent+AnalyticsEvent.swift | 6 +- ...WSPinpoint+AnalyticsErrorConvertible.swift | 2 +- .../Utils/AnalyticsErrorConvertible.swift | 2 +- .../Support/Utils/AnalyticsErrorHelper.swift | 2 +- ...nTimeError+AnalyticsErrorConvertible.swift | 4 +- ...alyticsPluginAmplifyVersionableTests.swift | 2 +- ...ntAnalyticsPluginClientBehaviorTests.swift | 14 ++--- ...inpointAnalyticsPluginConfigureTests.swift | 11 ++-- ...AWSPinpointAnalyticsPluginResetTests.swift | 2 +- .../AWSPinpointAnalyticsPluginTestBase.swift | 7 ++- ...uginAmplifyOutputsConfigurationTests.swift | 4 +- ...intAnalyticsPluginConfigurationTests.swift | 6 +- .../Mocks/MockAWSPinpoint+Analytics.swift | 61 ++++++++++--------- .../Mocks/MockAWSPinpoint+Targeting.swift | 23 +++---- .../Mocks/MockAWSPinpoint.swift | 10 +-- .../Mocks/MockNetworkMonitor.swift | 2 +- ...pointAnalyticsPluginIntegrationTests.swift | 53 ++++++++-------- .../AnalyticsStressTests.swift | 24 ++++---- 24 files changed, 162 insertions(+), 148 deletions(-) diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift index c2e168e217..364b94e344 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift @@ -10,8 +10,8 @@ import AWSPinpoint import Foundation @_spi(InternalAWSPinpoint) import InternalAWSPinpoint -extension AWSPinpointAnalyticsPlugin { - public func identifyUser(userId: String, userProfile: AnalyticsUserProfile?) { +public extension AWSPinpointAnalyticsPlugin { + func identifyUser(userId: String, userProfile: AnalyticsUserProfile?) { if !isEnabled { log.warn("Cannot identify user. Analytics is disabled. Call Amplify.Analytics.enable() to enable") return @@ -20,7 +20,7 @@ extension AWSPinpointAnalyticsPlugin { Task { var currentEndpointProfile = await pinpoint.currentEndpointProfile() currentEndpointProfile.addUserId(userId) - if let userProfile = userProfile { + if let userProfile { currentEndpointProfile.addUserProfile(userProfile) } do { @@ -33,7 +33,7 @@ extension AWSPinpointAnalyticsPlugin { } } - public func record(event: AnalyticsEvent) { + func record(event: AnalyticsEvent) { if !isEnabled { log.warn("Cannot record events. Analytics is disabled. Call Amplify.Analytics.enable() to enable") return @@ -55,12 +55,12 @@ extension AWSPinpointAnalyticsPlugin { } } - public func record(eventWithName eventName: String) { + func record(eventWithName eventName: String) { let event = BasicAnalyticsEvent(name: eventName) record(event: event) } - public func registerGlobalProperties(_ properties: [String: AnalyticsPropertyValue]) { + func registerGlobalProperties(_ properties: [String: AnalyticsPropertyValue]) { // TODO: check if there is a limit on total number of properties properties.forEach { key, _ in guard key.count >= 1, key.count <= 50 else { @@ -75,13 +75,13 @@ extension AWSPinpointAnalyticsPlugin { } } - public func unregisterGlobalProperties(_ keys: Set?) { + func unregisterGlobalProperties(_ keys: Set?) { Task { await unregisterGlobalProperties(keys) } } - public func flushEvents() { + func flushEvents() { if !isEnabled { log.warn("Cannot flushEvents. Analytics is disabled. Call Amplify.Analytics.enable() to enable") return @@ -105,18 +105,18 @@ extension AWSPinpointAnalyticsPlugin { } } - public func enable() { + func enable() { isEnabled = true } - public func disable() { + func disable() { isEnabled = false } /// Retrieve the escape hatch to perform actions directly on PinpointClient. /// /// - Returns: PinpointClientProtocol instance - public func getEscapeHatch() -> PinpointClientProtocol { + func getEscapeHatch() -> PinpointClientProtocol { pinpoint.pinpointClient } @@ -128,7 +128,7 @@ extension AWSPinpointAnalyticsPlugin { } private func unregisterGlobalProperties(_ keys: Set?) async { - guard let keys = keys else { + guard let keys else { for (key, value) in globalProperties { await pinpoint.removeGlobalProperty(value, forKey: key) } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift index 2acad0b80b..f8fd7e1ae8 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift @@ -11,7 +11,7 @@ import Foundation @_spi(InternalAWSPinpoint) import InternalAWSPinpoint import Network -extension AWSPinpointAnalyticsPlugin { +public extension AWSPinpointAnalyticsPlugin { /// Configures AWSPinpointAnalyticsPlugin with the specified configuration. /// /// This method will be invoked as part of the Amplify configuration flow. @@ -19,7 +19,7 @@ extension AWSPinpointAnalyticsPlugin { /// - Parameter configuration: The configuration specified for this plugin /// - Throws: /// - PluginError.pluginConfigurationError: If one of the configuration values is invalid or empty - public func configure(using configuration: Any?) throws { + func configure(using configuration: Any?) throws { let pluginConfiguration: AWSPinpointAnalyticsPluginConfiguration if let config = configuration as? AmplifyOutputsData { print(config) @@ -45,7 +45,7 @@ extension AWSPinpointAnalyticsPlugin { } /// Configure AWSPinpointAnalyticsPlugin programatically using AWSPinpointAnalyticsPluginConfiguration - public func configure(using configuration: AWSPinpointAnalyticsPluginConfiguration) throws { + func configure(using configuration: AWSPinpointAnalyticsPluginConfiguration) throws { let pinpoint = try AWSPinpointFactory.sharedPinpoint( appId: configuration.appId, region: configuration.region @@ -82,10 +82,11 @@ extension AWSPinpointAnalyticsPlugin { // MARK: Internal /// Internal configure method to set the properties of the plugin - func configure(pinpoint: AWSPinpointBehavior, + internal func configure(pinpoint: AWSPinpointBehavior, networkMonitor: NetworkMonitor, globalProperties: AtomicDictionary = [:], - isEnabled: Bool = true) { + isEnabled: Bool = true) + { self.pinpoint = pinpoint self.networkMonitor = networkMonitor self.globalProperties = globalProperties diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift index 9849e6e9f5..328ca4c92d 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift @@ -7,8 +7,8 @@ import Foundation -extension AWSPinpointAnalyticsPlugin { - public struct Options { +public extension AWSPinpointAnalyticsPlugin { + struct Options { static let defaultAutoFlushEventsInterval: TimeInterval = 60 static let defaultTrackAppSession = true @@ -17,13 +17,15 @@ extension AWSPinpointAnalyticsPlugin { #if os(macOS) public init(autoFlushEventsInterval: TimeInterval = 60, - trackAppSessions: Bool = true) { + trackAppSessions: Bool = true) + { self.autoFlushEventsInterval = autoFlushEventsInterval self.trackAppSessions = trackAppSessions } #else public init(autoFlushEventsInterval: TimeInterval = 60, - trackAppSessions: Bool = true) { + trackAppSessions: Bool = true) + { self.autoFlushEventsInterval = autoFlushEventsInterval self.trackAppSessions = trackAppSessions } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Reset.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Reset.swift index c6e43f86da..3c2c0dc32f 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Reset.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Reset.swift @@ -9,9 +9,9 @@ import Amplify import Foundation @_spi(InternalAWSPinpoint) import InternalAWSPinpoint -extension AWSPinpointAnalyticsPlugin { +public extension AWSPinpointAnalyticsPlugin { /// Resets the state of the plugin - public func reset() async { + func reset() async { if pinpoint != nil { pinpoint = nil } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift index 44456d7c60..c0a8fd7a57 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift @@ -6,8 +6,8 @@ // @_spi(InternalAmplifyConfiguration) import Amplify -import AWSPinpoint import AWSClientRuntime +import AWSPinpoint import Foundation @_spi(InternalAWSPinpoint) import InternalAWSPinpoint @@ -54,20 +54,20 @@ public struct AWSPinpointAnalyticsPluginConfiguration { let pluginConfiguration = try AWSPinpointPluginConfiguration(pinpointAnalyticsConfig) - let configOptions: AWSPinpointAnalyticsPlugin.Options - if let options { - configOptions = options + let configOptions: AWSPinpointAnalyticsPlugin.Options = if let options { + options } else { - configOptions = .init( - autoFlushEventsInterval: try Self.getAutoFlushEventsInterval(configObject), - trackAppSessions: try Self.getTrackAppSessions(configObject)) + try .init( + autoFlushEventsInterval: Self.getAutoFlushEventsInterval(configObject), + trackAppSessions: Self.getTrackAppSessions(configObject)) } let autoSessionTrackingInterval = try Self.getAutoSessionTrackingInterval(configObject) // Warn users in case they set different regions between pinpointTargeting and pinpointAnalytics if let pinpointTargetingJson = configObject[Self.pinpointTargetingConfigKey], let pinpointTargetingConfig = try? AWSPinpointPluginConfiguration(pinpointTargetingJson), - pinpointTargetingConfig.region != pluginConfiguration.region { + pinpointTargetingConfig.region != pluginConfiguration.region + { Self.logger.warn("Having different regions for Analytics and Targeting operations is not supported. The Analytics region will be used.") } @@ -78,7 +78,8 @@ public struct AWSPinpointAnalyticsPluginConfiguration { } init(_ configuration: AmplifyOutputsData, - options: AWSPinpointAnalyticsPlugin.Options) throws { + options: AWSPinpointAnalyticsPlugin.Options) throws + { guard let analyticsConfig = configuration.analytics else { throw PluginError.pluginConfigurationError( AnalyticsPluginErrorConstant.missingAnalyticsCategoryConfiguration.errorDescription, @@ -102,7 +103,8 @@ public struct AWSPinpointAnalyticsPluginConfiguration { init(appId: String, region: String, autoSessionTrackingInterval: TimeInterval, - options: AWSPinpointAnalyticsPlugin.Options) { + options: AWSPinpointAnalyticsPlugin.Options) + { self.appId = appId self.region = region self.autoSessionTrackingInterval = autoSessionTrackingInterval @@ -148,7 +150,7 @@ public struct AWSPinpointAnalyticsPluginConfiguration { private static func getAutoSessionTrackingInterval(_ configuration: [String: JSONValue]) throws -> TimeInterval { guard let autoSessionTrackingInterval = configuration[autoSessionTrackingIntervalKey] else { - return Self.defaultAutoSessionTrackingInterval + return defaultAutoSessionTrackingInterval } guard case let .number(autoSessionTrackingIntervalValue) = autoSessionTrackingInterval else { diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Constants/AnalyticsErrorConstants.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Constants/AnalyticsErrorConstants.swift index 2ea40f5eb7..49cc32f2ba 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Constants/AnalyticsErrorConstants.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Constants/AnalyticsErrorConstants.swift @@ -10,7 +10,7 @@ import Foundation typealias AnalyticsPluginErrorString = (errorDescription: ErrorDescription, recoverySuggestion: RecoverySuggestion) -struct AnalyticsPluginErrorConstant { +enum AnalyticsPluginErrorConstant { static let decodeConfigurationError: AnalyticsPluginErrorString = ( "Unable to decode configuration", "Make sure the plugin configuration is JSONValue" diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift index bc51eec63c..0507d81ec5 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift @@ -9,8 +9,8 @@ import Amplify import Foundation @_spi(InternalAWSPinpoint) import InternalAWSPinpoint -extension PinpointEvent { - public func asAnalyticsEvent() -> AnalyticsEvent { +public extension PinpointEvent { + func asAnalyticsEvent() -> AnalyticsEvent { var properties: AnalyticsProperties = [:] for attribute in attributes { @@ -26,7 +26,7 @@ extension PinpointEvent { } } -extension Array where Element == PinpointEvent { +extension [PinpointEvent] { func asAnalyticsEventArray() -> [AnalyticsEvent] { map { $0.asAnalyticsEvent() } } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AWSPinpoint+AnalyticsErrorConvertible.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AWSPinpoint+AnalyticsErrorConvertible.swift index 42c5464f9e..d042e981cb 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AWSPinpoint+AnalyticsErrorConvertible.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AWSPinpoint+AnalyticsErrorConvertible.swift @@ -5,10 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import Amplify import AWSPinpoint import ClientRuntime +import Foundation extension AWSPinpoint.BadRequestException: AnalyticsErrorConvertible { var analyticsError: AnalyticsError { diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorConvertible.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorConvertible.swift index e21c889309..d422e9a13e 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorConvertible.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorConvertible.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import Amplify +import Foundation protocol AnalyticsErrorConvertible { var analyticsError: AnalyticsError { get } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorHelper.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorHelper.swift index da6a74fe7b..93167a2d8a 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorHelper.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/AnalyticsErrorHelper.swift @@ -5,9 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import Amplify import AwsCommonRuntimeKit +import Foundation enum AnalyticsErrorHelper { static func getDefaultError(_ error: Error) -> AnalyticsError { diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/CommonRunTimeError+AnalyticsErrorConvertible.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/CommonRunTimeError+AnalyticsErrorConvertible.swift index b65918f472..07784736d3 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/CommonRunTimeError+AnalyticsErrorConvertible.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Utils/CommonRunTimeError+AnalyticsErrorConvertible.swift @@ -5,10 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import Amplify -@_spi(InternalAWSPinpoint) import InternalAWSPinpoint import AwsCommonRuntimeKit +import Foundation +@_spi(InternalAWSPinpoint) import InternalAWSPinpoint extension CommonRunTimeError: AnalyticsErrorConvertible { var analyticsError: AnalyticsError { diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginAmplifyVersionableTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginAmplifyVersionableTests.swift index e9922169db..cdbb482f27 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginAmplifyVersionableTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginAmplifyVersionableTests.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest import AWSPinpointAnalyticsPlugin +import XCTest // swiftlint:disable:next type_name class AWSPinpointAnalyticsPluginAmplifyVersionableTests: XCTestCase { diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift index 92c4636fd3..bc462b9ec4 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift @@ -7,10 +7,10 @@ import Amplify import AWSPinpoint -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -@testable import AWSPinpointAnalyticsPlugin -@testable import AmplifyTestCommon import XCTest +@testable import AmplifyTestCommon +@testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint // swiftlint:disable:next type_name class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginTestBase { @@ -281,9 +281,9 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT func testRegisterGlobalProperties() async { mockPinpoint.addGlobalPropertyExpectation = expectation(description: "Add global property called") mockPinpoint.addGlobalPropertyExpectation?.expectedFulfillmentCount = testProperties.count - + analyticsPlugin.registerGlobalProperties(testProperties) - + await fulfillment(of: [mockPinpoint.addGlobalPropertyExpectation!], timeout: 1) XCTAssertEqual(analyticsPlugin.globalProperties.count, testProperties.count) XCTAssertTrue(mockPinpoint.addGlobalMetricCalled > 0) @@ -310,7 +310,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT func testUnregisterGlobalProperties() async { mockPinpoint.removeGlobalPropertyExpectation = expectation(description: "Remove global property called") mockPinpoint.removeGlobalPropertyExpectation?.expectedFulfillmentCount = testProperties.count - + analyticsPlugin.globalProperties = AtomicDictionary(initialValue: testProperties) analyticsPlugin.unregisterGlobalProperties(Set(testProperties.keys)) @@ -365,7 +365,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 1) mockPinpoint.verifySubmitEvents() } - + /// Given: The device does not have internet access /// When: AnalyticsPlugin.flushEvents is invoked /// Then: AWSPinpoint.submitEvents is invoked diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift index 4c14742004..4b84e729c7 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift @@ -5,19 +5,19 @@ // SPDX-License-Identifier: Apache-2.0 // +import XCTest @testable @_spi(InternalAmplifyConfiguration) import Amplify @testable import AmplifyTestCommon -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint @testable import AWSPinpointAnalyticsPlugin -import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class AWSPinpointAnalyticsPluginConfigureTests: AWSPinpointAnalyticsPluginTestBase { - + override func setUp() async throws { AWSPinpointFactory.credentialsProvider = MockCredentialsProvider() try await super.setUp() } - + // MARK: Plugin Key test func testPluginKey() { @@ -115,7 +115,8 @@ class AWSPinpointAnalyticsPluginConfigureTests: AWSPinpointAnalyticsPluginTestBa XCTFail("Analytics configuration should not succeed") } catch { guard let pluginError = error as? PluginError, - case .pluginConfigurationError = pluginError else { + case .pluginConfigurationError = pluginError + else { XCTFail("Should throw invalidConfiguration exception. But received \(error) ") return } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginResetTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginResetTests.swift index a5338f8e5e..b2e8be43be 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginResetTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginResetTests.swift @@ -7,8 +7,8 @@ import Amplify @_spi(InternalAWSPinpoint) import InternalAWSPinpoint -@testable import AWSPinpointAnalyticsPlugin import XCTest +@testable import AWSPinpointAnalyticsPlugin class AWSPinpointAnalyticsPluginResetTests: AWSPinpointAnalyticsPluginTestBase { func testReset() async { diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift index 6e637db34a..bd4ae217f8 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift @@ -5,11 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 // +import XCTest @testable import Amplify @testable import AmplifyTestCommon -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint @testable import AWSPinpointAnalyticsPlugin -import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class AWSPinpointAnalyticsPluginTestBase: XCTestCase { var analyticsPlugin: AWSPinpointAnalyticsPlugin! @@ -24,7 +24,8 @@ class AWSPinpointAnalyticsPluginTestBase: XCTestCase { var plugin: HubCategoryPlugin { guard let plugin = try? Amplify.Hub.getPlugin(for: "awsHubPlugin"), - plugin.key == "awsHubPlugin" else { + plugin.key == "awsHubPlugin" + else { fatalError("Could not access awsHubPlugin") } return plugin diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift index e4aeffa943..c624344118 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift @@ -5,10 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 // -@testable @_spi(InternalAmplifyConfiguration) import Amplify import XCTest -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint +@testable @_spi(InternalAmplifyConfiguration) import Amplify @testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint // swiftlint:disable:next type_name class AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests: XCTestCase { diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift index f7b8f7216f..947f3e920d 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift @@ -7,8 +7,8 @@ import Amplify import XCTest -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint @testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint // swiftlint:disable:next type_name class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { @@ -52,7 +52,7 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTFail("Failed to instantiate analytics plugin configuration") } } - + func testConfigureSuccess_withoutTargetingConfiguration() throws { let analyticsPluginConfig = JSONValue( dictionaryLiteral: @@ -190,7 +190,7 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { } func testConfigureThrowsErrorForMissingPinpointAnalyticsConfiguration() { - + let analyticsPluginConfig = JSONValue( dictionaryLiteral: (AWSPinpointAnalyticsPluginConfiguration.regionConfigKey, region) diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift index 9466403f55..67ce6261a7 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift @@ -7,13 +7,13 @@ import Amplify import AWSPinpoint -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -@testable import AWSPinpointAnalyticsPlugin import Foundation import StoreKit +@testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -extension MockAWSPinpoint { - public func addGlobalProperty(_ value: AnalyticsPropertyValue, forKey: String) { +public extension MockAWSPinpoint { + func addGlobalProperty(_ value: AnalyticsPropertyValue, forKey: String) { if let value = value as? String { addGlobalAttribute(value, forKey: forKey) } else if let value = value as? Int { @@ -26,7 +26,7 @@ extension MockAWSPinpoint { addGlobalPropertyExpectation?.fulfill() } - public func removeGlobalProperty(_ value: AnalyticsPropertyValue, forKey: String) { + func removeGlobalProperty(_ value: AnalyticsPropertyValue, forKey: String) { if value is String || value is Bool { removeGlobalAttribute(forKey: forKey) } else if value is Int || value is Double { @@ -35,14 +35,14 @@ extension MockAWSPinpoint { removeGlobalPropertyExpectation?.fulfill() } - public func addGlobalAttribute(_ theValue: String, forKey theKey: String) { + func addGlobalAttribute(_ theValue: String, forKey theKey: String) { addGlobalAttributeCalled += 1 addGlobalAttributeValue = theValue addGlobalAttributeKey = theKey } - public func addGlobalAttribute(_ theValue: String, forKey theKey: String, forEventType theEventType: String) { + func addGlobalAttribute(_ theValue: String, forKey theKey: String, forEventType theEventType: String) { addGlobalAttributeCalled += 1 addGlobalAttributeValue = theValue @@ -50,14 +50,14 @@ extension MockAWSPinpoint { addGlobalAttributeEventType = theEventType } - public func addGlobalMetric(_ theValue: Double, forKey theKey: String) { + func addGlobalMetric(_ theValue: Double, forKey theKey: String) { addGlobalMetricCalled += 1 addGlobalMetricValue = theValue addGlobalMetricKey = theKey } - public func addGlobalMetric(_ theValue: Double, forKey theKey: String, forEventType theEventType: String) { + func addGlobalMetric(_ theValue: Double, forKey theKey: String, forEventType theEventType: String) { addGlobalMetricCalled += 1 addGlobalMetricValue = theValue @@ -65,30 +65,30 @@ extension MockAWSPinpoint { addGlobalMetricEventType = theEventType } - public func removeGlobalAttribute(forKey theKey: String) { + func removeGlobalAttribute(forKey theKey: String) { removeGlobalAttributeCalled += 1 removeGlobalAttributeKey = theKey } - public func removeGlobalAttribute(forKey theKey: String, forEventType theEventType: String) { + func removeGlobalAttribute(forKey theKey: String, forEventType theEventType: String) { removeGlobalAttributeCalled += 1 removeGlobalAttributeKey = theKey removeGlobalAttributeEventType = theEventType } - public func removeGlobalMetric(forKey theKey: String) { + func removeGlobalMetric(forKey theKey: String) { removeGlobalMetricCalled += 1 removeGlobalMetricKey = theKey } - public func removeGlobalMetric(forKey theKey: String, forEventType theEventType: String) { + func removeGlobalMetric(forKey theKey: String, forEventType theEventType: String) { removeGlobalMetricCalled += 1 removeGlobalMetricKey = theKey removeglobalMetricEventType = theEventType } - public func record(_ theEvent: PinpointEvent) async throws { + func record(_ theEvent: PinpointEvent) async throws { recordCalled += 1 recordEvent = theEvent @@ -97,15 +97,16 @@ extension MockAWSPinpoint { } } - public func createEvent(withEventType theEventType: String) -> PinpointEvent { + func createEvent(withEventType theEventType: String) -> PinpointEvent { createEventCalled += 1 createEventEventType = theEventType return createEventResult ?? createEmptyEvent() } - public func createAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) -> PinpointEvent { + func createAppleMonetizationEvent(with transaction: SKPaymentTransaction, + with product: SKProduct) -> PinpointEvent + { createAppleMonetizationEventCalled += 1 createAppleMonetizationEventTransaction = transaction createAppleMonetizationEventProduct = product @@ -113,10 +114,11 @@ extension MockAWSPinpoint { return createAppleMonetizationEventResult ?? createEmptyEvent() } - public func createVirtualMonetizationEvent(withProductId theProductId: String, + func createVirtualMonetizationEvent(withProductId theProductId: String, withItemPrice theItemPrice: Double, withQuantity theQuantity: Int, - withCurrency theCurrency: String) -> PinpointEvent { + withCurrency theCurrency: String) -> PinpointEvent + { createVirtualMonetizationEventCalled += 1 createVirtualMonetizationEventProductId = theProductId createVirtualMonetizationEventItemPrice = theItemPrice @@ -126,11 +128,11 @@ extension MockAWSPinpoint { return createVirtualMonetizationEventResult ?? createEmptyEvent() } - public func submitEvents() async throws { + func submitEvents() async throws { submitEventsCalled += 1 } - public func submitEvents() async throws -> [PinpointEvent] { + func submitEvents() async throws -> [PinpointEvent] { submitEventsCalled += 1 switch submitEventsResult { case .success(let result): @@ -146,17 +148,18 @@ extension MockAWSPinpoint { return PinpointEvent(eventType: "", session: PinpointSession(appId: "", uniqueId: "")) } - - public func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: AnalyticsClientBehaviour.SubmitResult?) { - + + func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, + onSubmit: AnalyticsClientBehaviour.SubmitResult?) + { + } - - public func startTrackingSessions(backgroundTimeout: TimeInterval) { - + + func startTrackingSessions(backgroundTimeout: TimeInterval) { + } - func setRemoteGlobalAttributes(_ attributes: [String : String]) async { + internal func setRemoteGlobalAttributes(_ attributes: [String: String]) async { } } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift index 429d2ffd8d..b6b7d9df2e 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift @@ -6,18 +6,18 @@ // import AWSPinpoint -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -@testable import AWSPinpointAnalyticsPlugin import Foundation +@testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -extension MockAWSPinpoint { - public func currentEndpointProfile() -> PinpointEndpointProfile { +public extension MockAWSPinpoint { + func currentEndpointProfile() -> PinpointEndpointProfile { currentEndpointProfileCalled += 1 return PinpointEndpointProfile(applicationId: applicationId, endpointId: endpointId) } - public func updateEndpointProfile() async throws { + func updateEndpointProfile() async throws { updateEndpointProfileCalled += 1 if case let .failure(error) = updateEndpointProfileResult { @@ -25,8 +25,9 @@ extension MockAWSPinpoint { } } - public func updateEndpoint(with endpointProfile: PinpointEndpointProfile, - source: AWSPinpointSource) async throws { + func updateEndpoint(with endpointProfile: PinpointEndpointProfile, + source: AWSPinpointSource) async throws + { updateEndpointProfileCalled += 1 updateEndpointProfileValue = endpointProfile @@ -35,27 +36,27 @@ extension MockAWSPinpoint { } } - public func addAttributes(_ attributes: [String], forKey key: String) { + func addAttributes(_ attributes: [String], forKey key: String) { addAttributeCalled += 1 addAttributeValue = attributes addAttributeKey = key } - public func removeAttributes(forKey key: String) { + func removeAttributes(forKey key: String) { removeAttributeCalled += 1 removeAttributeKey = key } - public func addMetric(_ metric: Double, forKey key: String) { + func addMetric(_ metric: Double, forKey key: String) { addMetricCalled += 1 addMetricValue = metric addMetricKey = key } - public func removeMetric(forKey theKey: String) { + func removeMetric(forKey theKey: String) { removeMetricCalled += 1 removeMetricKey = theKey diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift index 9c445fb449..e6985475da 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift @@ -10,8 +10,8 @@ import Foundation import StoreKit import XCTest -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint @testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class MockAWSPinpoint: AWSPinpointBehavior { let applicationId = "applicationId" @@ -81,7 +81,7 @@ class MockAWSPinpoint: AWSPinpointBehavior { var createAppleMonetizationEventResult: PinpointEvent? var createVirtualMonetizationEventResult: PinpointEvent? var submitEventsResult: Result<[PinpointEvent], Error>? - + var addGlobalPropertyExpectation: XCTestExpectation? var removeGlobalPropertyExpectation: XCTestExpectation? @@ -217,7 +217,8 @@ extension MockAWSPinpoint { } public func verifyCreateAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) { + with product: SKProduct) + { XCTAssertEqual(createAppleMonetizationEventCalled, 1) XCTAssertEqual(createAppleMonetizationEventTransaction, transaction) XCTAssertEqual(createAppleMonetizationEventProduct, product) @@ -226,7 +227,8 @@ extension MockAWSPinpoint { public func verifyCreateVirtualMonetizationEvent(withProductId theProductId: String, withItemPrice theItemPrice: Double, withQuantity theQuantity: Int, - withCurrency theCurrency: String) { + withCurrency theCurrency: String) + { XCTAssertEqual(createVirtualMonetizationEventCalled, 1) XCTAssertEqual(createVirtualMonetizationEventProductId, theProductId) XCTAssertEqual(createVirtualMonetizationEventItemPrice, theItemPrice) diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockNetworkMonitor.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockNetworkMonitor.swift index bcd1099b71..9298fcdd46 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockNetworkMonitor.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockNetworkMonitor.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -@testable import AWSPinpointAnalyticsPlugin import Foundation +@testable import AWSPinpointAnalyticsPlugin class MockNetworkMonitor: NetworkMonitor { var isOnline = true diff --git a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift index 3716620822..5673f02b48 100644 --- a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift @@ -5,14 +5,14 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest import AWSPinpoint +import XCTest -@testable import Amplify -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -@testable import AWSPinpointAnalyticsPlugin import AWSCognitoAuthPlugin import Network +@testable import Amplify +@testable import AWSPinpointAnalyticsPlugin +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint // swiftlint:disable:next type_name class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { @@ -20,7 +20,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { static let amplifyConfiguration = "testconfiguration/AWSPinpointAnalyticsPluginIntegrationTests-amplifyconfiguration" static let amplifyOutputs = "testconfiguration/AWSPinpointAnalyticsPluginIntegrationTests-amplify_outputs" static let analyticsPluginKey = "awsPinpointAnalyticsPlugin" - + var useGen2Configuration: Bool { ProcessInfo.processInfo.arguments.contains("GEN2") } @@ -118,7 +118,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + let flushEventsInvoked = expectation(description: "Flush events invoked") _ = Amplify.Hub.listen(to: .analytics, isIncluded: nil) { payload in if payload.eventName == HubPayload.EventName.Analytics.flushEvents { @@ -143,14 +143,14 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) Amplify.Analytics.flushEvents() await fulfillment(of: [flushEventsInvoked], timeout: TestCommonConstants.networkTimeout) } - + /// Given: Analytics plugin /// When: An analytics event is recorded and flushed after the plugin is enabled /// Then: Flush Hub event is received @@ -163,7 +163,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + let flushEventsInvoked = expectation(description: "Flush events invoked") _ = Amplify.Hub.listen(to: .analytics, isIncluded: nil) { payload in if payload.eventName == HubPayload.EventName.Analytics.flushEvents { @@ -176,7 +176,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { flushEventsInvoked.fulfill() } } - + Amplify.Analytics.disable() Amplify.Analytics.enable() @@ -191,14 +191,14 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) Amplify.Analytics.flushEvents() await fulfillment(of: [flushEventsInvoked], timeout: TestCommonConstants.networkTimeout) } - + /// Given: Analytics plugin /// When: An analytics event is recorded and flushed after the plugin is disabled /// Then: Flush Hub event is not received @@ -211,7 +211,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + let flushEventsInvoked = expectation(description: "Flush events invoked") _ = Amplify.Hub.listen(to: .analytics, isIncluded: nil) { payload in if payload.eventName == HubPayload.EventName.Analytics.flushEvents { @@ -219,9 +219,9 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } flushEventsInvoked.isInverted = true - + Amplify.Analytics.disable() - + let globalProperties = ["globalPropertyStringKey": "eventProperyStringValue", "globalPropertyIntKey": 123, "globalPropertyDoubleKey": 12.34, @@ -233,13 +233,13 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) Amplify.Analytics.flushEvents() await fulfillment(of: [flushEventsInvoked], timeout: TestCommonConstants.networkTimeout) } - + /// Given: Analytics plugin /// When: An analytics event is recorded and flushed with global properties registered /// Then: Flush Hub event is received with global properties @@ -253,7 +253,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + let flushEventsInvoked = expectation(description: "Flush events invoked") _ = Amplify.Hub.listen(to: .analytics, isIncluded: nil) { payload in if payload.eventName == HubPayload.EventName.Analytics.flushEvents { @@ -275,7 +275,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { flushEventsInvoked.fulfill() } } - + let globalProperties = ["globalPropertyStringKey": "GlobalProperyStringValue", "globalPropertyIntKey": 321, "globalPropertyDoubleKey": 43.21, @@ -287,7 +287,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) Amplify.Analytics.flushEvents() @@ -307,7 +307,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + let flushEventsInvoked = expectation(description: "Flush events invoked") _ = Amplify.Hub.listen(to: .analytics, isIncluded: nil) { payload in if payload.eventName == HubPayload.EventName.Analytics.flushEvents { @@ -329,7 +329,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { flushEventsInvoked.fulfill() } } - + let globalProperties = ["globalPropertyStringKey": "GlobalProperyStringValue", "globalPropertyIntKey": 321, "globalPropertyDoubleKey": 43.21, @@ -342,7 +342,7 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) Amplify.Analytics.flushEvents() @@ -358,11 +358,12 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } let awsPinpoint = pinpointAnalyticsPlugin.getEscapeHatch() XCTAssertNotNil(awsPinpoint) - } - + } + private func plugin() -> AWSPinpointAnalyticsPlugin { guard let plugin = try? Amplify.Analytics.getPlugin(for: "awsPinpointAnalyticsPlugin"), - let analyticsPlugin = plugin as? AWSPinpointAnalyticsPlugin else { + let analyticsPlugin = plugin as? AWSPinpointAnalyticsPlugin + else { fatalError("Unable to retrieve configuration") } diff --git a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift index 308dcfd1fb..168c4079ea 100644 --- a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift @@ -5,20 +5,20 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest import AWSPinpoint +import XCTest -@testable import Amplify -@testable import AWSPinpointAnalyticsPlugin import AWSCognitoAuthPlugin import Network +@testable import Amplify +@testable import AWSPinpointAnalyticsPlugin final class AnalyticsStressTests: XCTestCase { static let amplifyConfiguration = "testconfiguration/AWSAmplifyStressTests-amplifyconfiguration" static let analyticsPluginKey = "awsPinpointAnalyticsPlugin" let concurrencyLimit = 50 - + override func setUp() { do { let config = try TestConfigHelper.retrieveAmplifyConfiguration(forResource: Self.amplifyConfiguration) @@ -35,7 +35,7 @@ final class AnalyticsStressTests: XCTestCase { } // MARK: - Stress Tests - + /// - Given: Analytics plugin configured with valid configuration /// - When: 50 different events with 5 attributes are recorded simultaneously /// - Then: Operations are successful @@ -48,12 +48,12 @@ final class AnalyticsStressTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) - + let recordExpectation = expectation(description: "Records are successfully recorded") recordExpectation.expectedFulfillmentCount = concurrencyLimit - for eventNumber in 0...concurrencyLimit { + for eventNumber in 0 ... concurrencyLimit { let properties = ["eventPropertyStringKey1": "eventProperyStringValue1", "eventPropertyStringKey2": "eventProperyStringValue2", "eventPropertyStringKey3": "eventProperyStringValue3", @@ -66,7 +66,7 @@ final class AnalyticsStressTests: XCTestCase { await fulfillment(of: [recordExpectation], timeout: TestCommonConstants.networkTimeout) } - + /// - Given: Analytics plugin configured with valid configuration /// - When: 50 different events with 20 attributes are recorded simultaneously /// - Then: Operations are successful @@ -79,13 +79,13 @@ final class AnalyticsStressTests: XCTestCase { } } networkMonitor.start(queue: DispatchQueue(label: "AWSPinpointAnalyticsPluginIntergrationTests.NetworkMonitor")) - + await fulfillment(of: [onlineExpectation], timeout: TestCommonConstants.networkTimeout) - + let recordExpectation = expectation(description: "Records are successfully recorded") recordExpectation.expectedFulfillmentCount = concurrencyLimit - for eventNumber in 0...concurrencyLimit { + for eventNumber in 0 ... concurrencyLimit { Task { let properties = ["eventPropertyStringKey1": "eventProperyStringValue1", "eventPropertyStringKey2": "eventProperyStringValue2", From 4d60fa9f6a5a386d35f2c5119d50df30d67ae417 Mon Sep 17 00:00:00 2001 From: Tuan Pham Date: Tue, 3 Sep 2024 13:05:30 -0500 Subject: [PATCH 2/4] chore(analytics): resolve swiftformat errors and warnings --- .../Analytics/AnalyticsClient.swift | 43 ++++++++------- .../Analytics/EventRecorder.swift | 46 ++++++++-------- .../AnalyticsEventSQLStorage.swift | 13 ++--- .../LocalStorage/AnalyticsEventStorage.swift | 2 +- .../LocalStorage/PinpointEvent+Bindings.swift | 14 +++-- .../SQLiteLocalStorageAdapter.swift | 7 +-- .../PinpointEvent+PinpointClientTypes.swift | 4 +- .../Analytics/PinpointEvent.swift | 7 +-- .../AWSPinpointPluginConfiguration.swift | 11 ++-- .../Context/AWSPinpointFactory.swift | 3 +- .../PinpointContext+AWSPinpointBehavior.swift | 6 ++- .../Context/PinpointContext.swift | 52 +++++++++++-------- .../Endpoint/EndpointClient.swift | 23 ++++---- .../Endpoint/PinpointEndpointProfile.swift | 18 ++++--- ...mmonRunTimeError+isConnectivityError.swift | 2 +- .../Extensions/Date+Formatting.swift | 6 +-- .../PinpointClient+CredentialsProvider.swift | 2 +- .../SDKModels+AmplifyStringConvertible.swift | 4 +- .../ActivityTracking/ActivityTracker.swift | 7 +-- .../Session/PinpointSession.swift | 23 ++++---- .../Session/SessionClient.swift | 50 ++++++++++-------- .../AWSPinpointAnalyticsConstants.swift | 6 +-- .../Constants/AWSPinpointErrorConstants.swift | 2 +- .../Support/ModeledErrorDescribable.swift | 2 +- .../Support/Utils/AmplifyArchiver.swift | 2 +- .../Utils/AmplifyStringConvertible.swift | 3 +- .../Utils/AnalyticsPropertiesModel.swift | 4 +- .../Utils/PinpointRequestsRegistry.swift | 5 +- .../Utils/ProvisioningProfileReader.swift | 18 ++++--- .../Utils/RemoteNotificationsHelper.swift | 4 +- .../Support/Utils/RepeatingTimer.swift | 3 +- .../AWSPinpointFactoryTests.swift | 2 +- .../ActivityTrackerTests.swift | 10 ++-- .../AnalyticsClientTests.swift | 21 ++++---- .../AnalyticsEventStorageTests.swift | 20 +++---- ...pointAnalyticsKeychainMigrationTests.swift | 24 ++++----- .../EndpointClientTests.swift | 6 +-- .../EndpointInformationProviderTests.swift | 4 +- .../EventRecorderTests.swift | 20 +++---- .../Mocks/MockActivityTracker.swift | 4 +- .../Mocks/MockAnalyticsClient.swift | 4 +- .../Mocks/MockAnalyticsEventStorage.swift | 3 +- .../Mocks/MockArchiver.swift | 6 +-- .../Mocks/MockEndpointClient.swift | 4 +- .../Mocks/MockEventRecorder.swift | 4 +- .../Mocks/MockFileManager.swift | 3 +- .../Mocks/MockKeychainStore.swift | 4 +- .../Mocks/MockSQLiteLocalStorageAdapter.swift | 1 + .../Mocks/MockUserDefaults.swift | 2 +- .../PinpointRequestsRegistryTests.swift | 4 +- .../SQLiteLocalStorageAdapterTests.swift | 8 +-- .../SessionClientTests.swift | 8 +-- 52 files changed, 303 insertions(+), 251 deletions(-) diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift index c7db089487..808b5ad801 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift @@ -5,14 +5,14 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation -import StoreKit import Amplify import AWSPinpoint +import Foundation +import StoreKit @_spi(InternalAWSPinpoint) public protocol AnalyticsClientBehaviour: Actor { - typealias SubmitResult = ((Result<[PinpointEvent], Error>) -> Void) + typealias SubmitResult = (Result<[PinpointEvent], Error>) -> Void nonisolated var pinpointClient: PinpointClientProtocol { get } func addGlobalAttribute(_ attribute: String, forKey key: String) @@ -68,7 +68,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { private lazy var eventTypeMetrics: [String: PinpointEventMetrics] = [:] init(eventRecorder: AnalyticsEventRecording, - sessionProvider: @escaping SessionProvider) { + sessionProvider: @escaping SessionProvider) + { self.eventRecorder = eventRecorder self.sessionProvider = sessionProvider } @@ -79,7 +80,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { init(applicationId: String, pinpointClient: PinpointClientProtocol, endpointClient: EndpointClientBehaviour, - sessionProvider: @escaping SessionProvider) throws { + sessionProvider: @escaping SessionProvider) throws + { let dbAdapter = try SQLiteLocalStorageAdapter(prefixPath: Constants.eventRecorderStoragePathPrefix, databaseName: applicationId) let eventRecorder = try EventRecorder(appId: applicationId, @@ -92,7 +94,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { convenience init(applicationId: String, pinpointClient: PinpointClientProtocol, endpointClient: EndpointClientBehaviour, - sessionProvider: @escaping SessionProvider) throws { + sessionProvider: @escaping SessionProvider) throws + { let dbAdapter = try SQLiteLocalStorageAdapter(prefixPath: Constants.eventRecorderStoragePathPrefix, databaseName: applicationId) let eventRecorder = try EventRecorder(appId: applicationId, @@ -161,7 +164,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { // MARK: - Monetization events nonisolated func createAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) -> PinpointEvent { + with product: SKProduct) -> PinpointEvent + { let numberFormatter = NumberFormatter() numberFormatter.locale = product.priceLocale numberFormatter.numberStyle = .currency @@ -179,7 +183,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { nonisolated func createVirtualMonetizationEvent(withProductId productId: String, withItemPrice itemPrice: Double, withQuantity quantity: Int, - withCurrency currency: String) -> PinpointEvent { + withCurrency currency: String) -> PinpointEvent + { return createMonetizationEvent(withStore: Constants.PurchaseEvent.virtual, productId: productId, quantity: quantity, @@ -194,7 +199,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { currencyCode: String?, formattedItemPrice: String? = nil, priceLocale: Locale? = nil, - transactionId: String? = nil) -> PinpointEvent { + transactionId: String? = nil) -> PinpointEvent + { let monetizationEvent = PinpointEvent(eventType: Constants.PurchaseEvent.name, session: sessionProvider()) monetizationEvent.addAttribute(store, @@ -206,17 +212,17 @@ actor AnalyticsClient: AnalyticsClientBehaviour { monetizationEvent.addMetric(itemPrice, forKey: Constants.PurchaseEvent.Keys.itemPrice) - if let currencyCode = currencyCode { + if let currencyCode { monetizationEvent.addAttribute(currencyCode, forKey: Constants.PurchaseEvent.Keys.currency) } - if let formattedItemPrice = formattedItemPrice { + if let formattedItemPrice { monetizationEvent.addAttribute(formattedItemPrice, forKey: Constants.PurchaseEvent.Keys.priceFormatted) } - if let transactionId = transactionId { + if let transactionId { monetizationEvent.addAttribute(transactionId, forKey: Constants.PurchaseEvent.Keys.transactionId) } @@ -263,13 +269,14 @@ actor AnalyticsClient: AnalyticsClientBehaviour { func submitEvents() async throws -> [PinpointEvent] { return try await eventRecorder.submitAllEvents() } - + func update(_ session: PinpointSession) async throws { try await eventRecorder.update(session) } func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: SubmitResult?) { + onSubmit: SubmitResult?) + { guard automaticSubmitEventsInterval != interval else { let message = interval == .zero ? "disabled" : "set to \(interval) seconds" log.verbose("Automatic Submission of Events' interval is already \(message).") @@ -287,7 +294,7 @@ actor AnalyticsClient: AnalyticsClientBehaviour { automaticSubmitEventsTimer = RepeatingTimer.createRepeatingTimer( timeInterval: automaticSubmitEventsInterval, eventHandler: { [weak self] in - guard let self = self else { return } + guard let self else { return } Task { self.log.debug("AutoFlushTimer triggered, flushing events") do { @@ -313,13 +320,13 @@ extension AnalyticsClient: DefaultLogger { } extension AnalyticsClient { - private struct Constants { - struct PurchaseEvent { + private enum Constants { + enum PurchaseEvent { static let name = "_monetization.purchase" static let appleStore = "Apple" static let virtual = "Virtual" - struct Keys { + enum Keys { static let productId = "_product_id" static let quantity = "_quantity" static let itemPrice = "_item_price" diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift index 0291d2f412..060c36c2ef 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift @@ -7,9 +7,9 @@ import Amplify import AWSCognitoAuthPlugin +import enum AwsCommonRuntimeKit.CommonRunTimeError import AWSPinpoint import ClientRuntime -import enum AwsCommonRuntimeKit.CommonRunTimeError import Foundation /// AnalyticsEventRecording saves and submits pinpoint events @@ -28,7 +28,7 @@ protocol AnalyticsEventRecording: Actor { func updateAttributesOfEvents(ofType: String, withSessionId: PinpointSession.SessionId, setAttributes: [String: String]) throws - + /// Updates the session information of the events that match the same sessionId. /// - Parameter session: The session to update func update(_ session: PinpointSession) throws @@ -56,7 +56,8 @@ actor EventRecorder: AnalyticsEventRecording { init(appId: String, storage: AnalyticsEventStorage, pinpointClient: PinpointClientProtocol, - endpointClient: EndpointClientBehaviour) throws { + endpointClient: EndpointClientBehaviour) throws + { self.appId = appId self.storage = storage self.pinpointClient = pinpointClient @@ -76,7 +77,8 @@ actor EventRecorder: AnalyticsEventRecording { func updateAttributesOfEvents(ofType eventType: String, withSessionId sessionId: PinpointSession.SessionId, - setAttributes attributes: [String: String]) throws { + setAttributes attributes: [String: String]) throws + { try storage.updateEvents(ofType: eventType, withSessionId: sessionId, setAttributes: attributes) @@ -129,7 +131,8 @@ actor EventRecorder: AnalyticsEventRecording { } private func submit(pinpointEvents: [PinpointEvent], - endpointProfile: PinpointEndpointProfile) async throws { + endpointProfile: PinpointEndpointProfile) async throws + { var clientEvents = [String: PinpointClientTypes.Event]() var pinpointEventsById = [String: PinpointEvent]() for event in pinpointEvents { @@ -155,7 +158,7 @@ actor EventRecorder: AnalyticsEventRecording { throw AnalyticsError.unknown(errorMessage) } - let endpointResponseMap = results.compactMap { $0.value.endpointItemResponse } + let endpointResponseMap = results.compactMap(\.value.endpointItemResponse) for endpointResponse in endpointResponseMap { if HttpStatusCode.accepted.rawValue == endpointResponse.statusCode { log.verbose("EndpointProfile updated successfully.") @@ -164,12 +167,13 @@ actor EventRecorder: AnalyticsEventRecording { } } - let eventsResponseMap = results.compactMap { $0.value.eventsItemResponse } + let eventsResponseMap = results.compactMap(\.value.eventsItemResponse) for (eventId, eventResponse) in eventsResponseMap.flatMap({ $0 }) { guard let event = pinpointEventsById[eventId] else { continue } let responseMessage = eventResponse.message ?? "Unknown" if HttpStatusCode.accepted.rawValue == eventResponse.statusCode, - Constants.acceptedResponseMessage == responseMessage { + Constants.acceptedResponseMessage == responseMessage + { // On successful submission, add the event to the list of submitted events and delete it from the local storage log.verbose("Successful submit for event with id \(eventId)") submittedEvents.append(event) @@ -181,11 +185,10 @@ actor EventRecorder: AnalyticsEventRecording { } else { // On other failures, increment the event retry counter incrementEventRetry(eventId: eventId) - let retryMessage: String - if event.retryCount < Constants.maxNumberOfRetries { - retryMessage = "Event will be retried" + let retryMessage = if event.retryCount < Constants.maxNumberOfRetries { + "Event will be retried" } else { - retryMessage = "Event will be discarded because it exceeded its max retry attempts" + "Event will be discarded because it exceeded its max retry attempts" } log.verbose("Submit attempt #\(event.retryCount + 1) for event with id \(eventId) failed.") log.error("Unable to successfully deliver event with id \(eventId) to the server. \(retryMessage). Error: \(responseMessage)") @@ -328,7 +331,8 @@ actor EventRecorder: AnalyticsEventRecording { private func retry(times: Int = Constants.defaultNumberOfRetriesForStorageOperations, onErrorMessage: String, - _ closure: () throws -> Void) { + _ closure: () throws -> Void) + { do { try closure() } catch { @@ -357,30 +361,30 @@ extension EventRecorder: DefaultLogger { public static var log: Logger { Amplify.Logging.logger(forCategory: CategoryType.analytics.displayName, forNamespace: String(describing: self)) } - nonisolated public var log: Logger { + public nonisolated var log: Logger { Self.log } } extension EventRecorder { - private struct Constants { + private enum Constants { static let maxEventsSubmittedPerBatch = 100 - static let pinpointClientByteLimitDefault = 5 * 1024 * 1024 // 5MB - static let pinpointClientBatchRecordByteLimitDefault = 512 * 1024 // 0.5MB - static let pinpointClientBatchRecordByteLimitMax = 4 * 1024 * 1024 // 4MB + static let pinpointClientByteLimitDefault = 5 * 1_024 * 1_024 // 5MB + static let pinpointClientBatchRecordByteLimitDefault = 512 * 1_024 // 0.5MB + static let pinpointClientBatchRecordByteLimitMax = 4 * 1_024 * 1_024 // 4MB static let acceptedResponseMessage = "Accepted" static let defaultNumberOfRetriesForStorageOperations = 1 static let maxNumberOfRetries = 3 } } -private extension Array where Element == PinpointEvent { +private extension [PinpointEvent] { func numberOfPushNotificationsEvents() -> Int { - let pushNotificationsEvents = filter({ event in + let pushNotificationsEvents = filter { event in event.eventType.contains(".opened_notification") || event.eventType.contains(".received_foreground") || event.eventType.contains(".received_background") - }) + } return pushNotificationsEvents.count } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift index c0597a6e98..3a66abf700 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import Amplify +import Foundation import SQLite /// This is a temporary placeholder class to interface with the SQLiteLocalStorageAdapter @@ -103,7 +103,8 @@ class AnalyticsEventSQLStorage: AnalyticsEventStorage { func updateEvents(ofType eventType: String, withSessionId sessionId: PinpointSession.SessionId, - setAttributes attributes: [String: String]) throws { + setAttributes attributes: [String: String]) throws + { let updateStatement = """ UPDATE Event SET attributes = ? @@ -115,7 +116,7 @@ class AnalyticsEventSQLStorage: AnalyticsEventStorage { sessionId, eventType]) } - + func updateSession(_ session: PinpointSession) throws { let updateStatement = """ UPDATE Event @@ -226,15 +227,15 @@ class AnalyticsEventSQLStorage: AnalyticsEventStorage { } /// Check the disk usage limit of the local database. - /// If database is over the limit then delete all dirty events and oldest event + /// If database is over the limit then delete all dirty events and oldest event /// - Parameter limit: the size limit of the database in Byte unit func checkDiskSize(limit: Byte) throws { if dbAdapter.diskBytesUsed > limit { - try self.deleteDirtyEvents() + try deleteDirtyEvents() } if dbAdapter.diskBytesUsed > limit { - try self.deleteOldestEvent() + try deleteOldestEvent() } } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift index d5aea17167..e36b587d8f 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift @@ -29,7 +29,7 @@ protocol AnalyticsEventStorage { func updateEvents(ofType: String, withSessionId: PinpointSession.SessionId, setAttributes: [String: String]) throws - + /// Updates the session information of the events that match the same sessionId. /// - Parameter session: The session to update func updateSession(_ session: PinpointSession) throws diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift index 571d60b41d..ad1b43cd18 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift @@ -55,7 +55,8 @@ extension PinpointEvent { let dateFormatter = DateFormatter.iso8601Formatter guard let sessionId = element[EventPropertyIndex.sessionId] as? String, let startTimeString = element[EventPropertyIndex.sessionStartTime] as? String, - let startTime = dateFormatter.date(from: startTimeString) else { + let startTime = dateFormatter.date(from: startTimeString) + else { return nil } @@ -68,7 +69,8 @@ extension PinpointEvent { guard let eventType = element[EventPropertyIndex.eventType] as? String, let eventTimestampValue = element[EventPropertyIndex.eventTimestamp] as? String, - let timestamp = dateFormatter.date(from: eventTimestampValue) else { + let timestamp = dateFormatter.date(from: eventTimestampValue) + else { return nil } @@ -84,14 +86,16 @@ extension PinpointEvent { let pinpointEvent = PinpointEvent(id: eventId, eventType: eventType, eventDate: timestamp, session: session, retryCount: retryCount) if let attributes = element[EventPropertyIndex.attributes] as? Blob, - let decodedAttributes = try? archiver.decode(AnalyticsClient.PinpointEventAttributes.self, from: Data(attributes.bytes)) { + let decodedAttributes = try? archiver.decode(AnalyticsClient.PinpointEventAttributes.self, from: Data(attributes.bytes)) + { for (key, value) in decodedAttributes { pinpointEvent.addAttribute(value, forKey: key) } } if let metrics = element[EventPropertyIndex.metrics] as? Blob, - let decodedMetrics = try? archiver.decode(AnalyticsClient.PinpointEventMetrics.self, from: Data(metrics.bytes)) { + let decodedMetrics = try? archiver.decode(AnalyticsClient.PinpointEventMetrics.self, from: Data(metrics.bytes)) + { for (key, value) in decodedMetrics { pinpointEvent.addMetric(value, forKey: key) } @@ -100,7 +104,7 @@ extension PinpointEvent { return pinpointEvent } - struct EventPropertyIndex { + enum EventPropertyIndex { static let id = 0 static let attributes = 1 static let eventType = 2 diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift index ae32ef37fd..293fdfff1d 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift @@ -25,7 +25,8 @@ final class SQLiteLocalStorageAdapter: SQLStorageProtocol { /// - fileManager: A FileManagerBehaviour instance to interact with the disk. Defaults to FileManager.default init(prefixPath: String = "", databaseName: String, - fileManager: FileManagerBehaviour = FileManager.default) throws { + fileManager: FileManagerBehaviour = FileManager.default) throws + { let dbDirectoryPath = try Self.getTmpPath() .appendingPathComponent(prefixPath) var dbFilePath = dbDirectoryPath.appendingPathComponent(databaseName) @@ -77,7 +78,7 @@ final class SQLiteLocalStorageAdapter: SQLStorageProtocol { /// Create a SQL table /// - Parameter statement: SQL statement to create a table func createTable(_ statement: String) throws { - guard let connection = connection else { + guard let connection else { throw LocalStorageError.missingConnection } @@ -94,7 +95,7 @@ final class SQLiteLocalStorageAdapter: SQLStorageProtocol { /// - bindings: A collection of SQL bindings to prepare with the query statement /// - Returns: A SQL statement result from the query func executeQuery(_ statement: String, _ bindings: [Binding?]) throws -> Statement { - guard let connection = connection else { + guard let connection else { throw LocalStorageError.missingConnection } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent+PinpointClientTypes.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent+PinpointClientTypes.swift index e2c78b496e..ef39960ac0 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent+PinpointClientTypes.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent+PinpointClientTypes.swift @@ -7,12 +7,12 @@ import AWSPinpoint import AWSPluginsCore -import InternalAmplifyCredentials import Foundation +import InternalAmplifyCredentials extension PinpointEvent { private var clientTypeSession: PinpointClientTypes.Session? { - var sessionDuration: Int? = nil + var sessionDuration: Int? if let duration = session.duration { // If the session duration cannot be represented by Int, return a nil session instead. // This is extremely unlikely to happen since a session's stopTime is set when the app is closed diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift index a8296abaed..cb2f265033 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift @@ -17,14 +17,15 @@ public class PinpointEvent: AnalyticsPropertiesModel { let eventDate: Date let session: PinpointSession let retryCount: Int - private(set) public lazy var attributes: [String: String] = [:] - private(set) public lazy var metrics: [String: Double] = [:] + public private(set) lazy var attributes: [String: String] = [:] + public private(set) lazy var metrics: [String: Double] = [:] init(id: String = UUID().uuidString, eventType: String, eventDate: Date = Date(), session: PinpointSession, - retryCount: Int = 0) { + retryCount: Int = 0) + { self.id = id self.eventType = eventType self.eventDate = eventDate diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift index 6c2969fa3d..e9d4b40392 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift @@ -6,8 +6,8 @@ // @_spi(InternalAmplifyConfiguration) import Amplify -import AWSPinpoint import AWSClientRuntime +import AWSPinpoint import Foundation @_spi(InternalAWSPinpoint) @@ -26,14 +26,15 @@ public struct AWSPinpointPluginConfiguration { ) } - self.init( - appId: try AWSPinpointPluginConfiguration.getAppId(configObject), - region: try AWSPinpointPluginConfiguration.getRegion(configObject) + try self.init( + appId: AWSPinpointPluginConfiguration.getAppId(configObject), + region: AWSPinpointPluginConfiguration.getRegion(configObject) ) } public init(appId: String, - region: String) { + region: String) + { self.appId = appId self.region = region } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift index 05f64ea9e1..7758531797 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift @@ -25,7 +25,8 @@ public class AWSPinpointFactory { static var provisioningProfileReader: ProvisioningProfileReader = .default public static func sharedPinpoint(appId: String, - region: String) throws -> AWSPinpointBehavior { + region: String) throws -> AWSPinpointBehavior + { let key = PinpointContextKey(appId: appId, region: region) if let existingContext = instances[key] { return existingContext diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift index 30fe00f951..7bdc888521 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift @@ -32,7 +32,8 @@ extension PinpointContext: AWSPinpointBehavior { } func updateEndpoint(with endpointProfile: PinpointEndpointProfile, - source: AWSPinpointSource) async throws { + source: AWSPinpointSource) async throws + { await PinpointRequestsRegistry.shared.registerSource(source, for: .updateEndpoint) try await endpointClient.updateEndpointProfile(with: endpointProfile) } @@ -62,7 +63,8 @@ extension PinpointContext: AWSPinpointBehavior { } func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: AnalyticsClientBehaviour.SubmitResult?) { + onSubmit: AnalyticsClientBehaviour.SubmitResult?) + { Task { await analyticsClient.setAutomaticSubmitEventsInterval(interval, onSubmit: onSubmit) } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift index 4267e99084..8c581b8886 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift @@ -56,7 +56,7 @@ extension FileManager: FileManagerBehaviour, DefaultLogger { func fileSize(for url: URL) -> Byte { do { - let attributes = try self.attributesOfItem(atPath: url.path) + let attributes = try attributesOfItem(atPath: url.path) return attributes[.size] as? Byte ?? 0 } catch { log.error("Error getting file size with error \(error)") @@ -84,7 +84,8 @@ struct PinpointContextConfiguration { init(appId: String, region: String, credentialsProvider: CredentialsProviding, - isDebug: Bool = false) { + isDebug: Bool = false) + { self.appId = appId self.region = region self.credentialsProvider = credentialsProvider @@ -115,18 +116,19 @@ class PinpointContext { keychainStore: KeychainStoreBehavior = KeychainStore(service: PinpointContext.Constants.Keychain.service), fileManager: FileManagerBehaviour = FileManager.default, archiver: AmplifyArchiverBehaviour = AmplifyArchiver(), - remoteNotificationsHelper: RemoteNotificationsBehaviour = .default) throws { + remoteNotificationsHelper: RemoteNotificationsBehaviour = .default) throws + { self.configuration = configuration - storage = PinpointContextStorage(userDefaults: userDefaults, + self.storage = PinpointContextStorage(userDefaults: userDefaults, keychainStore: keychainStore, fileManager: fileManager, archiver: archiver) - uniqueId = Self.retrieveUniqueId(applicationId: configuration.appId, storage: storage) + self.uniqueId = Self.retrieveUniqueId(applicationId: configuration.appId, storage: storage) let pinpointClient = try PinpointClient(region: configuration.region, credentialsProvider: configuration.credentialsProvider) - endpointClient = EndpointClient(configuration: .init(appId: configuration.appId, + self.endpointClient = EndpointClient(configuration: .init(appId: configuration.appId, uniqueDeviceId: uniqueId, isDebug: configuration.isDebug), pinpointClient: pinpointClient, @@ -135,20 +137,20 @@ class PinpointContext { keychain: keychainStore, remoteNotificationsHelper: remoteNotificationsHelper) - sessionClient = SessionClient(archiver: archiver, + self.sessionClient = SessionClient(archiver: archiver, configuration: .init(appId: configuration.appId, uniqueDeviceId: uniqueId), endpointClient: endpointClient, userDefaults: userDefaults) let sessionProvider: () -> PinpointSession = { [weak sessionClient] in - guard let sessionClient = sessionClient else { + guard let sessionClient else { fatalError("SessionClient was deallocated") } return sessionClient.currentSession } - analyticsClient = try AnalyticsClient(applicationId: configuration.appId, + self.analyticsClient = try AnalyticsClient(applicationId: configuration.appId, pinpointClient: pinpointClient, endpointClient: endpointClient, sessionProvider: sessionProvider) @@ -158,7 +160,8 @@ class PinpointContext { } private static func legacyPreferencesFilePath(applicationId: String, - storage: PinpointContextStorage) -> String? { + storage: PinpointContextStorage) -> String? + { let applicationSupportDirectoryUrls = storage.fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask) let preferencesFileUrl = applicationSupportDirectoryUrls.first? @@ -170,9 +173,11 @@ class PinpointContext { } private static func removeLegacyPreferencesFile(applicationId: String, - storage: PinpointContextStorage) { + storage: PinpointContextStorage) + { guard let preferencesPath = legacyPreferencesFilePath(applicationId: applicationId, - storage: storage) else { + storage: storage) + else { return } @@ -184,12 +189,14 @@ class PinpointContext { } private static func legacyUniqueId(applicationId: String, - storage: PinpointContextStorage) -> String? { + storage: PinpointContextStorage) -> String? + { guard let preferencesPath = legacyPreferencesFilePath(applicationId: applicationId, storage: storage), storage.fileManager.fileExists(atPath: preferencesPath), let preferencesJson = try? JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: preferencesPath)), - options: .mutableContainers) as? [String: String] else { + options: .mutableContainers) as? [String: String] + else { return nil } @@ -198,20 +205,21 @@ class PinpointContext { /** Attempts to retrieve a previously generated Device Unique ID. - + This value can be present in 3 places: 1. In a preferences file stored in disk 2. In UserDefauls 3. In the Keychain - + 1 and 2 are legacy storage options that are supportted for backwards compability, but once retrieved those values will be migrated to the Keychain. - + If no existing Device Unique ID is found, a new one will be generated and stored in the Keychain. - + - Returns: A string representing the Device Unique ID */ private static func retrieveUniqueId(applicationId: String, - storage: PinpointContextStorage) -> String { + storage: PinpointContextStorage) -> String + { // 1. Look for the UniqueId in the Keychain if let deviceUniqueId = try? storage.keychainStore._getString(Constants.Keychain.uniqueIdKey) { return deviceUniqueId @@ -282,15 +290,15 @@ extension PinpointContext: DefaultLogger { } extension PinpointContext { - struct Constants { + enum Constants { static let defaultAutomaticSubmissionInterval: TimeInterval = 60 - struct Preferences { + enum Preferences { static let mobileAnalyticsRoot = "com.amazonaws.MobileAnalytics" static let fileName = "preferences" static let uniqueIdKey = "UniqueId" } - struct Keychain { + enum Keychain { static let service = "com.amazonaws.AWSPinpointContext" static let uniqueIdKey = "com.amazonaws.AWSPinpointContextKeychainUniqueIdKey" } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift index e89118f4bb..492a0da55b 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift @@ -76,14 +76,15 @@ actor EndpointClient: EndpointClientBehaviour { private func retrieveOrCreateEndpointProfile() async -> PinpointEndpointProfile { // 1. Look for the local endpointProfile variable - if let endpointProfile = endpointProfile { + if let endpointProfile { return endpointProfile } // 2. Look for a valid PinpointEndpointProfile object stored locally. It needs to match the current applicationId, otherwise we'll discard it. if let endpointProfileData = Self.getStoredData(from: keychain, forKey: Constants.endpointProfileKey, fallbackTo: userDefaults), let decodedEndpointProfile = try? archiver.decode(PinpointEndpointProfile.self, from: endpointProfileData), - decodedEndpointProfile.applicationId == configuration.appId { + decodedEndpointProfile.applicationId == configuration.appId + { return await configure(endpointProfile: decodedEndpointProfile) } @@ -132,7 +133,8 @@ actor EndpointClient: EndpointClientBehaviour { private func updateStoredAPNsToken(from endpointProfile: PinpointEndpointProfile) { do { guard let deviceToken = endpointProfile.deviceToken, - let apnsToken = Data(hexString: deviceToken) else { + let apnsToken = Data(hexString: deviceToken) + else { try keychain._remove(Constants.deviceTokenKey) return } @@ -183,18 +185,18 @@ actor EndpointClient: EndpointClientBehaviour { return publicEndpoint } - nonisolated private func getChannelType(from endpointProfile: PinpointEndpointProfile) -> PinpointClientTypes.ChannelType? { + private nonisolated func getChannelType(from endpointProfile: PinpointEndpointProfile) -> PinpointClientTypes.ChannelType? { if endpointProfile.deviceToken == nil { return nil } return endpointProfile.isDebug ? .apnsSandbox : .apns } - nonisolated private func getEffectiveDateIso8601FractionalSeconds(from endpointProfile: PinpointEndpointProfile) -> String { + private nonisolated func getEffectiveDateIso8601FractionalSeconds(from endpointProfile: PinpointEndpointProfile) -> String { endpointProfile.effectiveDate.asISO8601String } - nonisolated private func getOptOut(from endpointProfile: PinpointEndpointProfile) -> String? { + private nonisolated func getOptOut(from endpointProfile: PinpointEndpointProfile) -> String? { if endpointProfile.deviceToken == nil { return nil } @@ -245,8 +247,8 @@ extension EndpointClient: DefaultLogger { } extension EndpointClient { - struct Constants { - struct OptOut { + enum Constants { + enum OptOut { static let all = "ALL" static let none = "NONE" } @@ -257,14 +259,15 @@ extension EndpointClient { } extension PinpointClientTypes.EndpointDemographic { - struct Constants { + enum Constants { static let appleMake = "apple" static let unknown = "Unknown" } init(device: EndpointInformation, locale: String = Locale.autoupdatingCurrent.identifier, - timezone: String = TimeZone.current.identifier) { + timezone: String = TimeZone.current.identifier) + { self.init(appVersion: device.appVersion, locale: locale, make: Constants.appleMake, diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift index c2d6cca523..88155d70d6 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift @@ -33,7 +33,8 @@ public struct PinpointEndpointProfile: Codable, Equatable { isOptOut: Bool = false, location: PinpointClientTypes.EndpointLocation = .init(), demographic: PinpointClientTypes.EndpointDemographic = .init(), - user: PinpointClientTypes.EndpointUser = .init()) { + user: PinpointClientTypes.EndpointUser = .init()) + { self.applicationId = applicationId self.endpointId = endpointId self.deviceToken = deviceToken @@ -80,14 +81,14 @@ public struct PinpointEndpointProfile: Codable, Equatable { } private mutating func addCustomProperties(_ properties: [String: UserProfilePropertyValue]?) { - guard let properties = properties else { return } + guard let properties else { return } for (key, value) in properties { setCustomProperty(value, forKey: key) } } private mutating func addUserAttributes(_ attributes: [String: [String]]?) { - guard let attributes = attributes else { return } + guard let attributes else { return } let userAttributes = user.userAttributes ?? [:] user.userAttributes = userAttributes.merging( attributes, @@ -96,7 +97,8 @@ public struct PinpointEndpointProfile: Codable, Equatable { } private mutating func setCustomProperty(_ value: UserProfilePropertyValue, - forKey key: String) { + forKey key: String) + { if let value = value as? String { attributes[key] = [value] } else if let values = value as? [String] { @@ -111,16 +113,16 @@ public struct PinpointEndpointProfile: Codable, Equatable { } } -extension Optional where Wrapped == PinpointEndpointProfile.DeviceToken { +extension PinpointEndpointProfile.DeviceToken? { var isNotEmpty: Bool { - guard let self = self else { return false } + guard let self else { return false } return !self.isEmpty } } extension PinpointEndpointProfile { - struct Constants { - struct AttributeKeys { + enum Constants { + enum AttributeKeys { static let email = "email" static let name = "name" static let plan = "plan" diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/CommonRunTimeError+isConnectivityError.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/CommonRunTimeError+isConnectivityError.swift index c3a3c3dd20..7e651b1f2d 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/CommonRunTimeError+isConnectivityError.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/CommonRunTimeError+isConnectivityError.swift @@ -6,8 +6,8 @@ // import Amplify -import AwsCIo import AwsCHttp +import AwsCIo import AwsCommonRuntimeKit import AWSPinpoint import ClientRuntime diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/Date+Formatting.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/Date+Formatting.swift index d1dfabbe31..3c31e11d38 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/Date+Formatting.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/Date+Formatting.swift @@ -29,7 +29,7 @@ extension Date { typealias Millisecond = Int64 var millisecondsSince1970: Millisecond { - return Int64(self.timeIntervalSince1970 * 1000) + return Int64(timeIntervalSince1970 * 1_000) } var asISO8601String: String { @@ -39,7 +39,7 @@ extension Date { extension Date.Millisecond { var asDate: Date { - return Date(timeIntervalSince1970: TimeInterval(self / 1000)) - .addingTimeInterval(TimeInterval(Double(self % 1000) / 1000 )) + return Date(timeIntervalSince1970: TimeInterval(self / 1_000)) + .addingTimeInterval(TimeInterval(Double(self % 1_000) / 1_000 )) } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/PinpointClient+CredentialsProvider.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/PinpointClient+CredentialsProvider.swift index 1d7a9d7cd9..7322ededbb 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/PinpointClient+CredentialsProvider.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/PinpointClient+CredentialsProvider.swift @@ -6,8 +6,8 @@ // import AWSClientRuntime -import AWSPluginsCore import AWSPinpoint +import AWSPluginsCore @_spi(PluginHTTPClientEngine) import InternalAmplifyCredentials extension PinpointClient { diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/SDKModels+AmplifyStringConvertible.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/SDKModels+AmplifyStringConvertible.swift index 3421574914..ad66c348fc 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/SDKModels+AmplifyStringConvertible.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Extensions/SDKModels+AmplifyStringConvertible.swift @@ -17,7 +17,7 @@ extension PutEventsOutput: AmplifyStringConvertible { public func encode(to encoder: Encoder) throws { var encodeContainer = encoder.container(keyedBy: CodingKeys.self) - if let eventsResponse = self.eventsResponse { + if let eventsResponse { try encodeContainer.encode(eventsResponse, forKey: .eventsResponse) } } @@ -32,7 +32,7 @@ extension UpdateEndpointOutput: AmplifyStringConvertible { public func encode(to encoder: Encoder) throws { var encodeContainer = encoder.container(keyedBy: CodingKeys.self) - if let messageBody = self.messageBody { + if let messageBody { try encodeContainer.encode(messageBody, forKey: .messageBody) } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift index d85da389d3..7b8fc44031 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift @@ -28,7 +28,7 @@ enum ApplicationState { case runningInBackground(isStale: Bool) case terminated - struct Resolver { + enum Resolver { static func resolve(currentState: ApplicationState, event: ActivityEvent) -> ApplicationState { if case .terminated = currentState { log.warn("Unexpected state transition. Received event \(event) in \(currentState) state.") @@ -123,7 +123,8 @@ class ActivityTracker: ActivityTrackerBehaviour { ] init(backgroundTrackingTimeout: TimeInterval = .infinity, - stateMachine: StateMachine? = nil) { + stateMachine: StateMachine? = nil) + { self.backgroundTrackingTimeout = backgroundTrackingTimeout self.stateMachine = stateMachine ?? StateMachine(initialState: .initializing, resolver: ApplicationState.Resolver.resolve(currentState:event:)) @@ -197,7 +198,7 @@ class ActivityTracker: ActivityTrackerBehaviour { #if canImport(UIKit) extension ActivityTracker { - struct Constants { + enum Constants { static let backgroundTask = "com.amazonaws.AWSPinpointSessionBackgroundTask" } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift index 3a43fc8bce..9a02da61c3 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift @@ -27,19 +27,21 @@ public struct PinpointSession: Codable { return stopTime } } - + private var state: State = .active init(appId: String, - uniqueId: String) { - sessionId = Self.generateSessionId(appId: appId, + uniqueId: String) + { + self.sessionId = Self.generateSessionId(appId: appId, uniqueId: uniqueId) - startTime = Date() + self.startTime = Date() } init(sessionId: SessionId, startTime: Date, - stopTime: Date?) { + stopTime: Date?) + { self.sessionId = sessionId self.startTime = startTime if let stopTime { @@ -54,7 +56,7 @@ public struct PinpointSession: Codable { return false } - + var isStopped: Bool { if case .stopped = state { return true @@ -84,7 +86,8 @@ public struct PinpointSession: Codable { } private static func generateSessionId(appId: String, - uniqueId: String) -> SessionId { + uniqueId: String) -> SessionId + { let now = Date() let dateFormatter = DateFormatter() dateFormatter.timeZone = TimeZone(abbreviation: Constants.Date.defaultTimezone) @@ -120,19 +123,19 @@ extension PinpointSession: Equatable { } extension PinpointSession { - struct Constants { + enum Constants { static let defaultSessionId = "00000000-00000000" static let maxAppKeyLength = 8 static let maxUniqueIdLength = 8 static let paddingChar = "_" - struct CodingKeys { + enum CodingKeys { static let sessionId = "sessionId" static let startTime = "startTime" static let stopTime = "stopTime" } - struct Date { + enum Date { static let defaultTimezone = "GMT" static let defaultLocale = "en_US" static let dateFormat = "yyyyMMdd" diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/SessionClient.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/SessionClient.swift index 6d1fb27a03..6a57c3fea6 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/SessionClient.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/SessionClient.swift @@ -43,14 +43,15 @@ class SessionClient: SessionClientBehaviour { archiver: AmplifyArchiverBehaviour, configuration: SessionClientConfiguration, endpointClient: EndpointClientBehaviour, - userDefaults: UserDefaultsBehaviour) { + userDefaults: UserDefaultsBehaviour) + { self.activityTracker = activityTracker self.analyticsClient = analyticsClient self.archiver = archiver self.configuration = configuration self.endpointClient = endpointClient self.userDefaults = userDefaults - session = Self.retrieveStoredSession(from: userDefaults, using: archiver) ?? .none + self.session = Self.retrieveStoredSession(from: userDefaults, using: archiver) ?? .none } var currentSession: PinpointSession { @@ -83,18 +84,20 @@ class SessionClient: SessionClientBehaviour { activityTracker.backgroundTrackingTimeout = backgroundTimeout activityTracker.beginActivityTracking { [weak self] newState in guard let self else { return } - self.log.verbose("New state received: \(newState)") - self.sessionClientQueue.sync(flags: .barrier) { + log.verbose("New state received: \(newState)") + sessionClientQueue.sync(flags: .barrier) { self.respond(to: newState) } } } private static func retrieveStoredSession(from userDefaults: UserDefaultsBehaviour, - using archiver: AmplifyArchiverBehaviour) -> PinpointSession? { + using archiver: AmplifyArchiverBehaviour) -> PinpointSession? + { guard let sessionData = userDefaults.data(forKey: Constants.sessionKey), let storedSession = try? archiver.decode(PinpointSession.self, from: sessionData), - !storedSession.sessionId.isEmpty else { + !storedSession.sessionId.isEmpty + else { return nil } @@ -110,9 +113,9 @@ class SessionClient: SessionClientBehaviour { // Update Endpoint and record Session Start event analyticsTaskQueue.async { [weak self] in guard let self else { return } - try? await self.endpointClient.updateEndpointProfile() - self.log.verbose("Firing Session Event: Start") - await self.record(eventType: Constants.Events.start) + try? await endpointClient.updateEndpointProfile() + log.verbose("Firing Session Event: Start") + await record(eventType: Constants.Events.start) } } @@ -132,8 +135,8 @@ class SessionClient: SessionClientBehaviour { log.info("Session Paused.") analyticsTaskQueue.async { [weak self] in guard let self else { return } - self.log.verbose("Firing Session Event: Pause") - await self.record(eventType: Constants.Events.pause) + log.verbose("Firing Session Event: Pause") + await record(eventType: Constants.Events.pause) } } @@ -162,8 +165,8 @@ class SessionClient: SessionClientBehaviour { log.info("Session Resumed.") analyticsTaskQueue.async { [weak self] in guard let self else { return } - self.log.verbose("Firing Session Event: Resume") - await self.record(eventType: Constants.Events.resume) + log.verbose("Firing Session Event: Resume") + await record(eventType: Constants.Events.resume) } } @@ -176,21 +179,22 @@ class SessionClient: SessionClientBehaviour { session.stop() log.info("Session Stopped.") analyticsTaskQueue.async { [weak self, session] in - guard let self = self, - let analyticsClient = self.analyticsClient else { + guard let self, + let analyticsClient + else { return } - self.log.verbose("Removing remote global attributes") + log.verbose("Removing remote global attributes") await analyticsClient.removeAllRemoteGlobalAttributes() - self.log.verbose("Updating session for existing events") + log.verbose("Updating session for existing events") try? await analyticsClient.update(session) - self.log.verbose("Firing Session Event: Stop") - await self.record(eventType: Constants.Events.stop) + log.verbose("Firing Session Event: Stop") + await record(eventType: Constants.Events.stop) if shouldSave { - self.saveSession() + saveSession() } } } @@ -205,7 +209,7 @@ class SessionClient: SessionClientBehaviour { } private func record(eventType: String) async { - guard let analyticsClient = analyticsClient else { + guard let analyticsClient else { log.error("Pinpoint Analytics is disabled.") return } @@ -248,11 +252,11 @@ extension SessionClient: DefaultLogger { } extension SessionClient { - struct Constants { + enum Constants { static let sessionKey = "com.amazonaws.AWSPinpointSessionKey" static let queue = "com.amazonaws.Amplify.SessionClientQueue" - struct Events { + enum Events { static let start = "_session.start" static let stop = "_session.stop" static let pause = "_session.pause" diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointAnalyticsConstants.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointAnalyticsConstants.swift index 3697bcd459..be39b15aa6 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointAnalyticsConstants.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointAnalyticsConstants.swift @@ -7,9 +7,9 @@ import Foundation -public struct AWSPinpointAnalytics { - public struct Constants { - public struct Event { +public enum AWSPinpointAnalytics { + public enum Constants { + public enum Event { public static let maximumNumberOfAttributes = 40 public static let maximumNumberOfMetrics = 40 public static let maximumKeyLength = 50 diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointErrorConstants.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointErrorConstants.swift index 0eaeb915fd..7885a28475 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointErrorConstants.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Constants/AWSPinpointErrorConstants.swift @@ -10,7 +10,7 @@ import Foundation public typealias AWSPinpointErrorString = (errorDescription: ErrorDescription, recoverySuggestion: RecoverySuggestion) -public struct AWSPinpointErrorConstants { +public enum AWSPinpointErrorConstants { static let pinpointConfigurationExpected: AWSPinpointErrorString = ( "Configuration for Pinpoint is not a dictionary literal", "Make sure the value for Pinpoint is a dictionary literal with `AppId` and `Region`" diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/ModeledErrorDescribable.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/ModeledErrorDescribable.swift index 60608de459..a6108a3682 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/ModeledErrorDescribable.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/ModeledErrorDescribable.swift @@ -5,9 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import Amplify import AWSPinpoint +import Foundation protocol ModeledErrorDescribable { var errorDescription: String { get } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyArchiver.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyArchiver.swift index 8948ecb901..9e5a349bb4 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyArchiver.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyArchiver.swift @@ -13,7 +13,7 @@ protocol AmplifyArchiverBehaviour { } struct AmplifyArchiver: AmplifyArchiverBehaviour { - func encode(_ encodable: T) throws -> Data where T: Encodable { + func encode(_ encodable: some Encodable) throws -> Data { let archiver = NSKeyedArchiver(requiringSecureCoding: false) try archiver.encodeEncodable(encodable, forKey: NSKeyedArchiveRootObjectKey) archiver.finishEncoding() diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyStringConvertible.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyStringConvertible.swift index 6f12af8567..2884dac888 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyStringConvertible.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AmplifyStringConvertible.swift @@ -19,7 +19,8 @@ extension AmplifyStringConvertible { public var description: String { if let data = try? Self.jsonEncoder.encode(self), - let result = String(data: data, encoding: .utf8) { + let result = String(data: data, encoding: .utf8) + { return result } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AnalyticsPropertiesModel.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AnalyticsPropertiesModel.swift index 6c93cbaf26..13f0bc0fc4 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AnalyticsPropertiesModel.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/AnalyticsPropertiesModel.swift @@ -15,8 +15,8 @@ public protocol AnalyticsPropertiesModel { func addMetric(_ metric: Int, forKey key: String) } -extension AnalyticsPropertiesModel { - public func addProperties(_ properties: [String: AnalyticsPropertyValue]) { +public extension AnalyticsPropertiesModel { + func addProperties(_ properties: [String: AnalyticsPropertyValue]) { for (key, value) in properties { if let value = value as? String { addAttribute(value, forKey: key) diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/PinpointRequestsRegistry.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/PinpointRequestsRegistry.swift index 9a2b02fa87..4fa7b23e2a 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/PinpointRequestsRegistry.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/PinpointRequestsRegistry.swift @@ -5,9 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import AWSPinpoint import ClientRuntime +import Foundation @_spi(PluginHTTPClientEngine) import InternalAmplifyCredentials @globalActor actor PinpointRequestsRegistry { @@ -63,7 +63,8 @@ private struct CustomPinpointHttpClientEngine: HTTPClient { func send(request: ClientRuntime.SdkHttpRequest) async throws -> ClientRuntime.HttpResponse { guard let url = request.endpoint.url, let pinpointApi = PinpointRequestsRegistry.API(from: url), - let userAgentSuffix = await userAgent(for: pinpointApi) else { + let userAgentSuffix = await userAgent(for: pinpointApi) + else { return try await httpClientEngine.send(request: request) } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/ProvisioningProfileReader.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/ProvisioningProfileReader.swift index 05126e0295..31e427d23f 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/ProvisioningProfileReader.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/ProvisioningProfileReader.swift @@ -27,7 +27,7 @@ extension ProvisioningProfileReader where Self == DefaultProvisioningProfileRead } struct DefaultProvisioningProfileReader: ProvisioningProfileReader { - private struct Keys { + private enum Keys { static let entitlements = "Entitlements" static var apsEnvironment: String { #if os(macOS) @@ -73,14 +73,16 @@ struct DefaultProvisioningProfileReader: ProvisioningProfileReader { } private var contents: Data? { - guard let url = url, - let contents = try? String(contentsOf: url, encoding: .isoLatin1) else { + guard let url, + let contents = try? String(contentsOf: url, encoding: .isoLatin1) + else { return nil } let scanner = Scanner(string: contents) guard scanner.scanUpToString("") else { + let plist = scanner.scanUpToString("") + else { return nil } @@ -88,17 +90,19 @@ struct DefaultProvisioningProfileReader: ProvisioningProfileReader { } func profile() -> ProvisioningProfile? { - guard let contents = contents, + guard let contents, let provisioning = try? PropertyListSerialization.propertyList( from: contents, format: nil - ) as? [String: Any] else { + ) as? [String: Any] + else { return nil } var profile = ProvisioningProfile() if let entitlements = provisioning[Keys.entitlements] as? [String: Any], - let apnsEnvironment = entitlements[Keys.apsEnvironment] as? String { + let apnsEnvironment = entitlements[Keys.apsEnvironment] as? String + { profile.apsEnvironment = ProvisioningProfile.APSEnvironment(rawValue: apnsEnvironment) } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RemoteNotificationsHelper.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RemoteNotificationsHelper.swift index 514ec7e7fb..f2291b6cd0 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RemoteNotificationsHelper.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RemoteNotificationsHelper.swift @@ -18,8 +18,8 @@ public protocol RemoteNotificationsBehaviour { } @_spi(InternalAWSPinpoint) -extension RemoteNotificationsBehaviour where Self == AmplifyRemoteNotificationsHelper { - public static var `default`: RemoteNotificationsBehaviour { +public extension RemoteNotificationsBehaviour where Self == AmplifyRemoteNotificationsHelper { + static var `default`: RemoteNotificationsBehaviour { AmplifyRemoteNotificationsHelper.shared } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RepeatingTimer.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RepeatingTimer.swift index 5a849d7405..1ebac00586 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RepeatingTimer.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Support/Utils/RepeatingTimer.swift @@ -10,7 +10,8 @@ import Foundation class RepeatingTimer { static func createRepeatingTimer(timeInterval: TimeInterval, - eventHandler: @escaping BasicClosure) -> DispatchSourceTimer { + eventHandler: @escaping BasicClosure) -> DispatchSourceTimer + { let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global(qos: .background)) timer.schedule(deadline: .now() + timeInterval, repeating: timeInterval) timer.setEventHandler(handler: eventHandler) diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AWSPinpointFactoryTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AWSPinpointFactoryTests.swift index e56ffc2670..7af1c2f33f 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AWSPinpointFactoryTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AWSPinpointFactoryTests.swift @@ -5,9 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 // +import XCTest @testable import AmplifyTestCommon @_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -import XCTest final class AWSPinpointFactoryTests: XCTestCase { private var appId: String { diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift index 8e0820aa39..281a682dce 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -@testable import InternalAWSPinpoint import XCTest +@testable import InternalAWSPinpoint #if canImport(WatchKit) import WatchKit #elseif canImport(UIKit) @@ -79,11 +79,11 @@ class ActivityTrackerTests: XCTestCase { func testApplicationStateChanged_shouldReportProperEvent() async { stateMachine.processExpectation = expectation(description: "Application state changed") stateMachine.processExpectation?.expectedFulfillmentCount = 3 - + NotificationCenter.default.post(Notification(name: Self.applicationDidMoveToBackgroundNotification)) NotificationCenter.default.post(Notification(name: Self.applicationWillMoveToForegoundNotification)) await NotificationCenter.default.post(Notification(name: Self.applicationWillTerminateNotification)) - + await fulfillment(of: [stateMachine.processExpectation!], timeout: 1) XCTAssertTrue(stateMachine.processedEvents.contains(.applicationDidMoveToBackground)) XCTAssertTrue(stateMachine.processedEvents.contains(.applicationWillMoveToForeground)) @@ -94,7 +94,7 @@ class ActivityTrackerTests: XCTestCase { func testBackgroundTracking_afterTimeout_shouldReportBackgroundTimeout() async { stateMachine.processExpectation = expectation(description: "Background tracking timeout") stateMachine.processExpectation?.expectedFulfillmentCount = 2 - + NotificationCenter.default.post(Notification(name: Self.applicationDidMoveToBackgroundNotification)) await fulfillment(of: [stateMachine.processExpectation!], timeout: 5) @@ -104,7 +104,7 @@ class ActivityTrackerTests: XCTestCase { } } -extension Array where Element == ActivityEvent { +extension [ActivityEvent] { func contains(_ element: Element) -> Bool { return contains(where: { $0 == element }) } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsClientTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsClientTests.swift index 4e0be941ca..50ed736354 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsClientTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsClientTests.swift @@ -1,14 +1,13 @@ // -// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint import StoreKit import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class AnalyticsClientTests: XCTestCase { private var analyticsClient: AnalyticsClient! @@ -49,7 +48,7 @@ class AnalyticsClientTests: XCTestCase { func testCreateVirtualMonetizationEvent() { let productId = "productIt" - let itemPrice: Double = 5.25 + let itemPrice = 5.25 let quantity = 2 let currency = "USD" @@ -159,7 +158,7 @@ private class MockTransaction: SKPaymentTransaction { private let _quantity: Int init(quantity: Int) { - _quantity = quantity + self._quantity = quantity } override var quantity: Int { @@ -169,9 +168,10 @@ private class MockTransaction: SKPaymentTransaction { } init(transactionId: String, - quantity: Int) { - _transactionId = transactionId - _payment = MockPayment(quantity: quantity) + quantity: Int) + { + self._transactionId = transactionId + self._payment = MockPayment(quantity: quantity) } override var transactionIdentifier: String? { @@ -188,9 +188,10 @@ private class MockProduct: SKProduct { private let _price: Double init(productId: String, - price: Double) { - _productId = productId - _price = price + price: Double) + { + self._productId = productId + self._price = price } override var productIdentifier: String { diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsEventStorageTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsEventStorageTests.swift index d9189a95ce..4ef0bd975d 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsEventStorageTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AnalyticsEventStorageTests.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest import SQLite +import XCTest @testable import Amplify @_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint @@ -48,11 +48,11 @@ class AnalyticsEventStorageTests: XCTestCase { let attributesBlob = Blob(bytes: [UInt8](encodedAttributes)) let encodedMetrics = try archiver.encode(metrics) let metricsBlob = Blob(bytes: [UInt8](encodedMetrics)) - let basicEvent: [Binding] = [1, attributesBlob, "eventType", metricsBlob, "2022-06-10T18:50:20.618Z", 1, "2022-06-10T17:00:20.618Z", "2022-06-10T17:10:20.618Z", 1654904585, 0, 0] - let failedWithMaxRetry: [Binding] = [2, attributesBlob, "eventType", metricsBlob, "2022-06-9T18:50:20.618Z", 2, "2022-06-9T17:00:20.618Z", "2022-06-9T17:10:20.618Z", 1654818185, 0, 4] - let dirtyEvent: [Binding] = [3, attributesBlob, "eventType", metricsBlob, "2022-06-8T18:50:20.618Z", 3, "2022-06-8T17:00:20.618Z", "2022-06-8T17:10:20.618Z", 1654731785, 1, 3] - let dirtyEvent2: [Binding] = [4, attributesBlob, "eventType", metricsBlob, "2022-06-7T18:50:20.618Z", 4, "2022-06-7T17:00:20.618Z", "2022-06-7T17:10:20.618Z", 1654645385, 1, 3] - let eventWithDirtyFlag: [Binding] = [5, attributesBlob, "eventType", metricsBlob, "2022-06-6T18:50:20.618Z", 5, "2022-06-6T17:00:20.618Z", "2022-06-6T17:10:20.618Z", 1654558985, 1, 1] + let basicEvent: [Binding] = [1, attributesBlob, "eventType", metricsBlob, "2022-06-10T18:50:20.618Z", 1, "2022-06-10T17:00:20.618Z", "2022-06-10T17:10:20.618Z", 1_654_904_585, 0, 0] + let failedWithMaxRetry: [Binding] = [2, attributesBlob, "eventType", metricsBlob, "2022-06-9T18:50:20.618Z", 2, "2022-06-9T17:00:20.618Z", "2022-06-9T17:10:20.618Z", 1_654_818_185, 0, 4] + let dirtyEvent: [Binding] = [3, attributesBlob, "eventType", metricsBlob, "2022-06-8T18:50:20.618Z", 3, "2022-06-8T17:00:20.618Z", "2022-06-8T17:10:20.618Z", 1_654_731_785, 1, 3] + let dirtyEvent2: [Binding] = [4, attributesBlob, "eventType", metricsBlob, "2022-06-7T18:50:20.618Z", 4, "2022-06-7T17:00:20.618Z", "2022-06-7T17:10:20.618Z", 1_654_645_385, 1, 3] + let eventWithDirtyFlag: [Binding] = [5, attributesBlob, "eventType", metricsBlob, "2022-06-6T18:50:20.618Z", 5, "2022-06-6T17:00:20.618Z", "2022-06-6T17:10:20.618Z", 1_654_558_985, 1, 1] _ = try adapter.executeQuery(insertEventStatement, basicEvent) _ = try adapter.executeQuery(insertEventStatement, failedWithMaxRetry) @@ -85,7 +85,7 @@ class AnalyticsEventStorageTests: XCTestCase { XCTAssertEqual(eventcount, 3) XCTAssertEqual(dirtyEventcount, 2) - try storage.checkDiskSize(limit: 10000000) + try storage.checkDiskSize(limit: 10_000_000) eventcount = try adapter.executeQuery(eventCountStatement, []).scalar() as! Int64 dirtyEventcount = try adapter.executeQuery(dirtyEventCountStatement, []).scalar() as! Int64 @@ -200,11 +200,11 @@ class AnalyticsEventStorageTests: XCTestCase { let latestEvent = events.first(where: { $0.id == "1" }) XCTAssertNotNil(latestEvent) XCTAssertEqual(latestEvent?.eventType, "eventType") - XCTAssertEqual(latestEvent?.eventDate.millisecondsSince1970, 1654887020618) + XCTAssertEqual(latestEvent?.eventDate.millisecondsSince1970, 1_654_887_020_618) XCTAssertEqual(latestEvent?.session.sessionId, "1") XCTAssertEqual(latestEvent?.session.startTime, expectedSessionStartTime) XCTAssertEqual(latestEvent?.session.stopTime, expectedSessionStopTime) - XCTAssertEqual(latestEvent?.session.duration, 600000) + XCTAssertEqual(latestEvent?.session.duration, 600_000) XCTAssertEqual(latestEvent?.attributes.count, 3) XCTAssertEqual(latestEvent?.attributes["key2"], "value2") XCTAssertEqual(latestEvent?.metrics.count, 2) @@ -330,7 +330,7 @@ class AnalyticsEventStorageTests: XCTestCase { XCTAssertEqual(latestEvent?.session.sessionId, "6") XCTAssertEqual(latestEvent?.session.startTime, expectedSessionStartTime) XCTAssertEqual(latestEvent?.session.stopTime, expectedSessionStopTime) - XCTAssertEqual(latestEvent?.session.duration, 600000) + XCTAssertEqual(latestEvent?.session.duration, 600_000) XCTAssertEqual(latestEvent?.attributes.count, 1) XCTAssertEqual(latestEvent?.attributes["testKey"], "testValue") XCTAssertEqual(latestEvent?.metrics.count, 1) diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AwsPinpointAnalyticsKeychainMigrationTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AwsPinpointAnalyticsKeychainMigrationTests.swift index 24755235a6..8e063ef299 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AwsPinpointAnalyticsKeychainMigrationTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/AwsPinpointAnalyticsKeychainMigrationTests.swift @@ -5,9 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest -import AWSPluginsCore import AWSPinpoint +import AWSPluginsCore +import XCTest @testable import Amplify @_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint @@ -35,8 +35,8 @@ class AWSPinpointAnalyticsKeyValueStoreTests: XCTestCase { let deviceToken = "000102030405060708090a0b0c0d0e0f" let deviceTokenData = Data(deviceToken.utf8) userDefaults.setValue(deviceTokenData, forKey: EndpointClient.Constants.deviceTokenKey) - - var currentKeychainDeviceToken = try? self.keychain._getData(EndpointClient.Constants.deviceTokenKey) + + var currentKeychainDeviceToken = try? keychain._getData(EndpointClient.Constants.deviceTokenKey) XCTAssertNil(currentKeychainDeviceToken) XCTAssertNotNil(userDefaults.data(forKey: EndpointClient.Constants.deviceTokenKey)) @@ -48,9 +48,9 @@ class AWSPinpointAnalyticsKeyValueStoreTests: XCTestCase { endpointInformationProvider: endpointInformationProvider, userDefaults: userDefaults, keychain: keychain) - - currentKeychainDeviceToken = try? self.keychain._getData(EndpointClient.Constants.deviceTokenKey) - XCTAssertNil(userDefaults.data(forKey:EndpointClient.Constants.deviceTokenKey)) + + currentKeychainDeviceToken = try? keychain._getData(EndpointClient.Constants.deviceTokenKey) + XCTAssertNil(userDefaults.data(forKey: EndpointClient.Constants.deviceTokenKey)) XCTAssertNotNil(currentKeychainDeviceToken) } @@ -58,8 +58,8 @@ class AWSPinpointAnalyticsKeyValueStoreTests: XCTestCase { let profile = PinpointEndpointProfile(applicationId: "appId", endpointId: "endpointId") let profileData = try? archiver.encode(profile) userDefaults.setValue(profileData, forKey: EndpointClient.Constants.endpointProfileKey) - - var currentKeychainProfile = try? self.keychain._getData(EndpointClient.Constants.endpointProfileKey) + + var currentKeychainProfile = try? keychain._getData(EndpointClient.Constants.endpointProfileKey) XCTAssertNil(currentKeychainProfile) XCTAssertNotNil(userDefaults.data(forKey: EndpointClient.Constants.endpointProfileKey)) @@ -71,9 +71,9 @@ class AWSPinpointAnalyticsKeyValueStoreTests: XCTestCase { endpointInformationProvider: endpointInformationProvider, userDefaults: userDefaults, keychain: keychain) - - currentKeychainProfile = try? self.keychain._getData(EndpointClient.Constants.endpointProfileKey) - XCTAssertNil(userDefaults.data(forKey:EndpointClient.Constants.endpointProfileKey)) + + currentKeychainProfile = try? keychain._getData(EndpointClient.Constants.endpointProfileKey) + XCTAssertNil(userDefaults.data(forKey: EndpointClient.Constants.endpointProfileKey)) XCTAssertNotNil(currentKeychainProfile) } } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointClientTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointClientTests.swift index 693a3b6787..ec97027020 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointClientTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointClientTests.swift @@ -5,10 +5,10 @@ // SPDX-License-Identifier: Apache-2.0 // -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -import XCTest import AWSPinpoint import UserNotifications +import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class EndpointClientTests: XCTestCase { private let newTokenHex = "646576696365546f6b656e" @@ -87,7 +87,7 @@ class EndpointClientTests: XCTestCase { } func testCurrentEndpointProfile_withInvalidStoredProfile_shouldRemoveStored_andReturnNew() async { - let oldEffectiveDate = Date().addingTimeInterval(-1000) + let oldEffectiveDate = Date().addingTimeInterval(-1_000) let oldDemographic = PinpointClientTypes.EndpointDemographic(appVersion: "oldVersion") let storedEndpointProfile = PinpointEndpointProfile(applicationId: "oldApplicationId", endpointId: "oldEndpoint", diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointInformationProviderTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointInformationProviderTests.swift index 316e6190b8..84a2de578f 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointInformationProviderTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EndpointInformationProviderTests.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class EndpointInformationProviderTests: XCTestCase { @@ -21,7 +21,7 @@ class EndpointInformationProviderTests: XCTestCase { /// Given: DefaultEndpointInformationProvider /// When: endpointInfo() is called - /// Then: endpoint information returned contains platform name/version, app version, model, + /// Then: endpoint information returned contains platform name/version, app version, model, func testGetEndpointInformationDetails() async { let provider = DefaultEndpointInformationProvider() let endpointInfo = await provider.endpointInfo() diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EventRecorderTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EventRecorderTests.swift index ee604010b9..ef5934f4b8 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EventRecorderTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/EventRecorderTests.swift @@ -5,11 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest -import AWSPinpoint import AwsCommonRuntimeKit -@testable import Amplify +import AWSPinpoint import ClientRuntime +import XCTest +@testable import Amplify @_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class EventRecorderTests: XCTestCase { @@ -28,7 +28,7 @@ class EventRecorderTests: XCTestCase { XCTFail("Failed to setup EventRecorderTests") } } - + override func tearDown() { pinpointClient = nil endpointClient = nil @@ -65,7 +65,7 @@ class EventRecorderTests: XCTestCase { XCTAssertEqual(event, storage.events[0]) XCTAssertEqual(storage.checkDiskSizeCallCount, 2) } - + /// - Given: a event recorder with events saved in the local storage /// - When: submitAllEvents is invoked and successful /// - Then: the events are removed from the local storage @@ -87,13 +87,13 @@ class EventRecorderTests: XCTestCase { ) ]))) let events = try await recorder.submitAllEvents() - + XCTAssertEqual(events.count, 2) XCTAssertEqual(pinpointClient.putEventsCount, 1) XCTAssertTrue(storage.events.isEmpty) XCTAssertEqual(storage.deleteEventCallCount, 2) } - + /// - Given: a event recorder with events saved in the local storage with active and stopped sessions /// - When: submitAllEvents is invoked /// - Then: the input is generated accordingly by including duration only for the stopped session @@ -133,7 +133,7 @@ class EventRecorderTests: XCTestCase { let session = PinpointSession(sessionId: "1", startTime: Date(), stopTime: nil) let event1 = PinpointEvent(id: "1", eventType: "eventType1", eventDate: Date(), session: session) let event2 = PinpointEvent(id: "2", eventType: "eventType2", eventDate: Date(), session: session) - storage.events = [ event1, event2 ] + storage.events = [event1, event2] pinpointClient.putEventsResult = .failure(NonRetryableError()) do { let events = try await recorder.submitAllEvents() @@ -157,7 +157,7 @@ class EventRecorderTests: XCTestCase { let session = PinpointSession(sessionId: "1", startTime: Date(), stopTime: nil) let event1 = PinpointEvent(id: "1", eventType: "eventType1", eventDate: Date(), session: session) let event2 = PinpointEvent(id: "2", eventType: "eventType2", eventDate: Date(), session: session) - storage.events = [ event1, event2 ] + storage.events = [event1, event2] pinpointClient.putEventsResult = .failure(RetryableError()) do { let events = try await recorder.submitAllEvents() @@ -181,7 +181,7 @@ class EventRecorderTests: XCTestCase { let session = PinpointSession(sessionId: "1", startTime: Date(), stopTime: nil) let event1 = PinpointEvent(id: "1", eventType: "eventType1", eventDate: Date(), session: session) let event2 = PinpointEvent(id: "2", eventType: "eventType2", eventDate: Date(), session: session) - storage.events = [ event1, event2 ] + storage.events = [event1, event2] pinpointClient.putEventsResult = .failure(ConnectivityError()) do { let events = try await recorder.submitAllEvents() diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockActivityTracker.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockActivityTracker.swift index 5329b1cd34..64d91af6ef 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockActivityTracker.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockActivityTracker.swift @@ -5,12 +5,12 @@ // SPDX-License-Identifier: Apache-2.0 // -@testable import InternalAWSPinpoint import Foundation +@testable import InternalAWSPinpoint class MockActivityTracker: ActivityTrackerBehaviour { var backgroundTrackingTimeout: TimeInterval = 0 - + var beginActivityTrackingCount = 0 var callback: ((ApplicationState) -> Void)? diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsClient.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsClient.swift index 307fb0775e..8901f7f085 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsClient.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsClient.swift @@ -5,11 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 // +import AmplifyAsyncTesting import AWSPinpoint -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint import StoreKit import XCTest -import AmplifyAsyncTesting +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint actor MockAnalyticsClient: AnalyticsClientBehaviour { let pinpointClient: PinpointClientProtocol = MockPinpointClient() diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsEventStorage.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsEventStorage.swift index ebc515a641..e5abff7c4f 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsEventStorage.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockAnalyticsEventStorage.swift @@ -44,7 +44,8 @@ class MockAnalyticsEventStorage: AnalyticsEventStorage { } func updateEvents(ofType: String, withSessionId: PinpointSession.SessionId, - setAttributes: [String: String]) throws { + setAttributes: [String: String]) throws + { updateEventsCallCount += 1 } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockArchiver.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockArchiver.swift index 6c8b9f4836..a42b2bad2b 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockArchiver.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockArchiver.swift @@ -5,11 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 // -@testable import InternalAWSPinpoint import Foundation +@testable import InternalAWSPinpoint class MockArchiver: AmplifyArchiverBehaviour { - var encoded: Data = Data() + var encoded: Data = .init() var decoded: Decodable? func resetCounters() { @@ -18,7 +18,7 @@ class MockArchiver: AmplifyArchiverBehaviour { } var encodeCount = 0 - func encode(_ encodable: T) throws -> Data where T: Encodable { + func encode(_ encodable: some Encodable) throws -> Data { encodeCount += 1 return encoded } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEndpointClient.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEndpointClient.swift index 4af9110ff9..7130a8f6c3 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEndpointClient.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEndpointClient.swift @@ -5,17 +5,17 @@ // SPDX-License-Identifier: Apache-2.0 // -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint import AWSClientRuntime import AWSPinpoint import Foundation +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint actor MockEndpointClient: EndpointClientBehaviour { let pinpointClient: PinpointClientProtocol = MockPinpointClient() class MockCredentialsProvider: CredentialsProviding { func getCredentials() async throws -> AWSCredentials { - return AWSCredentials(accessKey: "", secret: "", expirationTimeout: Date().addingTimeInterval(1000)) + return AWSCredentials(accessKey: "", secret: "", expirationTimeout: Date().addingTimeInterval(1_000)) } } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEventRecorder.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEventRecorder.swift index 50044a2a55..1717a2c571 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEventRecorder.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockEventRecorder.swift @@ -1,5 +1,4 @@ // -// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // @@ -25,7 +24,8 @@ actor MockEventRecorder: AnalyticsEventRecording { func updateAttributesOfEvents(ofType: String, withSessionId: PinpointSession.SessionId, - setAttributes: [String: String]) throws { + setAttributes: [String: String]) throws + { updateCount += 1 } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockFileManager.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockFileManager.swift index fd223fc308..5fee974d11 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockFileManager.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockFileManager.swift @@ -1,13 +1,12 @@ // -// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // -@testable import InternalAWSPinpoint import Foundation +@testable import InternalAWSPinpoint class MockFileManager: FileManagerBehaviour { private let tempDirectory = FileManager.default.temporaryDirectory diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockKeychainStore.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockKeychainStore.swift index e2c127588e..a46ad77986 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockKeychainStore.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockKeychainStore.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -import Foundation import AWSPluginsCore +import Foundation class MockKeychainStore: KeychainStoreBehavior { var stringValues: [String: String] = [:] @@ -56,7 +56,7 @@ class MockKeychainStore: KeychainStoreBehavior { dataValues.removeValue(forKey: key) } } - + func _removeAll() throws { stringValues.removeAll() dataValues.removeAll() diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockSQLiteLocalStorageAdapter.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockSQLiteLocalStorageAdapter.swift index 8008e96783..0ba0ad054b 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockSQLiteLocalStorageAdapter.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockSQLiteLocalStorageAdapter.swift @@ -4,6 +4,7 @@ // // SPDX-License-Identifier: Apache-2.0 // + import SQLite @testable import InternalAWSPinpoint diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockUserDefaults.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockUserDefaults.swift index 700e5830ee..f252be51cb 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockUserDefaults.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockUserDefaults.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -@testable import InternalAWSPinpoint import Foundation +@testable import InternalAWSPinpoint class MockUserDefaults: UserDefaultsBehaviour { var data: [String: UserDefaultsBehaviourValue] = [:] diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/PinpointRequestsRegistryTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/PinpointRequestsRegistryTests.swift index 7b17dd5b74..371c6ed9da 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/PinpointRequestsRegistryTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/PinpointRequestsRegistryTests.swift @@ -7,8 +7,8 @@ import AWSPinpoint import ClientRuntime -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class PinpointRequestsRegistryTests: XCTestCase { private var mockedHttpSdkClient: MockHttpClientEngine! @@ -106,6 +106,6 @@ private class MockLogAgent: LogAgent { let name = "MockLogAgent" var level: LogAgentLevel = .info - func log(level: ClientRuntime.LogAgentLevel, message: String, metadata: [String : String]?, source: String, file: String, function: String, line: UInt) { + func log(level: ClientRuntime.LogAgentLevel, message: String, metadata: [String: String]?, source: String, file: String, function: String, line: UInt) { } } diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SQLiteLocalStorageAdapterTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SQLiteLocalStorageAdapterTests.swift index 0b65be6ba3..ff7abe6eab 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SQLiteLocalStorageAdapterTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SQLiteLocalStorageAdapterTests.swift @@ -5,8 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 // -import XCTest import SQLite +import XCTest @testable import Amplify @testable import InternalAWSPinpoint @@ -47,7 +47,7 @@ class SQLiteLocalStorageAdapterTests: XCTestCase { sessionStopTime, timestamp, dirty, retryCount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """ - let bindings: [Binding] = [1, "", "", "", 100000, 2, 1000000, 1000000, 100000, 1, 0] + let bindings: [Binding] = [1, "", "", "", 100_000, 2, 1_000_000, 1_000_000, 100_000, 1, 0] _ = try adapter.executeQuery(insertStatement, bindings) result = try adapter.executeQuery(countStatement, []).scalar() as! Int64 XCTAssertEqual(result, 1) @@ -68,7 +68,7 @@ class SQLiteLocalStorageAdapterTests: XCTestCase { sessionStopTime, timestamp, dirty, retryCount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """ - let bindings: [Binding] = [1, "", "", "", 100000, 2, 1000000, 1000000, 100000, 1, 0] + let bindings: [Binding] = [1, "", "", "", 100_000, 2, 1_000_000, 1_000_000, 100_000, 1, 0] _ = try adapter.executeQuery(insertStatement, bindings) let countStatement = "SELECT COUNT(*) FROM Event" @@ -97,7 +97,7 @@ class SQLiteLocalStorageAdapterTests: XCTestCase { sessionStopTime, timestamp, dirty, retryCount) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """ - let bindings: [Binding] = [123, "", "", "", 100000, 2, 1000000, 1000000, 100000, 0, 0] + let bindings: [Binding] = [123, "", "", "", 100_000, 2, 1_000_000, 1_000_000, 100_000, 0, 0] _ = try adapter.executeQuery(insertStatement, bindings) let countStatement = "SELECT COUNT(*) FROM Event WHERE dirty = false" diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SessionClientTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SessionClientTests.swift index 9799d3a172..860dd5f02d 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SessionClientTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/SessionClientTests.swift @@ -5,9 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 // -@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint -import XCTest import AmplifyAsyncTesting +import XCTest +@_spi(InternalAWSPinpoint) @testable import InternalAWSPinpoint class SessionClientTests: XCTestCase { private var client: SessionClient! @@ -92,7 +92,7 @@ class SessionClientTests: XCTestCase { XCTAssertEqual(archiver.encodeCount, 1) XCTAssertEqual(activityTracker.beginActivityTrackingCount, 0) XCTAssertEqual(userDefaults.saveCount, 1) - + await fulfillment(of: [expectationStartSession], timeout: 1) let updateEndpointProfileCount = await endpointClient.updateEndpointProfileCount XCTAssertEqual(updateEndpointProfileCount, 1) @@ -228,7 +228,7 @@ class SessionClientTests: XCTestCase { func testApplicationMovedToForeground_withNonExpiredSession_shouldRecordResumeEvent() async { let expectationStartandPause = expectation(description: "Start and Pause event for new session") await analyticsClient.setRecordExpectation(expectationStartandPause, count: 2) - sessionTimeout = 1000 + sessionTimeout = 1_000 createNewSessionClient() client.startPinpointSession() client.startTrackingSessions(backgroundTimeout: sessionTimeout) From c843bbe8c4ba14779248c40fc158affa86a900ed Mon Sep 17 00:00:00 2001 From: Tuan Pham Date: Mon, 9 Sep 2024 16:30:24 -0500 Subject: [PATCH 3/4] resolve review comments --- ...npointAnalyticsPlugin+ClientBehavior.swift | 6 +- ...AWSPinpointAnalyticsPlugin+Configure.swift | 11 +- .../AWSPinpointAnalyticsPlugin+Options.swift | 14 +- ...PinpointAnalyticsPluginConfiguration.swift | 52 +++-- ...SPinpointAnalyticsPlugin+HubCategory.swift | 6 +- .../PinpointEvent+AnalyticsEvent.swift | 6 +- ...ntAnalyticsPluginClientBehaviorTests.swift | 96 +++++--- ...inpointAnalyticsPluginConfigureTests.swift | 18 +- .../AWSPinpointAnalyticsPluginTestBase.swift | 6 +- ...uginAmplifyOutputsConfigurationTests.swift | 37 ++- ...intAnalyticsPluginConfigurationTests.swift | 96 +++++--- .../Mocks/MockAWSPinpoint+Analytics.swift | 31 +-- .../Mocks/MockAWSPinpoint+Targeting.swift | 7 +- .../Mocks/MockAWSPinpoint.swift | 18 +- ...pointAnalyticsPluginIntegrationTests.swift | 142 +++++++----- .../AnalyticsStressTests.swift | 54 ++--- .../AWSPinpointBehavior.swift | 12 +- .../Analytics/AnalyticsClient.swift | 210 +++++++++++------- .../Analytics/EventRecorder.swift | 67 +++--- .../AnalyticsEventSQLStorage.swift | 12 +- .../LocalStorage/AnalyticsEventStorage.swift | 8 +- .../LocalStorage/PinpointEvent+Bindings.swift | 6 +- .../SQLiteLocalStorageAdapter.swift | 15 +- .../Analytics/PinpointEvent.swift | 13 +- .../AWSPinpointPluginConfiguration.swift | 7 +- .../Context/AWSPinpointFactory.swift | 7 +- .../PinpointContext+AWSPinpointBehavior.swift | 14 +- .../Context/PinpointContext.swift | 152 ++++++++----- .../Endpoint/EndpointClient.swift | 80 ++++--- .../Endpoint/PinpointEndpointProfile.swift | 28 +-- .../ActivityTracking/ActivityTracker.swift | 31 ++- .../ActivityTracking/StateMachine.swift | 6 +- .../Session/PinpointSession.swift | 45 ++-- .../Session/SessionClient.swift | 34 +-- .../Utils/AmplifyStringConvertible.swift | 3 +- .../Utils/ProvisioningProfileReader.swift | 3 +- .../Support/Utils/RepeatingTimer.swift | 7 +- .../ActivityTrackerTests.swift | 6 +- .../AnalyticsClientTests.swift | 30 ++- .../AnalyticsEventStorageTests.swift | 42 ++-- ...pointAnalyticsKeychainMigrationTests.swift | 40 ++-- .../EndpointClientTests.swift | 68 +++--- .../Mocks/MockAnalyticsEventStorage.swift | 9 +- .../Mocks/MockEventRecorder.swift | 9 +- .../PinpointRequestsRegistryTests.swift | 6 +- .../SessionClientTests.swift | 18 +- 46 files changed, 953 insertions(+), 635 deletions(-) diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift index 364b94e344..343b51094e 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+ClientBehavior.swift @@ -24,8 +24,10 @@ public extension AWSPinpointAnalyticsPlugin { currentEndpointProfile.addUserProfile(userProfile) } do { - try await pinpoint.updateEndpoint(with: currentEndpointProfile, - source: .analytics) + try await pinpoint.updateEndpoint( + with: currentEndpointProfile, + source: .analytics + ) Amplify.Hub.dispatchIdentifyUser(userId, userProfile: userProfile) } catch { Amplify.Hub.dispatchIdentifyUser(AnalyticsErrorHelper.getDefaultError(error)) diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift index f8fd7e1ae8..33a9cd9850 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Configure.swift @@ -82,11 +82,12 @@ public extension AWSPinpointAnalyticsPlugin { // MARK: Internal /// Internal configure method to set the properties of the plugin - internal func configure(pinpoint: AWSPinpointBehavior, - networkMonitor: NetworkMonitor, - globalProperties: AtomicDictionary = [:], - isEnabled: Bool = true) - { + internal func configure( + pinpoint: AWSPinpointBehavior, + networkMonitor: NetworkMonitor, + globalProperties: AtomicDictionary = [:], + isEnabled: Bool = true + ) { self.pinpoint = pinpoint self.networkMonitor = networkMonitor self.globalProperties = globalProperties diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift index 328ca4c92d..ac44e7e82f 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/AWSPinpointAnalyticsPlugin+Options.swift @@ -16,16 +16,18 @@ public extension AWSPinpointAnalyticsPlugin { public let trackAppSessions: Bool #if os(macOS) - public init(autoFlushEventsInterval: TimeInterval = 60, - trackAppSessions: Bool = true) - { + public init( + autoFlushEventsInterval: TimeInterval = 60, + trackAppSessions: Bool = true + ) { self.autoFlushEventsInterval = autoFlushEventsInterval self.trackAppSessions = trackAppSessions } #else - public init(autoFlushEventsInterval: TimeInterval = 60, - trackAppSessions: Bool = true) - { + public init( + autoFlushEventsInterval: TimeInterval = 60, + trackAppSessions: Bool = true + ) { self.autoFlushEventsInterval = autoFlushEventsInterval self.trackAppSessions = trackAppSessions } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift index c0a8fd7a57..1d625d7518 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Configuration/AWSPinpointAnalyticsPluginConfiguration.swift @@ -54,32 +54,37 @@ public struct AWSPinpointAnalyticsPluginConfiguration { let pluginConfiguration = try AWSPinpointPluginConfiguration(pinpointAnalyticsConfig) - let configOptions: AWSPinpointAnalyticsPlugin.Options = if let options { - options + let configOptions: AWSPinpointAnalyticsPlugin.Options + if let options { + configOptions = options } else { - try .init( + configOptions = try .init( autoFlushEventsInterval: Self.getAutoFlushEventsInterval(configObject), - trackAppSessions: Self.getTrackAppSessions(configObject)) + trackAppSessions: Self.getTrackAppSessions(configObject) + ) + } let autoSessionTrackingInterval = try Self.getAutoSessionTrackingInterval(configObject) // Warn users in case they set different regions between pinpointTargeting and pinpointAnalytics if let pinpointTargetingJson = configObject[Self.pinpointTargetingConfigKey], let pinpointTargetingConfig = try? AWSPinpointPluginConfiguration(pinpointTargetingJson), - pinpointTargetingConfig.region != pluginConfiguration.region - { + pinpointTargetingConfig.region != pluginConfiguration.region { Self.logger.warn("Having different regions for Analytics and Targeting operations is not supported. The Analytics region will be used.") } - self.init(appId: pluginConfiguration.appId, - region: pluginConfiguration.region, - autoSessionTrackingInterval: autoSessionTrackingInterval, - options: configOptions) + self.init( + appId: pluginConfiguration.appId, + region: pluginConfiguration.region, + autoSessionTrackingInterval: autoSessionTrackingInterval, + options: configOptions + ) } - init(_ configuration: AmplifyOutputsData, - options: AWSPinpointAnalyticsPlugin.Options) throws - { + init( + _ configuration: AmplifyOutputsData, + options: AWSPinpointAnalyticsPlugin.Options + ) throws { guard let analyticsConfig = configuration.analytics else { throw PluginError.pluginConfigurationError( AnalyticsPluginErrorConstant.missingAnalyticsCategoryConfiguration.errorDescription, @@ -94,17 +99,20 @@ public struct AWSPinpointAnalyticsPluginConfiguration { ) } - self.init(appId: pinpointAnalyticsConfig.appId, - region: pinpointAnalyticsConfig.awsRegion, - autoSessionTrackingInterval: Self.defaultAutoSessionTrackingInterval, - options: options) + self.init( + appId: pinpointAnalyticsConfig.appId, + region: pinpointAnalyticsConfig.awsRegion, + autoSessionTrackingInterval: Self.defaultAutoSessionTrackingInterval, + options: options + ) } - init(appId: String, - region: String, - autoSessionTrackingInterval: TimeInterval, - options: AWSPinpointAnalyticsPlugin.Options) - { + init( + appId: String, + region: String, + autoSessionTrackingInterval: TimeInterval, + options: AWSPinpointAnalyticsPlugin.Options + ) { self.appId = appId self.region = region self.autoSessionTrackingInterval = autoSessionTrackingInterval diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/AWSPinpointAnalyticsPlugin+HubCategory.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/AWSPinpointAnalyticsPlugin+HubCategory.swift index a51cb40aee..286274402c 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/AWSPinpointAnalyticsPlugin+HubCategory.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/AWSPinpointAnalyticsPlugin+HubCategory.swift @@ -11,8 +11,10 @@ import Foundation extension HubCategory { func dispatchIdentifyUser(_ identityId: String, userProfile: AnalyticsUserProfile?) { - let payload = HubPayload(eventName: HubPayload.EventName.Analytics.identifyUser, - data: (identityId, userProfile)) + let payload = HubPayload( + eventName: HubPayload.EventName.Analytics.identifyUser, + data: (identityId, userProfile) + ) dispatch(to: .analytics, payload: payload) } diff --git a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift index 0507d81ec5..f42e5cd596 100644 --- a/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift +++ b/AmplifyPlugins/Analytics/Sources/AWSPinpointAnalyticsPlugin/Support/Extensions/PinpointEvent+AnalyticsEvent.swift @@ -21,8 +21,10 @@ public extension PinpointEvent { properties[metric.key] = metric.value } - return BasicAnalyticsEvent(name: eventType, - properties: properties) + return BasicAnalyticsEvent( + name: eventType, + properties: properties + ) } } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift index bc462b9ec4..d78ec37ffb 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift @@ -18,16 +18,20 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT let testIdentityId = "identityId" let testEmail = "testEmail" let testPlan = "testPlan" - let testProperties: [String: AnalyticsPropertyValue] = ["keyString": "value", - "keyInt": 123, - "keyDouble": 1.2, - "keyBool": true] - let testLocation = AnalyticsUserProfile.Location(latitude: 12, - longitude: 34, - postalCode: "98122", - city: "Seattle", - region: "WA", - country: "USA") + let testProperties: [String: AnalyticsPropertyValue] = [ + "keyString": "value", + "keyInt": 123, + "keyDouble": 1.2, + "keyBool": true + ] + let testLocation = AnalyticsUserProfile.Location( + latitude: 12, + longitude: 34, + postalCode: "98122", + city: "Seattle", + region: "WA", + country: "USA" + ) // MARK: IdentifyUser API @@ -52,13 +56,17 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT } } - let userProfile = AnalyticsUserProfile(name: testName, - email: testEmail, - plan: testPlan, - location: testLocation, - properties: testProperties) - var expectedEndpointProfile = PinpointEndpointProfile(applicationId: "appId", - endpointId: "endpointId") + let userProfile = AnalyticsUserProfile( + name: testName, + email: testEmail, + plan: testPlan, + location: testLocation, + properties: testProperties + ) + var expectedEndpointProfile = PinpointEndpointProfile( + applicationId: "appId", + endpointId: "endpointId" + ) expectedEndpointProfile.addUserId(testIdentityId) expectedEndpointProfile.addUserProfile(userProfile) @@ -86,8 +94,10 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Then: AWSPinpoint.currentEndpoint and updateEndpoint methods are called /// and Hub Analytics.identifyUser event is dispatched with an error func testIdentifyUserDispatchesErrorForPinpointError() async throws { - mockPinpoint.updateEndpointProfileResult = .failure(NSError(domain: "domain", - code: 1)) + mockPinpoint.updateEndpointProfileResult = .failure(NSError( + domain: "domain", + code: 1 + )) let analyticsEventReceived = expectation(description: "Analytics event was received on the hub plugin") _ = plugin.listen(to: .analytics, isIncluded: nil) { payload in @@ -103,13 +113,17 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT } } - let userProfile = AnalyticsUserProfile(name: testName, - email: testEmail, - plan: testPlan, - location: testLocation, - properties: testProperties) - var expectedEndpointProfile = PinpointEndpointProfile(applicationId: "appId", - endpointId: "endpointId") + let userProfile = AnalyticsUserProfile( + name: testName, + email: testEmail, + plan: testPlan, + location: testLocation, + properties: testProperties + ) + var expectedEndpointProfile = PinpointEndpointProfile( + applicationId: "appId", + endpointId: "endpointId" + ) expectedEndpointProfile.addUserId(testIdentityId) expectedEndpointProfile.addUserProfile(userProfile) @@ -170,9 +184,11 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Then: AWSPinpoint.createEvent and record methods are called /// and Hub Analytics.record event is dispatched with a error func testRecordEventDispatchesErrorForPinpointError() async { - mockPinpoint.recordResult = .failure(NSError(domain: "domain", - code: 1, - userInfo: nil)) + mockPinpoint.recordResult = .failure(NSError( + domain: "domain", + code: 1, + userInfo: nil + )) let expectedPinpointEvent = PinpointEvent(eventType: testName, session: PinpointSession(appId: "", uniqueId: "")) mockPinpoint.createEventResult = expectedPinpointEvent expectedPinpointEvent.addProperties(testProperties) @@ -246,9 +262,11 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Then: AWSPinpoint.createEvent and record methods are called /// and Hub Analytics.record event is dispatched with a error func testRecordEventWithNameDispatchesErrorForPinpointError() async { - mockPinpoint.recordResult = .failure(NSError(domain: "domain", - code: 1, - userInfo: nil)) + mockPinpoint.recordResult = .failure(NSError( + domain: "domain", + code: 1, + userInfo: nil + )) let expectedPinpointEvent = PinpointEvent(eventType: testName, session: PinpointSession(appId: "", uniqueId: "")) mockPinpoint.createEventResult = expectedPinpointEvent @@ -343,8 +361,10 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Then: AWSPinpoint.submitEvents is invoked /// and Hub Analytics.flushEvents event is dispatched with submitted events func testFlushEvents_isOnline() async { - let result = [PinpointEvent(eventType: "1", session: PinpointSession(appId: "", uniqueId: "")), - PinpointEvent(eventType: "2", session: PinpointSession(appId: "", uniqueId: ""))] + let result = [ + PinpointEvent(eventType: "1", session: PinpointSession(appId: "", uniqueId: "")), + PinpointEvent(eventType: "2", session: PinpointSession(appId: "", uniqueId: "")) + ] mockNetworkMonitor.isOnline = true mockPinpoint.submitEventsResult = .success(result) let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") @@ -407,9 +427,11 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Then: AWSPinpoint.submitEvents is invoked /// and Hub Analytics.flushEvents event is dispatched with error func testFlushEventsDispatchesErrorForPinpointError() async { - mockPinpoint.submitEventsResult = .failure(NSError(domain: "domain", - code: 1, - userInfo: nil)) + mockPinpoint.submitEventsResult = .failure(NSError( + domain: "domain", + code: 1, + userInfo: nil + )) let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") _ = plugin.listen(to: .analytics, isIncluded: nil) { payload in diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift index 4b84e729c7..3c65df01f5 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginConfigureTests.swift @@ -95,7 +95,8 @@ class AWSPinpointAnalyticsPluginConfigureTests: AWSPinpointAnalyticsPluginTestBa let analyticsPlugin = AWSPinpointAnalyticsPlugin( options: .init( autoFlushEventsInterval: 50, - trackAppSessions: true)) + trackAppSessions: true + )) try analyticsPlugin.configure(using: analyticsPluginConfig) XCTAssertNotNil(analyticsPlugin.pinpoint) @@ -127,8 +128,10 @@ class AWSPinpointAnalyticsPluginConfigureTests: AWSPinpointAnalyticsPluginTestBa func testConfigure_WithAmplifyOutputs() { let config = AmplifyOutputsData.init(analytics: .init( - amazonPinpoint: .init(awsRegion: testRegion, - appId: testAppId))) + amazonPinpoint: .init( + awsRegion: testRegion, + appId: testAppId + ))) do { let analyticsPlugin = AWSPinpointAnalyticsPlugin() @@ -149,13 +152,16 @@ class AWSPinpointAnalyticsPluginConfigureTests: AWSPinpointAnalyticsPluginTestBa func testConfigure_WithAmplifyOutputsAndOptions() { let config = AmplifyOutputsData.init(analytics: .init( - amazonPinpoint: .init(awsRegion: testRegion, - appId: testAppId))) + amazonPinpoint: .init( + awsRegion: testRegion, + appId: testAppId + ))) do { let analyticsPlugin = AWSPinpointAnalyticsPlugin(options: .init( autoFlushEventsInterval: 100, - trackAppSessions: false)) + trackAppSessions: false + )) try analyticsPlugin.configure(using: config) XCTAssertNotNil(analyticsPlugin.pinpoint) diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift index bd4ae217f8..bfefb36938 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginTestBase.swift @@ -37,8 +37,10 @@ class AWSPinpointAnalyticsPluginTestBase: XCTestCase { mockPinpoint = MockAWSPinpoint() mockNetworkMonitor = MockNetworkMonitor() - analyticsPlugin.configure(pinpoint: mockPinpoint, - networkMonitor: mockNetworkMonitor) + analyticsPlugin.configure( + pinpoint: mockPinpoint, + networkMonitor: mockNetworkMonitor + ) await Amplify.reset() let config = AmplifyConfiguration() diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift index c624344118..129a735cbd 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests.swift @@ -34,20 +34,29 @@ class AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests: XCTestCase { XCTAssertNotNil(result) XCTAssertEqual(result.appId, testAppId) XCTAssertEqual(result.region, testRegion) - XCTAssertEqual(result.options.autoFlushEventsInterval, - AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval) - XCTAssertEqual(result.options.trackAppSessions, - AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession) - XCTAssertEqual(result.autoSessionTrackingInterval, - AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval) + XCTAssertEqual( + result.options.autoFlushEventsInterval, + AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval + ) + XCTAssertEqual( + result.options.trackAppSessions, + AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession + ) + XCTAssertEqual( + result.autoSessionTrackingInterval, + AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval + ) } func testConfiguration_OptionsOverride() throws { let config = AmplifyOutputsData(analytics: .init(amazonPinpoint: .init(awsRegion: testRegion, appId: appId))) let result = try AWSPinpointAnalyticsPluginConfiguration( config, - options: .init(autoFlushEventsInterval: 100, - trackAppSessions: false)) + options: .init( + autoFlushEventsInterval: 100, + trackAppSessions: false + ) + ) XCTAssertNotNil(result) XCTAssertEqual(result.appId, testAppId) XCTAssertEqual(result.region, testRegion) @@ -65,8 +74,10 @@ class AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests: XCTestCase { XCTFail("Expected to catch PluginError.pluginConfigurationError.") return } - XCTAssertEqual(errorDescription, - AnalyticsPluginErrorConstant.missingAnalyticsCategoryConfiguration.errorDescription) + XCTAssertEqual( + errorDescription, + AnalyticsPluginErrorConstant.missingAnalyticsCategoryConfiguration.errorDescription + ) } } @@ -79,8 +90,10 @@ class AWSPinpointAnalyticsPluginAmplifyOutputsConfigurationTests: XCTestCase { XCTFail("Expected to catch PluginError.pluginConfigurationError.") return } - XCTAssertEqual(errorDescription, - AnalyticsPluginErrorConstant.missingAmazonPinpointConfiguration.errorDescription) + XCTAssertEqual( + errorDescription, + AnalyticsPluginErrorConstant.missingAmazonPinpointConfiguration.errorDescription + ) } } } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift index 947f3e920d..2407a7fea3 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Configuration/AWSPinpointAnalyticsPluginConfigurationTests.swift @@ -42,12 +42,18 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTAssertNotNil(config) XCTAssertEqual(config.appId, testAppId) XCTAssertEqual(config.region, testRegion) - XCTAssertEqual(config.options.autoFlushEventsInterval, - AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval) - XCTAssertEqual(config.options.trackAppSessions, - AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession) - XCTAssertEqual(config.autoSessionTrackingInterval, - AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval) + XCTAssertEqual( + config.options.autoFlushEventsInterval, + AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval + ) + XCTAssertEqual( + config.options.trackAppSessions, + AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession + ) + XCTAssertEqual( + config.autoSessionTrackingInterval, + AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval + ) } catch { XCTFail("Failed to instantiate analytics plugin configuration") } @@ -64,12 +70,18 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTAssertNotNil(config) XCTAssertEqual(config.appId, testAppId) XCTAssertEqual(config.region, testRegion) - XCTAssertEqual(config.options.autoFlushEventsInterval, - AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval) - XCTAssertEqual(config.options.trackAppSessions, - AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession) - XCTAssertEqual(config.autoSessionTrackingInterval, - AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval) + XCTAssertEqual( + config.options.autoFlushEventsInterval, + AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval + ) + XCTAssertEqual( + config.options.trackAppSessions, + AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession + ) + XCTAssertEqual( + config.autoSessionTrackingInterval, + AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval + ) } catch { XCTFail("Failed to instantiate analytics plugin configuration") } @@ -88,10 +100,14 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTAssertEqual(config.appId, testAppId) XCTAssertEqual(config.region, testRegion) XCTAssertEqual(config.options.autoFlushEventsInterval, testAutoFlushInterval) - XCTAssertEqual(config.options.trackAppSessions, - AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession) - XCTAssertEqual(config.autoSessionTrackingInterval, - AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval) + XCTAssertEqual( + config.options.trackAppSessions, + AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession + ) + XCTAssertEqual( + config.autoSessionTrackingInterval, + AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval + ) } catch { XCTFail("Failed to instantiate analytics plugin configuration") } @@ -110,8 +126,10 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTFail("Expected PluginError pluginConfigurationError, got: \(error)") return } - XCTAssertEqual(errorDescription, - AnalyticsPluginErrorConstant.invalidAutoFlushEventsInterval.errorDescription) + XCTAssertEqual( + errorDescription, + AnalyticsPluginErrorConstant.invalidAutoFlushEventsInterval.errorDescription + ) } } @@ -127,11 +145,15 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTAssertNotNil(config) XCTAssertEqual(config.appId, testAppId) XCTAssertEqual(config.region, testRegion) - XCTAssertEqual(config.options.autoFlushEventsInterval, - AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval) + XCTAssertEqual( + config.options.autoFlushEventsInterval, + AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval + ) XCTAssertEqual(config.options.trackAppSessions, testTrackAppSession) - XCTAssertEqual(config.autoSessionTrackingInterval, - AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval) + XCTAssertEqual( + config.autoSessionTrackingInterval, + AWSPinpointAnalyticsPluginConfiguration.defaultAutoSessionTrackingInterval + ) } catch { XCTFail("Failed to instantiate analytics plugin configuration") } @@ -149,8 +171,10 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTAssertNotNil(config) XCTAssertEqual(config.appId, testAppId) XCTAssertEqual(config.region, testRegion) - XCTAssertEqual(config.options.autoFlushEventsInterval, - AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval) + XCTAssertEqual( + config.options.autoFlushEventsInterval, + AWSPinpointAnalyticsPlugin.Options.defaultAutoFlushEventsInterval + ) XCTAssertEqual(config.options.trackAppSessions, AWSPinpointAnalyticsPlugin.Options.defaultTrackAppSession) XCTAssertEqual(config.autoSessionTrackingInterval, testAutoSessionTrackingInterval) } catch { @@ -171,8 +195,10 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTFail("Expected PluginError pluginConfigurationError, got: \(error)") return } - XCTAssertEqual(errorDescription, - AnalyticsPluginErrorConstant.invalidAutoSessionTrackingInterval.errorDescription) + XCTAssertEqual( + errorDescription, + AnalyticsPluginErrorConstant.invalidAutoSessionTrackingInterval.errorDescription + ) } } @@ -184,8 +210,10 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTFail("Expected PluginError pluginConfigurationError, got: \(error)") return } - XCTAssertEqual(errorDescription, - AnalyticsPluginErrorConstant.configurationObjectExpected.errorDescription) + XCTAssertEqual( + errorDescription, + AnalyticsPluginErrorConstant.configurationObjectExpected.errorDescription + ) } } @@ -201,8 +229,10 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTFail("Expected PluginError pluginConfigurationError, got: \(error)") return } - XCTAssertEqual(errorDescription, - AnalyticsPluginErrorConstant.missingPinpointAnalyicsConfiguration.errorDescription) + XCTAssertEqual( + errorDescription, + AnalyticsPluginErrorConstant.missingPinpointAnalyicsConfiguration.errorDescription + ) } } @@ -218,8 +248,10 @@ class AWSPinpointAnalyticsPluginConfigurationTests: XCTestCase { XCTFail("Expected PluginError pluginConfigurationError, got: \(error)") return } - XCTAssertEqual(errorDescription, - AWSPinpointErrorConstants.pinpointConfigurationExpected.errorDescription) + XCTAssertEqual( + errorDescription, + AWSPinpointErrorConstants.pinpointConfigurationExpected.errorDescription + ) } } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift index 67ce6261a7..a6235dc850 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Analytics.swift @@ -104,9 +104,10 @@ public extension MockAWSPinpoint { return createEventResult ?? createEmptyEvent() } - func createAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) -> PinpointEvent - { + func createAppleMonetizationEvent( + with transaction: SKPaymentTransaction, + with product: SKProduct + ) -> PinpointEvent { createAppleMonetizationEventCalled += 1 createAppleMonetizationEventTransaction = transaction createAppleMonetizationEventProduct = product @@ -114,11 +115,12 @@ public extension MockAWSPinpoint { return createAppleMonetizationEventResult ?? createEmptyEvent() } - func createVirtualMonetizationEvent(withProductId theProductId: String, - withItemPrice theItemPrice: Double, - withQuantity theQuantity: Int, - withCurrency theCurrency: String) -> PinpointEvent - { + func createVirtualMonetizationEvent( + withProductId theProductId: String, + withItemPrice theItemPrice: Double, + withQuantity theQuantity: Int, + withCurrency theCurrency: String + ) -> PinpointEvent { createVirtualMonetizationEventCalled += 1 createVirtualMonetizationEventProductId = theProductId createVirtualMonetizationEventItemPrice = theItemPrice @@ -145,13 +147,16 @@ public extension MockAWSPinpoint { } private func createEmptyEvent() -> PinpointEvent { - return PinpointEvent(eventType: "", - session: PinpointSession(appId: "", uniqueId: "")) + return PinpointEvent( + eventType: "", + session: PinpointSession(appId: "", uniqueId: "") + ) } - func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: AnalyticsClientBehaviour.SubmitResult?) - { + func setAutomaticSubmitEventsInterval( + _ interval: TimeInterval, + onSubmit: AnalyticsClientBehaviour.SubmitResult? + ) { } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift index b6b7d9df2e..234741b138 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint+Targeting.swift @@ -25,9 +25,10 @@ public extension MockAWSPinpoint { } } - func updateEndpoint(with endpointProfile: PinpointEndpointProfile, - source: AWSPinpointSource) async throws - { + func updateEndpoint( + with endpointProfile: PinpointEndpointProfile, + source: AWSPinpointSource + ) async throws { updateEndpointProfileCalled += 1 updateEndpointProfileValue = endpointProfile diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift index e6985475da..1e80ceca3d 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/Mocks/MockAWSPinpoint.swift @@ -216,19 +216,21 @@ extension MockAWSPinpoint { XCTAssertEqual(createEventEventType, theEventType) } - public func verifyCreateAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) - { + public func verifyCreateAppleMonetizationEvent( + with transaction: SKPaymentTransaction, + with product: SKProduct + ) { XCTAssertEqual(createAppleMonetizationEventCalled, 1) XCTAssertEqual(createAppleMonetizationEventTransaction, transaction) XCTAssertEqual(createAppleMonetizationEventProduct, product) } - public func verifyCreateVirtualMonetizationEvent(withProductId theProductId: String, - withItemPrice theItemPrice: Double, - withQuantity theQuantity: Int, - withCurrency theCurrency: String) - { + public func verifyCreateVirtualMonetizationEvent( + withProductId theProductId: String, + withItemPrice theItemPrice: Double, + withQuantity theQuantity: Int, + withCurrency theCurrency: String + ) { XCTAssertEqual(createVirtualMonetizationEventCalled, 1) XCTAssertEqual(createVirtualMonetizationEventProductId, theProductId) XCTAssertEqual(createVirtualMonetizationEventItemPrice, theItemPrice) diff --git a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift index 5673f02b48..de5427eaff 100644 --- a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AWSPinpointAnalyticsPluginIntegrationTests/AWSPinpointAnalyticsPluginIntegrationTests.swift @@ -65,21 +65,27 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } - let location = AnalyticsUserProfile.Location(latitude: 47.606209, - longitude: -122.332069, - postalCode: "98122", - city: "Seattle", - region: "WA", - country: "USA") - let properties = ["userPropertyStringKey": "userProperyStringValue", - "userPropertyIntKey": 123, - "userPropertyDoubleKey": 12.34, - "userPropertyBoolKey": true] as [String: AnalyticsPropertyValue] - let userProfile = AnalyticsUserProfile(name: "name", - email: "email", - plan: "plan", - location: location, - properties: properties) + let location = AnalyticsUserProfile.Location( + latitude: 47.606209, + longitude: -122.332069, + postalCode: "98122", + city: "Seattle", + region: "WA", + country: "USA" + ) + let properties = [ + "userPropertyStringKey": "userProperyStringValue", + "userPropertyIntKey": 123, + "userPropertyDoubleKey": 12.34, + "userPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] + let userProfile = AnalyticsUserProfile( + name: "name", + email: "email", + plan: "plan", + location: location, + properties: properties + ) Amplify.Analytics.identifyUser(userId: userId, userProfile: userProfile) await fulfillment(of: [identifyUserEvent], timeout: TestCommonConstants.networkTimeout) @@ -96,8 +102,10 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { func skip_testDeleteEndpointsForUser() async throws { let userId = "userId" let applicationId = await endpointClient().currentEndpointProfile().applicationId - let deleteEndpointsRequest = DeleteUserEndpointsInput(applicationId: applicationId, - userId: userId) + let deleteEndpointsRequest = DeleteUserEndpointsInput( + applicationId: applicationId, + userId: userId + ) do { let response = try await pinpointClient().deleteUserEndpoints(input: deleteEndpointsRequest) XCTAssertNotNil(response.endpointsResponse) @@ -132,15 +140,19 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } - let globalProperties = ["globalPropertyStringKey": "eventProperyStringValue", - "globalPropertyIntKey": 123, - "globalPropertyDoubleKey": 12.34, - "globalPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let globalProperties = [ + "globalPropertyStringKey": "eventProperyStringValue", + "globalPropertyIntKey": 123, + "globalPropertyDoubleKey": 12.34, + "globalPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] Amplify.Analytics.registerGlobalProperties(globalProperties) - let properties = ["eventPropertyStringKey": "eventProperyStringValue", - "eventPropertyIntKey": 123, - "eventPropertyDoubleKey": 12.34, - "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey": "eventProperyStringValue", + "eventPropertyIntKey": 123, + "eventPropertyDoubleKey": 12.34, + "eventPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) @@ -180,15 +192,19 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { Amplify.Analytics.disable() Amplify.Analytics.enable() - let globalProperties = ["globalPropertyStringKey": "eventProperyStringValue", - "globalPropertyIntKey": 123, - "globalPropertyDoubleKey": 12.34, - "globalPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let globalProperties = [ + "globalPropertyStringKey": "eventProperyStringValue", + "globalPropertyIntKey": 123, + "globalPropertyDoubleKey": 12.34, + "globalPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] Amplify.Analytics.registerGlobalProperties(globalProperties) - let properties = ["eventPropertyStringKey": "eventProperyStringValue", - "eventPropertyIntKey": 123, - "eventPropertyDoubleKey": 12.34, - "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey": "eventProperyStringValue", + "eventPropertyIntKey": 123, + "eventPropertyDoubleKey": 12.34, + "eventPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) @@ -222,15 +238,19 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { Amplify.Analytics.disable() - let globalProperties = ["globalPropertyStringKey": "eventProperyStringValue", - "globalPropertyIntKey": 123, - "globalPropertyDoubleKey": 12.34, - "globalPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let globalProperties = [ + "globalPropertyStringKey": "eventProperyStringValue", + "globalPropertyIntKey": 123, + "globalPropertyDoubleKey": 12.34, + "globalPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] Amplify.Analytics.registerGlobalProperties(globalProperties) - let properties = ["eventPropertyStringKey": "eventProperyStringValue", - "eventPropertyIntKey": 123, - "eventPropertyDoubleKey": 12.34, - "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey": "eventProperyStringValue", + "eventPropertyIntKey": 123, + "eventPropertyDoubleKey": 12.34, + "eventPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) @@ -276,15 +296,19 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } - let globalProperties = ["globalPropertyStringKey": "GlobalProperyStringValue", - "globalPropertyIntKey": 321, - "globalPropertyDoubleKey": 43.21, - "globalPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let globalProperties = [ + "globalPropertyStringKey": "GlobalProperyStringValue", + "globalPropertyIntKey": 321, + "globalPropertyDoubleKey": 43.21, + "globalPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] Amplify.Analytics.registerGlobalProperties(globalProperties) - let properties = ["eventPropertyStringKey": "eventProperyStringValue", - "eventPropertyIntKey": 123, - "eventPropertyDoubleKey": 12.34, - "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey": "eventProperyStringValue", + "eventPropertyIntKey": 123, + "eventPropertyDoubleKey": 12.34, + "eventPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) @@ -330,16 +354,20 @@ class AWSPinpointAnalyticsPluginIntergrationTests: XCTestCase { } } - let globalProperties = ["globalPropertyStringKey": "GlobalProperyStringValue", - "globalPropertyIntKey": 321, - "globalPropertyDoubleKey": 43.21, - "globalPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let globalProperties = [ + "globalPropertyStringKey": "GlobalProperyStringValue", + "globalPropertyIntKey": 321, + "globalPropertyDoubleKey": 43.21, + "globalPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] Amplify.Analytics.registerGlobalProperties(globalProperties) Amplify.Analytics.unregisterGlobalProperties() - let properties = ["eventPropertyStringKey": "eventProperyStringValue", - "eventPropertyIntKey": 123, - "eventPropertyDoubleKey": 12.34, - "eventPropertyBoolKey": true] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey": "eventProperyStringValue", + "eventPropertyIntKey": 123, + "eventPropertyDoubleKey": 12.34, + "eventPropertyBoolKey": true + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName", properties: properties) Amplify.Analytics.record(event: event) diff --git a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift index 168c4079ea..736a2117b9 100644 --- a/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AnalyticsHostApp/AnalyticsStressTests/AnalyticsStressTests.swift @@ -54,11 +54,13 @@ final class AnalyticsStressTests: XCTestCase { let recordExpectation = expectation(description: "Records are successfully recorded") recordExpectation.expectedFulfillmentCount = concurrencyLimit for eventNumber in 0 ... concurrencyLimit { - let properties = ["eventPropertyStringKey1": "eventProperyStringValue1", - "eventPropertyStringKey2": "eventProperyStringValue2", - "eventPropertyStringKey3": "eventProperyStringValue3", - "eventPropertyStringKey4": "eventProperyStringValue4", - "eventPropertyStringKey5": "eventProperyStringValue5"] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey1": "eventProperyStringValue1", + "eventPropertyStringKey2": "eventProperyStringValue2", + "eventPropertyStringKey3": "eventProperyStringValue3", + "eventPropertyStringKey4": "eventProperyStringValue4", + "eventPropertyStringKey5": "eventProperyStringValue5" + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName" + String(eventNumber), properties: properties) Amplify.Analytics.record(event: event) recordExpectation.fulfill() @@ -87,26 +89,28 @@ final class AnalyticsStressTests: XCTestCase { for eventNumber in 0 ... concurrencyLimit { Task { - let properties = ["eventPropertyStringKey1": "eventProperyStringValue1", - "eventPropertyStringKey2": "eventProperyStringValue2", - "eventPropertyStringKey3": "eventProperyStringValue3", - "eventPropertyStringKey4": "eventProperyStringValue4", - "eventPropertyStringKey5": "eventProperyStringValue5", - "eventPropertyIntKey1": 123, - "eventPropertyIntKey2": 123, - "eventPropertyIntKey3": 123, - "eventPropertyIntKey4": 123, - "eventPropertyIntKey5": 123, - "eventPropertyDoubleKey1": 12.34, - "eventPropertyDoubleKey2": 12.34, - "eventPropertyDoubleKey3": 12.34, - "eventPropertyDoubleKey4": 12.34, - "eventPropertyDoubleKey5": 12.34, - "eventPropertyBoolKey1": true, - "eventPropertyBoolKey2": true, - "eventPropertyBoolKey3": true, - "eventPropertyBoolKey4": true, - "eventPropertyBoolKey5": true] as [String: AnalyticsPropertyValue] + let properties = [ + "eventPropertyStringKey1": "eventProperyStringValue1", + "eventPropertyStringKey2": "eventProperyStringValue2", + "eventPropertyStringKey3": "eventProperyStringValue3", + "eventPropertyStringKey4": "eventProperyStringValue4", + "eventPropertyStringKey5": "eventProperyStringValue5", + "eventPropertyIntKey1": 123, + "eventPropertyIntKey2": 123, + "eventPropertyIntKey3": 123, + "eventPropertyIntKey4": 123, + "eventPropertyIntKey5": 123, + "eventPropertyDoubleKey1": 12.34, + "eventPropertyDoubleKey2": 12.34, + "eventPropertyDoubleKey3": 12.34, + "eventPropertyDoubleKey4": 12.34, + "eventPropertyDoubleKey5": 12.34, + "eventPropertyBoolKey1": true, + "eventPropertyBoolKey2": true, + "eventPropertyBoolKey3": true, + "eventPropertyBoolKey4": true, + "eventPropertyBoolKey5": true + ] as [String: AnalyticsPropertyValue] let event = BasicAnalyticsEvent(name: "eventName" + String(eventNumber), properties: properties) Amplify.Analytics.record(event: event) recordExpectation.fulfill() diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/AWSPinpointBehavior.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/AWSPinpointBehavior.swift index 9f4c7d5d7a..e46287ddff 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/AWSPinpointBehavior.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/AWSPinpointBehavior.swift @@ -46,8 +46,10 @@ public protocol AWSPinpointBehavior { /// the automatic submission is disabled /// - Parameter interval: How much to wait between submissions /// - Parameter onSubmit: An optional callback to be run after each submission happens - func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: AnalyticsClientBehaviour.SubmitResult?) + func setAutomaticSubmitEventsInterval( + _ interval: TimeInterval, + onSubmit: AnalyticsClientBehaviour.SubmitResult? + ) // MARK: Session /// Beings automatically tracking session activity in the device. @@ -67,8 +69,10 @@ public protocol AWSPinpointBehavior { /// Updates the current endpoint with the provided profile /// - Parameter endpointProfile: The new endpoint profile /// - Parameter source: The source that originates this endpoint update, i.e. analytics or pushNotifications - func updateEndpoint(with endpointProfile: PinpointEndpointProfile, - source: AWSPinpointSource) async throws + func updateEndpoint( + with endpointProfile: PinpointEndpointProfile, + source: AWSPinpointSource + ) async throws } @_spi(InternalAWSPinpoint) diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift index 808b5ad801..9374091b5c 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/AnalyticsClient.swift @@ -27,18 +27,24 @@ public protocol AnalyticsClientBehaviour: Actor { func setRemoteGlobalAttributes(_ attributes: [String: String]) func removeAllRemoteGlobalAttributes() - func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: SubmitResult?) + func setAutomaticSubmitEventsInterval( + _ interval: TimeInterval, + onSubmit: SubmitResult? + ) @discardableResult func submitEvents() async throws -> [PinpointEvent] func update(_ session: PinpointSession) async throws - nonisolated func createAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) -> PinpointEvent - nonisolated func createVirtualMonetizationEvent(withProductId productId: String, - withItemPrice itemPrice: Double, - withQuantity quantity: Int, - withCurrency currency: String) -> PinpointEvent + nonisolated func createAppleMonetizationEvent( + with transaction: SKPaymentTransaction, + with product: SKProduct + ) -> PinpointEvent + nonisolated func createVirtualMonetizationEvent( + withProductId productId: String, + withItemPrice itemPrice: Double, + withQuantity quantity: Int, + withCurrency currency: String + ) -> PinpointEvent nonisolated func createEvent(withEventType eventType: String) -> PinpointEvent } @@ -67,9 +73,10 @@ actor AnalyticsClient: AnalyticsClientBehaviour { private lazy var eventTypeAttributes: [String: PinpointEventAttributes] = [:] private lazy var eventTypeMetrics: [String: PinpointEventMetrics] = [:] - init(eventRecorder: AnalyticsEventRecording, - sessionProvider: @escaping SessionProvider) - { + init( + eventRecorder: AnalyticsEventRecording, + sessionProvider: @escaping SessionProvider + ) { self.eventRecorder = eventRecorder self.sessionProvider = sessionProvider } @@ -77,30 +84,42 @@ actor AnalyticsClient: AnalyticsClientBehaviour { // Actors no longer use 'convenience' for inits. This is a warning in swift 5.7 and an error in swift 6+. // However, 'convenience' is required to build with swift <5.7 #if swift(>=5.7) - init(applicationId: String, - pinpointClient: PinpointClientProtocol, - endpointClient: EndpointClientBehaviour, - sessionProvider: @escaping SessionProvider) throws - { - let dbAdapter = try SQLiteLocalStorageAdapter(prefixPath: Constants.eventRecorderStoragePathPrefix, - databaseName: applicationId) - let eventRecorder = try EventRecorder(appId: applicationId, - storage: AnalyticsEventSQLStorage(dbAdapter: dbAdapter), - pinpointClient: pinpointClient, endpointClient: endpointClient) + init( + applicationId: String, + pinpointClient: PinpointClientProtocol, + endpointClient: EndpointClientBehaviour, + sessionProvider: @escaping SessionProvider + ) throws { + let dbAdapter = try SQLiteLocalStorageAdapter( + prefixPath: Constants.eventRecorderStoragePathPrefix, + databaseName: applicationId + ) + let eventRecorder = try EventRecorder( + appId: applicationId, + storage: AnalyticsEventSQLStorage(dbAdapter: dbAdapter), + pinpointClient: pinpointClient, + endpointClient: endpointClient + ) self.init(eventRecorder: eventRecorder, sessionProvider: sessionProvider) } #else - convenience init(applicationId: String, - pinpointClient: PinpointClientProtocol, - endpointClient: EndpointClientBehaviour, - sessionProvider: @escaping SessionProvider) throws - { - let dbAdapter = try SQLiteLocalStorageAdapter(prefixPath: Constants.eventRecorderStoragePathPrefix, - databaseName: applicationId) - let eventRecorder = try EventRecorder(appId: applicationId, - storage: AnalyticsEventSQLStorage(dbAdapter: dbAdapter), - pinpointClient: pinpointClient, endpointClient: endpointClient) + convenience init( + applicationId: String, + pinpointClient: PinpointClientProtocol, + endpointClient: EndpointClientBehaviour, + sessionProvider: @escaping SessionProvider + ) throws { + let dbAdapter = try SQLiteLocalStorageAdapter( + prefixPath: Constants.eventRecorderStoragePathPrefix, + databaseName: applicationId + ) + let eventRecorder = try EventRecorder( + appId: applicationId, + storage: AnalyticsEventSQLStorage(dbAdapter: dbAdapter), + pinpointClient: pinpointClient, + endpointClient: endpointClient + ) self.init(eventRecorder: eventRecorder, sessionProvider: sessionProvider) } @@ -163,68 +182,91 @@ actor AnalyticsClient: AnalyticsClientBehaviour { } // MARK: - Monetization events - nonisolated func createAppleMonetizationEvent(with transaction: SKPaymentTransaction, - with product: SKProduct) -> PinpointEvent - { + nonisolated func createAppleMonetizationEvent( + with transaction: SKPaymentTransaction, + with product: SKProduct + ) -> PinpointEvent { let numberFormatter = NumberFormatter() numberFormatter.locale = product.priceLocale numberFormatter.numberStyle = .currency numberFormatter.isLenient = true - return createMonetizationEvent(withStore: Constants.PurchaseEvent.appleStore, - productId: product.productIdentifier, - quantity: transaction.payment.quantity, - itemPrice: product.price.doubleValue, - currencyCode: product.priceLocale.currencyCode, - formattedItemPrice: numberFormatter.string(from: product.price), - transactionId: transaction.transactionIdentifier) + return createMonetizationEvent( + withStore: Constants.PurchaseEvent.appleStore, + productId: product.productIdentifier, + quantity: transaction.payment.quantity, + itemPrice: product.price.doubleValue, + currencyCode: product.priceLocale.currencyCode, + formattedItemPrice: numberFormatter.string(from: product.price), + transactionId: transaction.transactionIdentifier + ) } - nonisolated func createVirtualMonetizationEvent(withProductId productId: String, - withItemPrice itemPrice: Double, - withQuantity quantity: Int, - withCurrency currency: String) -> PinpointEvent - { - return createMonetizationEvent(withStore: Constants.PurchaseEvent.virtual, - productId: productId, - quantity: quantity, - itemPrice: itemPrice, - currencyCode: currency) + nonisolated func createVirtualMonetizationEvent( + withProductId productId: String, + withItemPrice itemPrice: Double, + withQuantity quantity: Int, + withCurrency currency: String + ) -> PinpointEvent { + return createMonetizationEvent( + withStore: Constants.PurchaseEvent.virtual, + productId: productId, + quantity: quantity, + itemPrice: itemPrice, + currencyCode: currency + ) } - private nonisolated func createMonetizationEvent(withStore store: String, - productId: String, - quantity: Int, - itemPrice: Double, - currencyCode: String?, - formattedItemPrice: String? = nil, - priceLocale: Locale? = nil, - transactionId: String? = nil) -> PinpointEvent - { - let monetizationEvent = PinpointEvent(eventType: Constants.PurchaseEvent.name, - session: sessionProvider()) - monetizationEvent.addAttribute(store, - forKey: Constants.PurchaseEvent.Keys.store) - monetizationEvent.addAttribute(productId, - forKey: Constants.PurchaseEvent.Keys.productId) - monetizationEvent.addMetric(quantity, - forKey: Constants.PurchaseEvent.Keys.quantity) - monetizationEvent.addMetric(itemPrice, - forKey: Constants.PurchaseEvent.Keys.itemPrice) + private nonisolated func createMonetizationEvent( + withStore store: String, + productId: String, + quantity: Int, + itemPrice: Double, + currencyCode: String?, + formattedItemPrice: String? = nil, + priceLocale: Locale? = nil, + transactionId: String? = nil + ) -> PinpointEvent { + let monetizationEvent = PinpointEvent( + eventType: Constants.PurchaseEvent.name, + session: sessionProvider() + ) + monetizationEvent.addAttribute( + store, + forKey: Constants.PurchaseEvent.Keys.store + ) + monetizationEvent.addAttribute( + productId, + forKey: Constants.PurchaseEvent.Keys.productId + ) + monetizationEvent.addMetric( + quantity, + forKey: Constants.PurchaseEvent.Keys.quantity + ) + monetizationEvent.addMetric( + itemPrice, + forKey: Constants.PurchaseEvent.Keys.itemPrice + ) if let currencyCode { - monetizationEvent.addAttribute(currencyCode, - forKey: Constants.PurchaseEvent.Keys.currency) + monetizationEvent.addAttribute( + currencyCode, + forKey: Constants.PurchaseEvent.Keys.currency + ) } if let formattedItemPrice { - monetizationEvent.addAttribute(formattedItemPrice, - forKey: Constants.PurchaseEvent.Keys.priceFormatted) + monetizationEvent.addAttribute( + formattedItemPrice, + forKey: Constants.PurchaseEvent.Keys.priceFormatted + ) } if let transactionId { - monetizationEvent.addAttribute(transactionId, - forKey: Constants.PurchaseEvent.Keys.transactionId) + monetizationEvent.addAttribute( + transactionId, + forKey: Constants.PurchaseEvent.Keys.transactionId + ) } return monetizationEvent @@ -233,8 +275,10 @@ actor AnalyticsClient: AnalyticsClientBehaviour { // MARK: - Event recording nonisolated func createEvent(withEventType eventType: String) -> PinpointEvent { precondition(!eventType.isEmpty, "Event types must be at least 1 character in length.") - return PinpointEvent(eventType: eventType, - session: sessionProvider()) + return PinpointEvent( + eventType: eventType, + session: sessionProvider() + ) } func record(_ event: PinpointEvent) async throws { @@ -274,9 +318,10 @@ actor AnalyticsClient: AnalyticsClientBehaviour { try await eventRecorder.update(session) } - func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: SubmitResult?) - { + func setAutomaticSubmitEventsInterval( + _ interval: TimeInterval, + onSubmit: SubmitResult? + ) { guard automaticSubmitEventsInterval != interval else { let message = interval == .zero ? "disabled" : "set to \(interval) seconds" log.verbose("Automatic Submission of Events' interval is already \(message).") @@ -304,7 +349,8 @@ actor AnalyticsClient: AnalyticsClientBehaviour { onSubmit?(.failure(error)) } } - }) + } + ) automaticSubmitEventsTimer?.resume() } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift index 060c36c2ef..cf155d9bde 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/EventRecorder.swift @@ -25,9 +25,11 @@ protocol AnalyticsEventRecording: Actor { /// - ofType: event type /// - withSessionId: session identifier /// - setAttributes: event attributes - func updateAttributesOfEvents(ofType: String, - withSessionId: PinpointSession.SessionId, - setAttributes: [String: String]) throws + func updateAttributesOfEvents( + ofType: String, + withSessionId: PinpointSession.SessionId, + setAttributes: [String: String] + ) throws /// Updates the session information of the events that match the same sessionId. /// - Parameter session: The session to update @@ -53,11 +55,12 @@ actor EventRecorder: AnalyticsEventRecording { /// - storage: A storage object that conforms to AnalyticsEventStorage /// - pinpointClient: A Pinpoint client /// - endpointClient: An EndpointClientBehaviour client - init(appId: String, - storage: AnalyticsEventStorage, - pinpointClient: PinpointClientProtocol, - endpointClient: EndpointClientBehaviour) throws - { + init( + appId: String, + storage: AnalyticsEventStorage, + pinpointClient: PinpointClientProtocol, + endpointClient: EndpointClientBehaviour + ) throws { self.appId = appId self.storage = storage self.pinpointClient = pinpointClient @@ -75,13 +78,16 @@ actor EventRecorder: AnalyticsEventRecording { try storage.checkDiskSize(limit: Constants.pinpointClientByteLimitDefault) } - func updateAttributesOfEvents(ofType eventType: String, - withSessionId sessionId: PinpointSession.SessionId, - setAttributes attributes: [String: String]) throws - { - try storage.updateEvents(ofType: eventType, - withSessionId: sessionId, - setAttributes: attributes) + func updateAttributesOfEvents( + ofType eventType: String, + withSessionId sessionId: PinpointSession.SessionId, + setAttributes attributes: [String: String] + ) throws { + try storage.updateEvents( + ofType: eventType, + withSessionId: sessionId, + setAttributes: attributes + ) } func update(_ session: PinpointSession) throws { @@ -130,9 +136,10 @@ actor EventRecorder: AnalyticsEventRecording { } } - private func submit(pinpointEvents: [PinpointEvent], - endpointProfile: PinpointEndpointProfile) async throws - { + private func submit( + pinpointEvents: [PinpointEvent], + endpointProfile: PinpointEndpointProfile + ) async throws { var clientEvents = [String: PinpointClientTypes.Event]() var pinpointEventsById = [String: PinpointEvent]() for event in pinpointEvents { @@ -141,11 +148,15 @@ actor EventRecorder: AnalyticsEventRecording { } let publicEndpoint = endpointClient.convertToPublicEndpoint(endpointProfile) - let eventsBatch = PinpointClientTypes.EventsBatch(endpoint: publicEndpoint, - events: clientEvents) + let eventsBatch = PinpointClientTypes.EventsBatch( + endpoint: publicEndpoint, + events: clientEvents + ) let batchItem = [endpointProfile.endpointId: eventsBatch] - let putEventsInput = PutEventsInput(applicationId: appId, - eventsRequest: .init(batchItem: batchItem)) + let putEventsInput = PutEventsInput( + applicationId: appId, + eventsRequest: .init(batchItem: batchItem) + ) await identifySource(for: pinpointEvents) do { @@ -172,8 +183,7 @@ actor EventRecorder: AnalyticsEventRecording { guard let event = pinpointEventsById[eventId] else { continue } let responseMessage = eventResponse.message ?? "Unknown" if HttpStatusCode.accepted.rawValue == eventResponse.statusCode, - Constants.acceptedResponseMessage == responseMessage - { + Constants.acceptedResponseMessage == responseMessage { // On successful submission, add the event to the list of submitted events and delete it from the local storage log.verbose("Successful submit for event with id \(eventId)") submittedEvents.append(event) @@ -329,10 +339,11 @@ actor EventRecorder: AnalyticsEventRecording { events.forEach { incrementEventRetry(eventId: $0.id) } } - private func retry(times: Int = Constants.defaultNumberOfRetriesForStorageOperations, - onErrorMessage: String, - _ closure: () throws -> Void) - { + private func retry( + times: Int = Constants.defaultNumberOfRetriesForStorageOperations, + onErrorMessage: String, + _ closure: () throws -> Void + ) { do { try closure() } catch { diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift index 3a66abf700..91f7df443b 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventSQLStorage.swift @@ -101,10 +101,11 @@ class AnalyticsEventSQLStorage: AnalyticsEventStorage { _ = try dbAdapter.executeQuery(deleteStatement, []) } - func updateEvents(ofType eventType: String, - withSessionId sessionId: PinpointSession.SessionId, - setAttributes attributes: [String: String]) throws - { + func updateEvents( + ofType eventType: String, + withSessionId sessionId: PinpointSession.SessionId, + setAttributes attributes: [String: String] + ) throws { let updateStatement = """ UPDATE Event SET attributes = ? @@ -114,7 +115,8 @@ class AnalyticsEventSQLStorage: AnalyticsEventStorage { _ = try dbAdapter.executeQuery(updateStatement, [ PinpointEvent.archiveEventAttributes(attributes), sessionId, - eventType]) + eventType + ]) } func updateSession(_ session: PinpointSession) throws { diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift index e36b587d8f..8fcf6db67c 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/AnalyticsEventStorage.swift @@ -26,9 +26,11 @@ protocol AnalyticsEventStorage { /// - ofType: event type /// - sessionId: session identifier /// - setAttributes: event attributes - func updateEvents(ofType: String, - withSessionId: PinpointSession.SessionId, - setAttributes: [String: String]) throws + func updateEvents( + ofType: String, + withSessionId: PinpointSession.SessionId, + setAttributes: [String: String] + ) throws /// Updates the session information of the events that match the same sessionId. /// - Parameter session: The session to update diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift index ad1b43cd18..7ebc4965af 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/PinpointEvent+Bindings.swift @@ -86,16 +86,14 @@ extension PinpointEvent { let pinpointEvent = PinpointEvent(id: eventId, eventType: eventType, eventDate: timestamp, session: session, retryCount: retryCount) if let attributes = element[EventPropertyIndex.attributes] as? Blob, - let decodedAttributes = try? archiver.decode(AnalyticsClient.PinpointEventAttributes.self, from: Data(attributes.bytes)) - { + let decodedAttributes = try? archiver.decode(AnalyticsClient.PinpointEventAttributes.self, from: Data(attributes.bytes)) { for (key, value) in decodedAttributes { pinpointEvent.addAttribute(value, forKey: key) } } if let metrics = element[EventPropertyIndex.metrics] as? Blob, - let decodedMetrics = try? archiver.decode(AnalyticsClient.PinpointEventMetrics.self, from: Data(metrics.bytes)) - { + let decodedMetrics = try? archiver.decode(AnalyticsClient.PinpointEventMetrics.self, from: Data(metrics.bytes)) { for (key, value) in decodedMetrics { pinpointEvent.addMetric(value, forKey: key) } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift index 293fdfff1d..0c4f147cd6 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/LocalStorage/SQLiteLocalStorageAdapter.swift @@ -23,16 +23,19 @@ final class SQLiteLocalStorageAdapter: SQLStorageProtocol { /// - prefixPath: A prefix to be used for the database path. Defaults to none. /// - databaseName: The database name /// - fileManager: A FileManagerBehaviour instance to interact with the disk. Defaults to FileManager.default - init(prefixPath: String = "", - databaseName: String, - fileManager: FileManagerBehaviour = FileManager.default) throws - { + init( + prefixPath: String = "", + databaseName: String, + fileManager: FileManagerBehaviour = FileManager.default + ) throws { let dbDirectoryPath = try Self.getTmpPath() .appendingPathComponent(prefixPath) var dbFilePath = dbDirectoryPath.appendingPathComponent(databaseName) if !fileManager.fileExists(atPath: dbDirectoryPath.path) { - try fileManager.createDirectory(atPath: dbDirectoryPath.path, - withIntermediateDirectories: true) + try fileManager.createDirectory( + atPath: dbDirectoryPath.path, + withIntermediateDirectories: true + ) } let connection: Connection diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift index cb2f265033..9d92cd94f8 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Analytics/PinpointEvent.swift @@ -20,12 +20,13 @@ public class PinpointEvent: AnalyticsPropertiesModel { public private(set) lazy var attributes: [String: String] = [:] public private(set) lazy var metrics: [String: Double] = [:] - init(id: String = UUID().uuidString, - eventType: String, - eventDate: Date = Date(), - session: PinpointSession, - retryCount: Int = 0) - { + init( + id: String = UUID().uuidString, + eventType: String, + eventDate: Date = Date(), + session: PinpointSession, + retryCount: Int = 0 + ) { self.id = id self.eventType = eventType self.eventDate = eventDate diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift index e9d4b40392..ec22d2fbb0 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Configuration/AWSPinpointPluginConfiguration.swift @@ -32,9 +32,10 @@ public struct AWSPinpointPluginConfiguration { ) } - public init(appId: String, - region: String) - { + public init( + appId: String, + region: String + ) { self.appId = appId self.region = region } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift index 7758531797..4eaf2e06e1 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/AWSPinpointFactory.swift @@ -24,9 +24,10 @@ public class AWSPinpointFactory { static var provisioningProfileReader: ProvisioningProfileReader = .default - public static func sharedPinpoint(appId: String, - region: String) throws -> AWSPinpointBehavior - { + public static func sharedPinpoint( + appId: String, + region: String + ) throws -> AWSPinpointBehavior { let key = PinpointContextKey(appId: appId, region: region) if let existingContext = instances[key] { return existingContext diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift index 7bdc888521..0b15e93011 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext+AWSPinpointBehavior.swift @@ -31,9 +31,10 @@ extension PinpointContext: AWSPinpointBehavior { await endpointClient.currentEndpointProfile() } - func updateEndpoint(with endpointProfile: PinpointEndpointProfile, - source: AWSPinpointSource) async throws - { + func updateEndpoint( + with endpointProfile: PinpointEndpointProfile, + source: AWSPinpointSource + ) async throws { await PinpointRequestsRegistry.shared.registerSource(source, for: .updateEndpoint) try await endpointClient.updateEndpointProfile(with: endpointProfile) } @@ -62,9 +63,10 @@ extension PinpointContext: AWSPinpointBehavior { await analyticsClient.setRemoteGlobalAttributes(attributes) } - func setAutomaticSubmitEventsInterval(_ interval: TimeInterval, - onSubmit: AnalyticsClientBehaviour.SubmitResult?) - { + func setAutomaticSubmitEventsInterval( + _ interval: TimeInterval, + onSubmit: AnalyticsClientBehaviour.SubmitResult? + ) { Task { await analyticsClient.setAutomaticSubmitEventsInterval(interval, onSubmit: onSubmit) } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift index 8c581b8886..59e67ebd44 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Context/PinpointContext.swift @@ -49,9 +49,11 @@ extension FileManager: FileManagerBehaviour, DefaultLogger { } func createDirectory(atPath path: String, withIntermediateDirectories createIntermediates: Bool) throws { - try createDirectory(atPath: path, - withIntermediateDirectories: createIntermediates, - attributes: nil) + try createDirectory( + atPath: path, + withIntermediateDirectories: createIntermediates, + attributes: nil + ) } func fileSize(for url: URL) -> Byte { @@ -81,11 +83,12 @@ struct PinpointContextConfiguration { /// Setting this flag to true will set the Endpoint Profile to have a channel type of "APNS_SANDBOX". let isDebug: Bool - init(appId: String, - region: String, - credentialsProvider: CredentialsProviding, - isDebug: Bool = false) - { + init( + appId: String, + region: String, + credentialsProvider: CredentialsProviding, + isDebug: Bool = false + ) { self.appId = appId self.region = region self.credentialsProvider = credentialsProvider @@ -110,38 +113,51 @@ class PinpointContext { private let configuration: PinpointContextConfiguration private let storage: PinpointContextStorage - init(with configuration: PinpointContextConfiguration, - endpointInformationProvider: EndpointInformationProvider = DefaultEndpointInformationProvider(), - userDefaults: UserDefaultsBehaviour = UserDefaults.standard, - keychainStore: KeychainStoreBehavior = KeychainStore(service: PinpointContext.Constants.Keychain.service), - fileManager: FileManagerBehaviour = FileManager.default, - archiver: AmplifyArchiverBehaviour = AmplifyArchiver(), - remoteNotificationsHelper: RemoteNotificationsBehaviour = .default) throws - { + init( + with configuration: PinpointContextConfiguration, + endpointInformationProvider: EndpointInformationProvider = DefaultEndpointInformationProvider(), + userDefaults: UserDefaultsBehaviour = UserDefaults.standard, + keychainStore: KeychainStoreBehavior = KeychainStore(service: PinpointContext.Constants.Keychain.service), + fileManager: FileManagerBehaviour = FileManager.default, + archiver: AmplifyArchiverBehaviour = AmplifyArchiver(), + remoteNotificationsHelper: RemoteNotificationsBehaviour = .default + ) throws { self.configuration = configuration - self.storage = PinpointContextStorage(userDefaults: userDefaults, - keychainStore: keychainStore, - fileManager: fileManager, - archiver: archiver) + self.storage = PinpointContextStorage( + userDefaults: userDefaults, + keychainStore: keychainStore, + fileManager: fileManager, + archiver: archiver + ) self.uniqueId = Self.retrieveUniqueId(applicationId: configuration.appId, storage: storage) - let pinpointClient = try PinpointClient(region: configuration.region, - credentialsProvider: configuration.credentialsProvider) - - self.endpointClient = EndpointClient(configuration: .init(appId: configuration.appId, - uniqueDeviceId: uniqueId, - isDebug: configuration.isDebug), - pinpointClient: pinpointClient, - endpointInformationProvider: endpointInformationProvider, - userDefaults: userDefaults, - keychain: keychainStore, - remoteNotificationsHelper: remoteNotificationsHelper) - - self.sessionClient = SessionClient(archiver: archiver, - configuration: .init(appId: configuration.appId, - uniqueDeviceId: uniqueId), - endpointClient: endpointClient, - userDefaults: userDefaults) + let pinpointClient = try PinpointClient( + region: configuration.region, + credentialsProvider: configuration.credentialsProvider + ) + + self.endpointClient = EndpointClient( + configuration: .init( + appId: configuration.appId, + uniqueDeviceId: uniqueId, + isDebug: configuration.isDebug + ), + pinpointClient: pinpointClient, + endpointInformationProvider: endpointInformationProvider, + userDefaults: userDefaults, + keychain: keychainStore, + remoteNotificationsHelper: remoteNotificationsHelper + ) + + self.sessionClient = SessionClient( + archiver: archiver, + configuration: .init( + appId: configuration.appId, + uniqueDeviceId: uniqueId + ), + endpointClient: endpointClient, + userDefaults: userDefaults + ) let sessionProvider: () -> PinpointSession = { [weak sessionClient] in guard let sessionClient else { @@ -150,20 +166,25 @@ class PinpointContext { return sessionClient.currentSession } - self.analyticsClient = try AnalyticsClient(applicationId: configuration.appId, - pinpointClient: pinpointClient, - endpointClient: endpointClient, - sessionProvider: sessionProvider) + self.analyticsClient = try AnalyticsClient( + applicationId: configuration.appId, + pinpointClient: pinpointClient, + endpointClient: endpointClient, + sessionProvider: sessionProvider + ) sessionClient.analyticsClient = analyticsClient sessionClient.startPinpointSession() setAutomaticSubmitEventsInterval(Constants.defaultAutomaticSubmissionInterval) } - private static func legacyPreferencesFilePath(applicationId: String, - storage: PinpointContextStorage) -> String? - { - let applicationSupportDirectoryUrls = storage.fileManager.urls(for: .applicationSupportDirectory, - in: .userDomainMask) + private static func legacyPreferencesFilePath( + applicationId: String, + storage: PinpointContextStorage + ) -> String? { + let applicationSupportDirectoryUrls = storage.fileManager.urls( + for: .applicationSupportDirectory, + in: .userDomainMask + ) let preferencesFileUrl = applicationSupportDirectoryUrls.first? .appendingPathComponent(Constants.Preferences.mobileAnalyticsRoot) .appendingPathComponent(applicationId) @@ -172,11 +193,14 @@ class PinpointContext { return preferencesFileUrl?.path } - private static func removeLegacyPreferencesFile(applicationId: String, - storage: PinpointContextStorage) - { - guard let preferencesPath = legacyPreferencesFilePath(applicationId: applicationId, - storage: storage) + private static func removeLegacyPreferencesFile( + applicationId: String, + storage: PinpointContextStorage + ) { + guard let preferencesPath = legacyPreferencesFilePath( + applicationId: applicationId, + storage: storage + ) else { return } @@ -188,14 +212,19 @@ class PinpointContext { } } - private static func legacyUniqueId(applicationId: String, - storage: PinpointContextStorage) -> String? - { - guard let preferencesPath = legacyPreferencesFilePath(applicationId: applicationId, - storage: storage), + private static func legacyUniqueId( + applicationId: String, + storage: PinpointContextStorage + ) -> String? { + guard let preferencesPath = legacyPreferencesFilePath( + applicationId: applicationId, + storage: storage + ), storage.fileManager.fileExists(atPath: preferencesPath), - let preferencesJson = try? JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: preferencesPath)), - options: .mutableContainers) as? [String: String] + let preferencesJson = try? JSONSerialization.jsonObject( + with: Data(contentsOf: URL(fileURLWithPath: preferencesPath)), + options: .mutableContainers + ) as? [String: String] else { return nil } @@ -217,9 +246,10 @@ class PinpointContext { - Returns: A string representing the Device Unique ID */ - private static func retrieveUniqueId(applicationId: String, - storage: PinpointContextStorage) -> String - { + private static func retrieveUniqueId( + applicationId: String, + storage: PinpointContextStorage + ) -> String { // 1. Look for the UniqueId in the Keychain if let deviceUniqueId = try? storage.keychainStore._getString(Constants.Keychain.uniqueIdKey) { return deviceUniqueId diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift index 492a0da55b..f71e0f824a 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/EndpointClient.swift @@ -40,13 +40,14 @@ actor EndpointClient: EndpointClientBehaviour { private var endpointProfile: PinpointEndpointProfile? private static let defaultDateFormatter = ISO8601DateFormatter() - init(configuration: EndpointClient.Configuration, - pinpointClient: PinpointClientProtocol, - archiver: AmplifyArchiverBehaviour = AmplifyArchiver(), - endpointInformationProvider: EndpointInformationProvider, - userDefaults: UserDefaultsBehaviour = UserDefaults.standard, - keychain: KeychainStoreBehavior = KeychainStore(service: PinpointContext.Constants.Keychain.service), - remoteNotificationsHelper: RemoteNotificationsBehaviour = .default + init( + configuration: EndpointClient.Configuration, + pinpointClient: PinpointClientProtocol, + archiver: AmplifyArchiverBehaviour = AmplifyArchiver(), + endpointInformationProvider: EndpointInformationProvider, + userDefaults: UserDefaultsBehaviour = UserDefaults.standard, + keychain: KeychainStoreBehavior = KeychainStore(service: PinpointContext.Constants.Keychain.service), + remoteNotificationsHelper: RemoteNotificationsBehaviour = .default ) { self.configuration = configuration self.pinpointClient = pinpointClient @@ -83,15 +84,16 @@ actor EndpointClient: EndpointClientBehaviour { // 2. Look for a valid PinpointEndpointProfile object stored locally. It needs to match the current applicationId, otherwise we'll discard it. if let endpointProfileData = Self.getStoredData(from: keychain, forKey: Constants.endpointProfileKey, fallbackTo: userDefaults), let decodedEndpointProfile = try? archiver.decode(PinpointEndpointProfile.self, from: endpointProfileData), - decodedEndpointProfile.applicationId == configuration.appId - { + decodedEndpointProfile.applicationId == configuration.appId { return await configure(endpointProfile: decodedEndpointProfile) } try? keychain._remove(Constants.endpointProfileKey) // Create a new PinpointEndpointProfile - return await configure(endpointProfile: PinpointEndpointProfile(applicationId: configuration.appId, - endpointId: configuration.uniqueDeviceId)) + return await configure(endpointProfile: PinpointEndpointProfile( + applicationId: configuration.appId, + endpointId: configuration.uniqueDeviceId + )) } private func configure(endpointProfile: PinpointEndpointProfile) async -> PinpointEndpointProfile { @@ -154,18 +156,22 @@ actor EndpointClient: EndpointClientBehaviour { let channelType = getChannelType(from: endpointProfile) let effectiveDate = getEffectiveDateIso8601FractionalSeconds(from: endpointProfile) let optOut = getOptOut(from: endpointProfile) - let endpointRequest = PinpointClientTypes.EndpointRequest(address: endpointProfile.deviceToken, - attributes: endpointProfile.attributes, - channelType: channelType, - demographic: endpointProfile.demographic, - effectiveDate: effectiveDate, - location: endpointProfile.location, - metrics: endpointProfile.metrics, - optOut: optOut, - user: endpointProfile.user) - return UpdateEndpointInput(applicationId: endpointProfile.applicationId, - endpointId: endpointProfile.endpointId, - endpointRequest: endpointRequest) + let endpointRequest = PinpointClientTypes.EndpointRequest( + address: endpointProfile.deviceToken, + attributes: endpointProfile.attributes, + channelType: channelType, + demographic: endpointProfile.demographic, + effectiveDate: effectiveDate, + location: endpointProfile.location, + metrics: endpointProfile.metrics, + optOut: optOut, + user: endpointProfile.user + ) + return UpdateEndpointInput( + applicationId: endpointProfile.applicationId, + endpointId: endpointProfile.endpointId, + endpointRequest: endpointRequest + ) } nonisolated func convertToPublicEndpoint(_ endpointProfile: PinpointEndpointProfile) -> PinpointClientTypes.PublicEndpoint { @@ -181,7 +187,8 @@ actor EndpointClient: EndpointClientBehaviour { location: endpointProfile.location, metrics: endpointProfile.metrics, optOut: optOut, - user: endpointProfile.user) + user: endpointProfile.user + ) return publicEndpoint } @@ -264,16 +271,19 @@ extension PinpointClientTypes.EndpointDemographic { static let unknown = "Unknown" } - init(device: EndpointInformation, - locale: String = Locale.autoupdatingCurrent.identifier, - timezone: String = TimeZone.current.identifier) - { - self.init(appVersion: device.appVersion, - locale: locale, - make: Constants.appleMake, - model: device.model, - platform: device.platform.name, - platformVersion: device.platform.version, - timezone: timezone) + init( + device: EndpointInformation, + locale: String = Locale.autoupdatingCurrent.identifier, + timezone: String = TimeZone.current.identifier + ) { + self.init( + appVersion: device.appVersion, + locale: locale, + make: Constants.appleMake, + model: device.model, + platform: device.platform.name, + platformVersion: device.platform.version, + timezone: timezone + ) } } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift index 88155d70d6..9530f66267 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Endpoint/PinpointEndpointProfile.swift @@ -25,16 +25,17 @@ public struct PinpointEndpointProfile: Codable, Equatable { private(set) var attributes: [String: [String]] = [:] private(set) var metrics: [String: Double] = [:] - init(applicationId: String, - endpointId: String, - deviceToken: DeviceToken? = nil, - effectiveDate: Date = Date(), - isDebug: Bool = false, - isOptOut: Bool = false, - location: PinpointClientTypes.EndpointLocation = .init(), - demographic: PinpointClientTypes.EndpointDemographic = .init(), - user: PinpointClientTypes.EndpointUser = .init()) - { + init( + applicationId: String, + endpointId: String, + deviceToken: DeviceToken? = nil, + effectiveDate: Date = Date(), + isDebug: Bool = false, + isOptOut: Bool = false, + location: PinpointClientTypes.EndpointLocation = .init(), + demographic: PinpointClientTypes.EndpointDemographic = .init(), + user: PinpointClientTypes.EndpointUser = .init() + ) { self.applicationId = applicationId self.endpointId = endpointId self.deviceToken = deviceToken @@ -96,9 +97,10 @@ public struct PinpointEndpointProfile: Codable, Equatable { ) } - private mutating func setCustomProperty(_ value: UserProfilePropertyValue, - forKey key: String) - { + private mutating func setCustomProperty( + _ value: UserProfilePropertyValue, + forKey key: String + ) { if let value = value as? String { attributes[key] = [value] } else if let values = value as? [String] { diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift index 7b8fc44031..782c19ddbc 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/ActivityTracker.swift @@ -122,26 +122,33 @@ class ActivityTracker: ActivityTrackerBehaviour { applicationWillTerminateNotification ] - init(backgroundTrackingTimeout: TimeInterval = .infinity, - stateMachine: StateMachine? = nil) - { + init( + backgroundTrackingTimeout: TimeInterval = .infinity, + stateMachine: StateMachine? = nil + ) { self.backgroundTrackingTimeout = backgroundTrackingTimeout - self.stateMachine = stateMachine ?? StateMachine(initialState: .initializing, - resolver: ApplicationState.Resolver.resolve(currentState:event:)) + self.stateMachine = stateMachine ?? StateMachine( + initialState: .initializing, + resolver: ApplicationState.Resolver.resolve(currentState:event:) + ) for notification in ActivityTracker.notifications { - NotificationCenter.default.addObserver(self, - selector: #selector(handleApplicationStateChange), - name: notification, - object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(handleApplicationStateChange), + name: notification, + object: nil + ) } } deinit { for notification in ActivityTracker.notifications { - NotificationCenter.default.removeObserver(self, - name: notification, - object: nil) + NotificationCenter.default.removeObserver( + self, + name: notification, + object: nil + ) } stateMachineSubscriberToken = nil } diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/StateMachine.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/StateMachine.swift index 58bbe66676..32afd7d2c9 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/StateMachine.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/ActivityTracking/StateMachine.swift @@ -15,8 +15,10 @@ extension AnyCancellable: StateMachineSubscriberToken {} class StateMachine { typealias Reducer = (State, Event) -> State - private let queue = DispatchQueue(label: "com.amazonaws.Amplify.StateMachine<\(State.self), \(Event.self)>", - target: DispatchQueue.global()) + private let queue = DispatchQueue( + label: "com.amazonaws.Amplify.StateMachine<\(State.self), \(Event.self)>", + target: DispatchQueue.global() + ) private var reducer: Reducer #if canImport(Combine) diff --git a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift index 9a02da61c3..5d5e435299 100644 --- a/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift +++ b/AmplifyPlugins/Internal/Sources/InternalAWSPinpoint/Session/PinpointSession.swift @@ -30,18 +30,22 @@ public struct PinpointSession: Codable { private var state: State = .active - init(appId: String, - uniqueId: String) - { - self.sessionId = Self.generateSessionId(appId: appId, - uniqueId: uniqueId) + init( + appId: String, + uniqueId: String + ) { + self.sessionId = Self.generateSessionId( + appId: appId, + uniqueId: uniqueId + ) self.startTime = Date() } - init(sessionId: SessionId, - startTime: Date, - stopTime: Date?) - { + init( + sessionId: SessionId, + startTime: Date, + stopTime: Date? + ) { self.sessionId = sessionId self.startTime = startTime if let stopTime { @@ -85,9 +89,10 @@ public struct PinpointSession: Codable { state = .active } - private static func generateSessionId(appId: String, - uniqueId: String) -> SessionId - { + private static func generateSessionId( + appId: String, + uniqueId: String + ) -> SessionId { let now = Date() let dateFormatter = DateFormatter() dateFormatter.timeZone = TimeZone(abbreviation: Constants.Date.defaultTimezone) @@ -101,12 +106,16 @@ public struct PinpointSession: Codable { dateFormatter.dateFormat = Constants.Date.timeFormat let timestampTime = dateFormatter.string(from: now) - let appIdKey = appId.padding(toLength: Constants.maxAppKeyLength, - withPad: Constants.paddingChar, - startingAt: 0) - let uniqueIdKey = uniqueId.padding(toLength: Constants.maxUniqueIdLength, - withPad: Constants.paddingChar, - startingAt: 0) + let appIdKey = appId.padding( + toLength: Constants.maxAppKeyLength, + withPad: Constants.paddingChar, + startingAt: 0 + ) + let uniqueIdKey = uniqueId.padding( + toLength: Constants.maxUniqueIdLength, + withPad: Constants.paddingChar, + startingAt: 0 + ) // Create Session ID formatted as - - -