Files
firebase-ios-sdk/FirebaseAuth/Tests/Unit/AuthNotificationManagerTests.swift
T

169 lines
6.8 KiB
Swift

// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#if os(iOS)
import Foundation
import XCTest
@testable import FirebaseAuth
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
class AuthNotificationManagerTests: XCTestCase {
/** @var kReceipt
@brief A fake receipt used for testing.
*/
private let kReceipt = "FAKE_RECEIPT"
/** @var kSecret
@brief A fake secret used for testing.
*/
private let kSecret = "FAKE_SECRET"
/** @property notificationManager
@brief The notification manager to forward.
*/
private var notificationManager: AuthNotificationManager?
/** @var modernDelegate
@brief The modern fake UIApplicationDelegate for testing.
*/
private var modernDelegate: FakeForwardingDelegate?
/** @var appCredentialManager
@brief A stubbed AppCredentialManager for testing.
*/
private var appCredentialManager: AuthAppCredentialManager?
override func setUp() {
let fakeKeychain = AuthKeychainServices(
service: "AuthNotificationManagerTests",
storage: FakeAuthKeychainStorage()
)
appCredentialManager = AuthAppCredentialManager(withKeychain: fakeKeychain)
let application = UIApplication.shared
notificationManager = AuthNotificationManager(withApplication: application,
appCredentialManager: appCredentialManager!)
modernDelegate = FakeForwardingDelegate(notificationManager!)
application.delegate = modernDelegate
}
/** @fn testForwardingModernDelegate
@brief Tests checking notification forwarding on modern fake delegate.
*/
func testForwardingModernDelegate() throws {
try verify(forwarding: true, delegate: XCTUnwrap(modernDelegate))
}
/** @fn testNotForwardingModernDelegate
@brief Tests checking notification not forwarding on modern fake delegate.
*/
func testNotForwardingModernDelegate() throws {
try verify(forwarding: false, delegate: XCTUnwrap(modernDelegate))
}
private func verify(forwarding: Bool, delegate: FakeForwardingDelegate) throws {
delegate.forwardsNotification = forwarding
let expectation = self.expectation(description: "callback")
notificationManager?.checkNotificationForwardingInternal { forwarded in
XCTAssertEqual(forwarded, forwarding)
expectation.fulfill()
}
XCTAssertFalse(delegate.notificationReceived)
let timeout = try XCTUnwrap(notificationManager?.timeout) * (forwarding ? 0.5 : 1.5)
waitForExpectations(timeout: timeout)
XCTAssertTrue(delegate.notificationReceived)
XCTAssertEqual(delegate.notificationHandled, forwarding)
}
/** @fn testCachedResult
@brief Test notification forwarding is only checked once.
*/
func testCachedResult() throws {
let delegate = try XCTUnwrap(modernDelegate)
try verify(forwarding: false, delegate: delegate)
modernDelegate?.notificationReceived = false
var calledBack = false
notificationManager?.checkNotificationForwardingInternal { isNotificationBeingForwarded in
XCTAssertFalse(isNotificationBeingForwarded)
calledBack = true
}
XCTAssertTrue(calledBack)
XCTAssertFalse(delegate.notificationReceived)
}
/** @fn testPassingToCredentialManager
@brief Test notification with the right structure is passed to credential manager.
*/
func testPassingToCredentialManager() async throws {
let payload = ["receipt": kReceipt, "secret": kSecret]
let notification = ["com.google.firebase.auth": payload]
// Stub appCredentialManager
let _ = await appCredentialManager?.didStartVerification(withReceipt: kReceipt, timeout: 0)
XCTAssertTrue(try XCTUnwrap(notificationManager?.canHandle(notification: notification)))
// JSON string form
let data = try JSONSerialization.data(withJSONObject: payload)
let string = String(data: data, encoding: .utf8)
let jsonNotification = ["com.google.firebase.auth": string as Any] as [AnyHashable: Any]
let _ = await appCredentialManager?.didStartVerification(withReceipt: kReceipt, timeout: 0)
XCTAssertTrue(try XCTUnwrap(notificationManager?.canHandle(notification: jsonNotification)))
}
/** @fn testNotHandling
@brief Test unrecognized notifications are not handled.
*/
func testNotHandling() throws {
let manager = try XCTUnwrap(notificationManager)
XCTAssertFalse(manager.canHandle(notification: ["random": "string"]))
XCTAssertFalse(manager
.canHandle(notification: ["com.google.firebase.auth": "something wrong"]))
// Missing secret.
XCTAssertFalse(manager
.canHandle(notification: ["com.google.firebase.auth": ["receipt": kReceipt]]))
// Missing receipt.
XCTAssertFalse(manager
.canHandle(notification: ["com.google.firebase.auth": ["secret": kSecret]]))
// Probing notification does not belong to this instance.
XCTAssertFalse(manager
.canHandle(notification: ["com.google.firebase.auth": ["warning": "asdf"]]))
}
private class FakeApplication: UIApplication {}
private class FakeForwardingDelegate: NSObject, UIApplicationDelegate {
let notificationManager: AuthNotificationManager
var forwardsNotification = false
var notificationReceived = false
var notificationHandled = false
init(_ notificationManager: AuthNotificationManager, forwardsNotification: Bool = false,
notificationReceived: Bool = false, notificationHandled: Bool = false) {
self.notificationManager = notificationManager
self.forwardsNotification = forwardsNotification
self.notificationReceived = notificationReceived
self.notificationHandled = notificationHandled
}
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult)
-> Void) {
notificationReceived = true
if forwardsNotification {
notificationHandled = notificationManager.canHandle(notification: userInfo)
}
}
}
}
#endif