From 651f91b36789e7ba2119a57252283531a6a0352d Mon Sep 17 00:00:00 2001 From: Konstantin Kostov Date: Fri, 12 Dec 2025 14:11:14 +0100 Subject: [PATCH 1/2] docs: update readme to mention lint task, remove old lint rules --- .swift-format | 2 +- .swiftlint.yml | 64 -------------------------------------------------- README.md | 8 +++++++ 3 files changed, 9 insertions(+), 65 deletions(-) delete mode 100644 .swiftlint.yml diff --git a/.swift-format b/.swift-format index 8032757..4f29e40 100644 --- a/.swift-format +++ b/.swift-format @@ -67,4 +67,4 @@ "spacesAroundRangeFormationOperators" : false, "tabWidth" : 8, "version" : 1 -} \ No newline at end of file +} diff --git a/.swiftlint.yml b/.swiftlint.yml deleted file mode 100644 index 828eb0f..0000000 --- a/.swiftlint.yml +++ /dev/null @@ -1,64 +0,0 @@ -# By default, SwiftLint uses a set of sensible default rules you can adjust: -disabled_rules: # rule identifiers turned on by default to exclude from running - - function_body_length - - opening_brace - - trailing_comma - - function_parameter_count - - closure_parameter_position - - nesting -opt_in_rules: # some rules are turned off by default, so you need to opt-in - - empty_count # Find all the available rules by running: `swiftlint rules` - -# Alternatively, specify all rules explicitly by uncommenting this option: -# only_rules: # delete `disabled_rules` & `opt_in_rules` if using this -# - empty_parameters -# - vertical_whitespace - -included: # paths to include during linting. `--path` is ignored if present. - - Sources -excluded: # paths to ignore during linting. Takes precedence over `included`. - - Tests -analyzer_rules: # Rules run by `swiftlint analyze` - - explicit_self - -# configurable rules can be customized from this configuration file -# binary rules can set their severity level -force_cast: warning # implicitly -force_try: - severity: warning # explicitly -# rules that have both warning and error levels, can set just the warning level -# implicitly -line_length: 200 -# they can set both implicitly with an array -type_body_length: - - 1000 # warning - - 1400 # error -# or they can set both explicitly -file_length: - warning: 500 - error: 1200 -# naming rules can set warnings/errors for min_length and max_length -# additionally they can set excluded names -type_name: - min_length: 4 # only warning - max_length: # warning and error - warning: 40 - error: 50 - excluded: iPhone # excluded via string - allowed_symbols: ["_"] # these are allowed in type names -identifier_name: - min_length: # only min_length - error: 4 # only error - excluded: # excluded via string array - - id - - req - - key - - app - - App - - url - - URL - - res - - sql - - env - - telemetry_api_server_version -reporter: "github-actions-logging" # reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging) diff --git a/README.md b/README.md index 26477f7..7acc872 100644 --- a/README.md +++ b/README.md @@ -142,3 +142,11 @@ This allows for compatibility with other logging solutions, such as [swift-log]( Your PRs on TelemetryDeck's Swift SDK are very much welcome. Check out the [SwiftClientTester](https://github.com/TelemetryDeck/SwiftClientTester) project, which provides a harness you can use to work on the library and try out new things. When making a new release, run `./tag-release.sh MAJOR.MINOR.PATCH` to bump the version string in the SDK, create a new commit and tag that commit accordingly all in one step. + +The project includes a Makefile at the root with some useful commands: + +- `build`: Build the library +- `lint`: Applies all auto-correctable lint issues and reformats all source files +- `test`: Run unit tests + +Before finalising your PR, please run `make lint`. From b243b72b48813c3a7c75a9ff17e9370b9f6ed9f0 Mon Sep 17 00:00:00 2001 From: Konstantin Kostov Date: Fri, 12 Dec 2025 14:12:17 +0100 Subject: [PATCH 2/2] style: apply auto lint fixes --- Package.swift | 2 +- .../Signals/Signal+Helpers.swift | 3 +- Sources/TelemetryDeck/TelemetryClient.swift | 6 +- .../ArrayExtensionTests.swift | 7 +- .../CryptoHashingTests.swift | 54 ++-- .../TelemetryDeckTests/LogHandlerTests.swift | 7 +- .../SignalCacheConcurrencyTests.swift | 1 - .../SignalPayloadTests.swift | 7 +- .../TelemetryDeckTests.swift | 254 ++++++++++++++---- 9 files changed, 243 insertions(+), 98 deletions(-) diff --git a/Package.swift b/Package.swift index 21fd78c..0c5d48b 100644 --- a/Package.swift +++ b/Package.swift @@ -31,6 +31,6 @@ let package = Package( name: "TelemetryDeckTests", dependencies: ["TelemetryDeck"], swiftSettings: [.enableExperimentalFeature("StrictConcurrency")] - ) + ), ] ) diff --git a/Sources/TelemetryDeck/Signals/Signal+Helpers.swift b/Sources/TelemetryDeck/Signals/Signal+Helpers.swift index 76f6ef1..9ac52dc 100644 --- a/Sources/TelemetryDeck/Signals/Signal+Helpers.swift +++ b/Sources/TelemetryDeck/Signals/Signal+Helpers.swift @@ -109,8 +109,7 @@ extension DefaultSignalPayload { static var isTestFlight: Bool { guard !isDebug, !isSimulator else { return false } guard let receiptURL = Bundle.main.appStoreReceiptURL else { return false } - return receiptURL.lastPathComponent == "sandboxReceipt" || - receiptURL.path.contains("sandboxReceipt") + return receiptURL.lastPathComponent == "sandboxReceipt" || receiptURL.path.contains("sandboxReceipt") } /// Detects if the app is running in an App Store production environment. diff --git a/Sources/TelemetryDeck/TelemetryClient.swift b/Sources/TelemetryDeck/TelemetryClient.swift index 07f62a3..3e64e18 100644 --- a/Sources/TelemetryDeck/TelemetryClient.swift +++ b/Sources/TelemetryDeck/TelemetryClient.swift @@ -419,19 +419,19 @@ public final class TelemetryManager: @unchecked Sendable { private var _configuration: TelemetryManagerConfiguration var configuration: TelemetryManagerConfiguration { - get { queue.sync(flags: .barrier) { return _configuration } } + get { queue.sync(flags: .barrier) { _configuration } } set { queue.sync(flags: .barrier) { _configuration = newValue } } } private var _lastTimeImmediateSyncRequested: Date = .distantPast var lastTimeImmediateSyncRequested: Date { - get { queue.sync(flags: .barrier) { return _lastTimeImmediateSyncRequested } } + get { queue.sync(flags: .barrier) { _lastTimeImmediateSyncRequested } } set { queue.sync(flags: .barrier) { _lastTimeImmediateSyncRequested = newValue } } } private var _lastDateAppEnteredBackground: Date = .distantPast private var lastDateAppEnteredBackground: Date { - get { queue.sync(flags: .barrier) { return _lastDateAppEnteredBackground } } + get { queue.sync(flags: .barrier) { _lastDateAppEnteredBackground } } set { queue.sync(flags: .barrier) { _lastDateAppEnteredBackground = newValue } } } diff --git a/Tests/TelemetryDeckTests/ArrayExtensionTests.swift b/Tests/TelemetryDeckTests/ArrayExtensionTests.swift index f8826dc..50ae268 100644 --- a/Tests/TelemetryDeckTests/ArrayExtensionTests.swift +++ b/Tests/TelemetryDeckTests/ArrayExtensionTests.swift @@ -1,6 +1,7 @@ -@testable import TelemetryDeck import Testing +@testable import TelemetryDeck + enum ArrayExtensionTests { enum CountISODatesOnOrAfter { @Test @@ -32,7 +33,7 @@ enum ArrayExtensionTests { "2025-01-01", // Duplicate "2025-02-01", "2025-02-01", // Duplicate - "2025-03-01" + "2025-03-01", ] #expect(datesWithDuplicates.countISODatesOnOrAfter(cutoffISODate: "2025-01-01") == 5) @@ -58,7 +59,7 @@ enum ArrayExtensionTests { "2024-02-28", // End of February "2024-02-29", // Leap year day "2024-03-01", // Start of March - "2025-01-01" // Far future + "2025-01-01", // Far future ] // Test year boundaries diff --git a/Tests/TelemetryDeckTests/CryptoHashingTests.swift b/Tests/TelemetryDeckTests/CryptoHashingTests.swift index 0e3f33a..ac563be 100644 --- a/Tests/TelemetryDeckTests/CryptoHashingTests.swift +++ b/Tests/TelemetryDeckTests/CryptoHashingTests.swift @@ -1,41 +1,43 @@ -@testable import TelemetryDeck import Testing + +@testable import TelemetryDeck + #if canImport(CryptoKit) -import CryptoKit + import CryptoKit #endif struct CryptoHashingTests { #if canImport(CryptoKit) - @Test - func cryptoKitAndCommonCryptoHaveSameDigestStringResults() { - let stringToHash = "how do i get cowboy paint off a dog ." - let dataToHash = stringToHash.data(using: .utf8)! + @Test + func cryptoKitAndCommonCryptoHaveSameDigestStringResults() { + let stringToHash = "how do i get cowboy paint off a dog ." + let dataToHash = stringToHash.data(using: .utf8)! - let expectedDigestString = "5b8fab7cf45fcece0e99a05950611b7b355917e4fb6daa73fd3d7590764fa53b" + let expectedDigestString = "5b8fab7cf45fcece0e99a05950611b7b355917e4fb6daa73fd3d7590764fa53b" - #expect(expectedDigestString == CryptoHashing.sha256(string: stringToHash, salt: "")) - #expect(expectedDigestString == CryptoHashing.commonCryptoSha256(strData: dataToHash)) + #expect(expectedDigestString == CryptoHashing.sha256(string: stringToHash, salt: "")) + #expect(expectedDigestString == CryptoHashing.commonCryptoSha256(strData: dataToHash)) - // even though we already test if we can import CryptoKit, somehow this still fails on iOS 12, - // so we're gating it to iOS 13 et al. - if #available(watchOS 7, iOS 13, macOS 10.14, tvOS 13, *) { - // calling directly to prove that CryptoKit produces same reult, as ``sha256(str:)`` can fall back, - #expect(expectedDigestString == SHA256.hash(data: dataToHash).compactMap { String(format: "%02x", $0) }.joined()) + // even though we already test if we can import CryptoKit, somehow this still fails on iOS 12, + // so we're gating it to iOS 13 et al. + if #available(watchOS 7, iOS 13, macOS 10.14, tvOS 13, *) { + // calling directly to prove that CryptoKit produces same reult, as ``sha256(str:)`` can fall back, + #expect(expectedDigestString == SHA256.hash(data: dataToHash).compactMap { String(format: "%02x", $0) }.joined()) + } } - } - @Test - func saltedResultsAreDifferentFromUnsaltedResults() { - let stringToHash = "how do i get cowboy paint off a dog ." - let salt = "q8wMvgVW3LzGCRQiLSLk" - let expectedDigestString = "d46208db801b09cf055fedd7ae0390e9797fc00d1bcdcb3589ea075ca157e0d6" + @Test + func saltedResultsAreDifferentFromUnsaltedResults() { + let stringToHash = "how do i get cowboy paint off a dog ." + let salt = "q8wMvgVW3LzGCRQiLSLk" + let expectedDigestString = "d46208db801b09cf055fedd7ae0390e9797fc00d1bcdcb3589ea075ca157e0d6" - let secondSalt = "x21MTSq3MRSmLjVFsYIe" - let expectedSecondDigestString = "acb027bb031c0f73de26c6b8d0441d9c98449d582a538014c44ca49b4c299aa8" + let secondSalt = "x21MTSq3MRSmLjVFsYIe" + let expectedSecondDigestString = "acb027bb031c0f73de26c6b8d0441d9c98449d582a538014c44ca49b4c299aa8" - #expect(expectedDigestString == CryptoHashing.sha256(string: stringToHash, salt: salt)) - #expect(expectedSecondDigestString == CryptoHashing.sha256(string: stringToHash, salt: secondSalt)) - #expect(CryptoHashing.sha256(string: stringToHash, salt: salt) != CryptoHashing.sha256(string: stringToHash, salt: secondSalt)) - } + #expect(expectedDigestString == CryptoHashing.sha256(string: stringToHash, salt: salt)) + #expect(expectedSecondDigestString == CryptoHashing.sha256(string: stringToHash, salt: secondSalt)) + #expect(CryptoHashing.sha256(string: stringToHash, salt: salt) != CryptoHashing.sha256(string: stringToHash, salt: secondSalt)) + } #endif } diff --git a/Tests/TelemetryDeckTests/LogHandlerTests.swift b/Tests/TelemetryDeckTests/LogHandlerTests.swift index f8a08f3..06ca078 100644 --- a/Tests/TelemetryDeckTests/LogHandlerTests.swift +++ b/Tests/TelemetryDeckTests/LogHandlerTests.swift @@ -1,6 +1,7 @@ -@testable import TelemetryDeck import Testing +@testable import TelemetryDeck + actor LogHandlerTests { var counter: Int = 0 var lastLevel: LogHandler.LogLevel? @@ -17,7 +18,7 @@ actor LogHandlerTests { await self.increment() } } - + #expect(counter == 0) handler.log(.debug, message: "") @@ -40,7 +41,7 @@ actor LogHandlerTests { await self.setLastLevel(level) } } - + handler.log(message: "") try await Task.sleep(nanoseconds: 10_000_000) // 10 milliseconds #expect(lastLevel == .info) diff --git a/Tests/TelemetryDeckTests/SignalCacheConcurrencyTests.swift b/Tests/TelemetryDeckTests/SignalCacheConcurrencyTests.swift index 4b09e0e..cb6a5c1 100644 --- a/Tests/TelemetryDeckTests/SignalCacheConcurrencyTests.swift +++ b/Tests/TelemetryDeckTests/SignalCacheConcurrencyTests.swift @@ -86,7 +86,6 @@ struct SignalCacheConcurrencyTests { } } - /// Validates pop() correctly handles concurrent access without data races. /// Without barrier on pop(), concurrent calls can corrupt the array. /// Run multiple iterations to increase probability of catching race condition. diff --git a/Tests/TelemetryDeckTests/SignalPayloadTests.swift b/Tests/TelemetryDeckTests/SignalPayloadTests.swift index 82e7521..16ea46e 100644 --- a/Tests/TelemetryDeckTests/SignalPayloadTests.swift +++ b/Tests/TelemetryDeckTests/SignalPayloadTests.swift @@ -1,6 +1,7 @@ -@testable import TelemetryDeck import Testing +@testable import TelemetryDeck + struct DefaultSignalPayloadTests { @Test func isSimulatorOrTestFlight() { @@ -68,7 +69,7 @@ struct DefaultSignalPayloadTests { @Test func operatingSystem() { let expectedResult: String - + #if os(macOS) expectedResult = "macOS" #elseif os(iOS) @@ -84,7 +85,7 @@ struct DefaultSignalPayloadTests { #else return "Unknown Operating System" #endif - + #expect(expectedResult == DefaultSignalPayload.operatingSystem) print("operatingSystem", DefaultSignalPayload.operatingSystem) diff --git a/Tests/TelemetryDeckTests/TelemetryDeckTests.swift b/Tests/TelemetryDeckTests/TelemetryDeckTests.swift index 9655892..46794b7 100644 --- a/Tests/TelemetryDeckTests/TelemetryDeckTests.swift +++ b/Tests/TelemetryDeckTests/TelemetryDeckTests.swift @@ -1,6 +1,7 @@ -@testable import TelemetryDeck -import Testing import Foundation +import Testing + +@testable import TelemetryDeck struct TelemetryDeckTests { @Test @@ -13,49 +14,184 @@ struct TelemetryDeckTests { TelemetryDeck.signal("userLoggedIn", customUserID: "email") TelemetryDeck.signal("databaseUpdated", parameters: ["numberOfDatabaseEntries": "3831"]) } - + @Test func pushAndPop() { let signalCache = SignalCache(logHandler: nil) - + let signals: [SignalPostBody] = [ - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "01", sessionID: "01", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "02", sessionID: "02", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "03", sessionID: "03", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "04", sessionID: "04", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "05", sessionID: "05", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "06", sessionID: "06", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "07", sessionID: "07", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "08", sessionID: "08", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "09", sessionID: "09", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "10", sessionID: "10", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "11", sessionID: "11", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "12", sessionID: "12", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "13", sessionID: "13", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "14", sessionID: "14", type: "test", floatValue: nil, payload: [:], isTestMode: "true"), - .init(receivedAt: Date(), appID: UUID().uuidString, clientUser: "15", sessionID: "15", type: "test", floatValue: nil, payload: [:], isTestMode: "true") + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "01", + sessionID: "01", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "02", + sessionID: "02", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "03", + sessionID: "03", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "04", + sessionID: "04", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "05", + sessionID: "05", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "06", + sessionID: "06", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "07", + sessionID: "07", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "08", + sessionID: "08", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "09", + sessionID: "09", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "10", + sessionID: "10", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "11", + sessionID: "11", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "12", + sessionID: "12", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "13", + sessionID: "13", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "14", + sessionID: "14", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), + .init( + receivedAt: Date(), + appID: UUID().uuidString, + clientUser: "15", + sessionID: "15", + type: "test", + floatValue: nil, + payload: [:], + isTestMode: "true" + ), ] - + for signal in signals { signalCache.push(signal) } - + var allPoppedSignals: [SignalPostBody] = [] var poppedSignalsBatch: [SignalPostBody] = signalCache.pop() while !poppedSignalsBatch.isEmpty { allPoppedSignals.append(contentsOf: poppedSignalsBatch) poppedSignalsBatch = signalCache.pop() } - + #expect(signals.count == allPoppedSignals.count) allPoppedSignals.sort { lhs, rhs in lhs.type < rhs.type } - + #expect(signals == allPoppedSignals) } - + @Test(.disabled("this test is flaky"), .bug("https://github.com/TelemetryDeck/SwiftSDK/issues/200")) func signalEnrichers() throws { struct BasicEnricher: SignalEnricher { @@ -63,10 +199,10 @@ struct TelemetryDeckTests { ["isTestEnricher": "true"] } } - + let configuration = TelemetryManagerConfiguration(appID: UUID().uuidString) configuration.metadataEnrichers.append(BasicEnricher()) - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) TelemetryDeck.signal("testSignal") @@ -76,7 +212,7 @@ struct TelemetryDeckTests { let bodyItem = try #require(bodyItems.first) #expect(bodyItem.payload["isTestEnricher"] == "true") } - + @Test(.disabled("this test is flaky"), .bug("https://github.com/TelemetryDeck/SwiftSDK/issues/200")) func signalEnrichers_precedence() throws { struct BasicEnricher: SignalEnricher { @@ -84,10 +220,10 @@ struct TelemetryDeckTests { ["item": "A", "isDebug": "banana"] } } - + let configuration = TelemetryManagerConfiguration(appID: UUID().uuidString) configuration.metadataEnrichers.append(BasicEnricher()) - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) TelemetryDeck.signal("testSignal", parameters: ["item": "B"]) @@ -95,54 +231,54 @@ struct TelemetryDeckTests { let bodyItems = signalManager.processedSignals #expect(bodyItems.count == 1) let bodyItem = try #require(bodyItems.first) - #expect(bodyItem.payload["item"] == "B") // .send takes priority over enricher - #expect(bodyItem.payload["isDebug"] == "banana") // enricher takes priority over default payload + #expect(bodyItem.payload["item"] == "B") // .send takes priority over enricher + #expect(bodyItem.payload["isDebug"] == "banana") // enricher takes priority over default payload } - + @Test(.disabled("this test is flaky"), .bug("https://github.com/TelemetryDeck/SwiftSDK/issues/200")) func sendsSignals_withAnalyticsImplicitlyEnabled() { let YOUR_APP_ID = "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3" let configuration = TelemetryManagerConfiguration(appID: YOUR_APP_ID) - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) - + TelemetryDeck.signal("appOpenedRegularly") - + #expect(signalManager.processedSignalTypes.count == 1) } - + @Test(.disabled("this test is flaky"), .bug("https://github.com/TelemetryDeck/SwiftSDK/issues/200")) func sendsSignals_withAnalyticsExplicitlyEnabled() { let YOUR_APP_ID = "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3" let configuration = TelemetryManagerConfiguration(appID: YOUR_APP_ID) configuration.analyticsDisabled = false - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) - + TelemetryDeck.signal("appOpenedRegularly") - + #expect(signalManager.processedSignalTypes.count == 1) } - + @Test func doesNotSendSignals_withAnalyticsExplicitlyDisabled() { let YOUR_APP_ID = "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3" let configuration = TelemetryManagerConfiguration(appID: YOUR_APP_ID) configuration.analyticsDisabled = true - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) - + TelemetryDeck.signal("appOpenedRegularly") - + #expect(signalManager.processedSignalTypes.isEmpty == true) } - + @Test func doesNotSendSignals_withAnalyticsExplicitlyEnabled_inPreviewMode() { setenv("XCODE_RUNNING_FOR_PREVIEWS", "1", 1) @@ -151,26 +287,26 @@ struct TelemetryDeckTests { let configuration = TelemetryManagerConfiguration(appID: YOUR_APP_ID) configuration.analyticsDisabled = false - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) - + TelemetryDeck.signal("appOpenedRegularly") - + #expect(signalManager.processedSignalTypes.isEmpty == true) - + setenv("XCODE_RUNNING_FOR_PREVIEWS", "0", 1) } - + @Test(.disabled("this test is flaky"), .bug("https://github.com/TelemetryDeck/SwiftSDK/issues/200")) func sendsSignals_withNumercalValue() { let YOUR_APP_ID = "44e0f59a-60a2-4d4a-bf27-1f96ccb4aaa3" let configuration = TelemetryManagerConfiguration(appID: YOUR_APP_ID) - + let signalManager = FakeSignalManager() TelemetryManager.initialize(with: configuration, signalManager: signalManager) - + TelemetryDeck.signal("appOpenedRegularly", floatValue: 42) #expect(signalManager.processedSignals.first?.floatValue == 42) @@ -178,16 +314,22 @@ struct TelemetryDeckTests { } private class FakeSignalManager: @preconcurrency SignalManageable { - var processedSignalTypes = [String]() - var processedSignals = [SignalPostBody]() - + var processedSignalTypes: [String] = [] + var processedSignals: [SignalPostBody] = [] + @MainActor - func processSignal(_ signalType: String, parameters: [String: String], floatValue: Double?, customUserID: String?, configuration: TelemetryManagerConfiguration) { + func processSignal( + _ signalType: String, + parameters: [String: String], + floatValue: Double?, + customUserID: String?, + configuration: TelemetryManagerConfiguration + ) { processedSignalTypes.append(signalType) let enrichedMetadata: [String: String] = configuration.metadataEnrichers .map { $0.enrich(signalType: signalType, for: customUserID, floatValue: floatValue) } .reduce([String: String]()) { $0.applying($1) } - + let payload = DefaultSignalPayload.parameters .applying(enrichedMetadata) .applying(parameters)