From 6a8cb18098250df6234deed5eeab05384fbd5b26 Mon Sep 17 00:00:00 2001 From: Ilias Pavlidakis Date: Wed, 27 Nov 2024 13:09:54 +0200 Subject: [PATCH] [Fix]Update deviceToken to empty once unregister void notifications Update doc tests change --- CHANGELOG.md | 3 +- .../06-advanced/03-callkit-integration.swift | 14 ++- .../CallKitPushNotificationAdapter.swift | 1 + .../CallKitPushNotificationAdapterTests.swift | 92 +++++++++++++------ 4 files changed, 79 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2ca6cd3..177245a9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). # Upcoming -### 🔄 Changed +### 🐞 Fixed +- By observing the `CallKitPushNotificationAdapter.deviceToken` you will be notified with an empty `deviceToken` value, once the object unregister push notifications. [#608](https://github.com/GetStream/stream-video-swift/pull/608) # [1.14.1](https://github.com/GetStream/stream-video-swift/releases/tag/1.14.1) _November 12, 2024_ diff --git a/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift b/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift index 319bf4c94..807dbeb3c 100644 --- a/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift +++ b/DocumentationTests/DocumentationTests/DocumentationTests/06-advanced/03-callkit-integration.swift @@ -86,11 +86,17 @@ fileprivate func content() { voIPTokenObservationCancellable = callKitPushNotificationAdapter.$deviceToken.sink { [streamVideo] updatedDeviceToken in Task { - if let lastVoIPToken { - try await streamVideo.deleteDevice(id: updatedDeviceToken) + do { + if let lastVoIPToken, !lastVoIPToken.isEmpty { + try await streamVideo.deleteDevice(id: lastVoIPToken) + } + if !updatedDeviceToken.isEmpty { + try await streamVideo.setVoipDevice(id: updatedDeviceToken) + } + lastVoIPToken = updatedDeviceToken + } catch { + print(error) } - try await streamVideo.setVoipDevice(id: updatedDeviceToken) - lastVoIPToken = updatedDeviceToken } } } diff --git a/Sources/StreamVideo/CallKit/CallKitPushNotificationAdapter.swift b/Sources/StreamVideo/CallKit/CallKitPushNotificationAdapter.swift index 76eadc5d8..eee6009ac 100644 --- a/Sources/StreamVideo/CallKit/CallKitPushNotificationAdapter.swift +++ b/Sources/StreamVideo/CallKit/CallKitPushNotificationAdapter.swift @@ -62,6 +62,7 @@ open class CallKitPushNotificationAdapter: NSObject, PKPushRegistryDelegate, Obs #else registry.delegate = nil registry.desiredPushTypes = [] + deviceToken = "" #endif } diff --git a/StreamVideoTests/CallKit/CallKitPushNotificationAdapterTests.swift b/StreamVideoTests/CallKit/CallKitPushNotificationAdapterTests.swift index 8f5d51ebe..d317cc8e4 100644 --- a/StreamVideoTests/CallKit/CallKitPushNotificationAdapterTests.swift +++ b/StreamVideoTests/CallKit/CallKitPushNotificationAdapterTests.swift @@ -44,25 +44,50 @@ final class CallKitPushNotificationAdapterTests: XCTestCase { XCTAssertTrue(subject.registry.desiredPushTypes?.isEmpty ?? false) } + func test_unregister_deviceTokenWasConfiguredCorrectly() { + let expectedDecodedToken = "test-device-token" + subject.register() + subject.pushRegistry( + subject.registry, + didUpdate: .dummy(expectedDecodedToken), + for: .voIP + ) + + XCTAssertEqual(subject.deviceToken.decodedHex, expectedDecodedToken) + subject.unregister() + + XCTAssertTrue(subject.deviceToken.isEmpty) + } + // MARK: - pushRegistry(_:didUpdate:for:) func test_pushRegistryDidUpdatePushCredentials_deviceTokenWasConfiguredCorrectly() { - simulateDeviceTokenFetch("mockDeviceToken") + let expected = "mock-device-token" + subject.pushRegistry( + subject.registry, + didUpdate: .dummy(expected), + for: .voIP + ) - XCTAssertEqual(subject.deviceToken, "6d6f636b446576696365546f6b656e") + XCTAssertEqual(subject.deviceToken.decodedHex, expected) } // MARK: - pushRegistry(_:didInvalidatePushTokenFor:) func test_pushRegistryDidInvalidatePushCredentials_deviceTokenWasConfiguredCorrectly() { - simulateDeviceTokenFetch("mockDeviceToken") + let expected = "mock-device-token" + subject.pushRegistry( + subject.registry, + didUpdate: .dummy(expected), + for: .voIP + ) subject.pushRegistry( subject.registry, didInvalidatePushTokenFor: .voIP ) - XCTAssertEqual(subject.deviceToken, "") + XCTAssertTrue(subject.deviceToken.isEmpty) } // MARK: - pushRegistry(_:didReceiveIncomingPushWith:for:completion:) @@ -97,20 +122,6 @@ final class CallKitPushNotificationAdapterTests: XCTestCase { // MARK: - Private helpers - private func simulateDeviceTokenFetch(_ token: String) { - let registry = subject.registry - let deviceToken = token.data(using: .utf8)! - let stubPushCredentials = MockPKPushCredentials() - stubPushCredentials.stubType = .voIP - stubPushCredentials.stubToken = deviceToken - - subject.pushRegistry( - registry, - didUpdate: stubPushCredentials, - for: .voIP - ) - } - @MainActor private func assertDidReceivePushNotification( _ content: CallKitPushNotificationAdapter.Content? = nil, @@ -173,20 +184,49 @@ final class CallKitPushNotificationAdapterTests: XCTestCase { // MARK: - Mocks -private final class MockPKPushCredentials: PKPushCredentials { +private final class MockPKPushPayload: PKPushPayload { var stubType: PKPushType = .voIP - var stubToken: Data! + var stubDictionaryPayload: [AnyHashable: Any] = [:] override var type: PKPushType { stubType } - override var token: Data { stubToken } + override var dictionaryPayload: [AnyHashable: Any] { stubDictionaryPayload } } -private final class MockPKPushPayload: PKPushPayload { +private extension PKPushCredentials { + private final class MockPKPushCredentials: PKPushCredentials { + private let inputToken: Data + override var token: Data { inputToken } + init(_ input: String) { + inputToken = Data(input.utf8) + super.init() + } + } - var stubType: PKPushType = .voIP - var stubDictionaryPayload: [AnyHashable: Any] = [:] + static func dummy(_ token: String) -> PKPushCredentials { + MockPKPushCredentials(token) + } +} - override var type: PKPushType { stubType } - override var dictionaryPayload: [AnyHashable: Any] { stubDictionaryPayload } +private extension String { + var decodedHex: String { + var data = Data() + var currentIndex = startIndex + + // Ensure the string has an even number of characters + guard count % 2 == 0 else { return "self" } + + while currentIndex < endIndex { + let nextIndex = index(currentIndex, offsetBy: 2) + let byteString = self[currentIndex..