blob: de39a41bfb4edecf94cda8e2d15120fdb738720a [file] [log] [blame]
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//
// XCTestCase+NotificationExpectation.swift
//
public extension XCTestCase {
/// Creates and returns an expectation for a notification.
///
/// - Parameter notificationName: The name of the notification the
/// expectation observes.
/// - Parameter object: The object whose notifications the expectation will
/// receive; that is, only notifications with this object are observed by
/// the test case. If you pass nil, the expectation doesn't use
/// a notification's object to decide whether it is fulfilled.
/// - Parameter handler: If provided, the handler will be invoked when the
/// notification is observed. It will not be invoked on timeout. Use the
/// handler to further investigate if the notification fulfills the
/// expectation.
@discardableResult func expectation(forNotification notificationName: String, object objectToObserve: AnyObject?, handler: XCNotificationExpectationHandler? = nil) -> XCTestExpectation {
let objectDescription = objectToObserve == nil ? "any object" : "\(objectToObserve!)"
let expectation = self.expectation(description: "Expect notification '\(notificationName)' from " + objectDescription)
// Start observing the notification with specified name and object.
var observer: NSObjectProtocol? = nil
func removeObserver() {
if let observer = observer {
NotificationCenter.default.removeObserver(observer)
}
}
weak var weakExpectation = expectation
observer = NotificationCenter
.default
.addObserver(forName: Notification.Name(rawValue: notificationName),
object: objectToObserve,
queue: nil) {
notification in
guard let expectation = weakExpectation else {
removeObserver()
return
}
// If the handler is invoked, the test will
// only pass if true is returned.
if let handler = handler {
if handler(notification) {
expectation.fulfill()
removeObserver()
}
} else {
expectation.fulfill()
removeObserver()
}
}
return expectation
}
}