114 lines
4.2 KiB
Swift
114 lines
4.2 KiB
Swift
#if canImport(Combine)
|
|
import XCTest
|
|
|
|
/// A name space for publisher expectations
|
|
public enum PublisherExpectations { }
|
|
|
|
/// The base protocol for PublisherExpectation. It is an implementation detail
|
|
/// that you are not supposed to use, as shown by the underscore prefix.
|
|
public protocol _PublisherExpectationBase {
|
|
/// Sets up an XCTestExpectation. This method is an implementation detail
|
|
/// that you are not supposed to use, as shown by the underscore prefix.
|
|
func _setup(_ expectation: XCTestExpectation)
|
|
|
|
/// Returns an object that waits for the expectation. If nil, expectation
|
|
/// is waited by the XCTestCase.
|
|
func _makeWaiter() -> XCTWaiter?
|
|
}
|
|
|
|
extension _PublisherExpectationBase {
|
|
public func _makeWaiter() -> XCTWaiter? { nil }
|
|
}
|
|
|
|
/// The protocol for publisher expectations.
|
|
///
|
|
/// You can build publisher expectations from Recorder returned by the
|
|
/// `Publisher.record()` method.
|
|
///
|
|
/// For example:
|
|
///
|
|
/// // The expectation for all published elements until completion
|
|
/// let publisher = ["foo", "bar", "baz"].publisher
|
|
/// let recorder = publisher.record()
|
|
/// let expectation = recorder.elements
|
|
///
|
|
/// When a test grants some time for the expectation to fulfill, use the
|
|
/// XCTest `wait(for:timeout:description)` method:
|
|
///
|
|
/// // SUCCESS: no timeout, no error
|
|
/// func testArrayPublisherPublishesArrayElements() throws {
|
|
/// let publisher = ["foo", "bar", "baz"].publisher
|
|
/// let recorder = publisher.record()
|
|
/// let expectation = recorder.elements
|
|
/// let elements = try wait(for: expectation, timeout: 1)
|
|
/// XCTAssertEqual(elements, ["foo", "bar", "baz"])
|
|
/// }
|
|
///
|
|
/// On the other hand, when the expectation is supposed to be immediately
|
|
/// fulfilled, use the PublisherExpectation `get()` method in order to grab the
|
|
/// expected value:
|
|
///
|
|
/// // SUCCESS: no error
|
|
/// func testArrayPublisherSynchronouslyPublishesArrayElements() throws {
|
|
/// let publisher = ["foo", "bar", "baz"].publisher
|
|
/// let recorder = publisher.record()
|
|
/// let elements = try recorder.elements.get()
|
|
/// XCTAssertEqual(elements, ["foo", "bar", "baz"])
|
|
/// }
|
|
public protocol PublisherExpectation: _PublisherExpectationBase {
|
|
/// The type of the expected value.
|
|
associatedtype Output
|
|
|
|
/// Returns the expected value, or throws an error if the
|
|
/// expectation fails.
|
|
///
|
|
/// For example:
|
|
///
|
|
/// // SUCCESS: no error
|
|
/// func testArrayPublisherSynchronouslyPublishesArrayElements() throws {
|
|
/// let publisher = ["foo", "bar", "baz"].publisher
|
|
/// let recorder = publisher.record()
|
|
/// let elements = try recorder.elements.get()
|
|
/// XCTAssertEqual(elements, ["foo", "bar", "baz"])
|
|
/// }
|
|
func get() throws -> Output
|
|
}
|
|
|
|
extension XCTestCase {
|
|
/// Waits for the publisher expectation to fulfill, and returns the
|
|
/// expected value.
|
|
///
|
|
/// For example:
|
|
///
|
|
/// // SUCCESS: no timeout, no error
|
|
/// func testArrayPublisherPublishesArrayElements() throws {
|
|
/// let publisher = ["foo", "bar", "baz"].publisher
|
|
/// let recorder = publisher.record()
|
|
/// let elements = try wait(for: recorder.elements, timeout: 1)
|
|
/// XCTAssertEqual(elements, ["foo", "bar", "baz"])
|
|
/// }
|
|
///
|
|
/// - parameter publisherExpectation: The publisher expectation.
|
|
/// - parameter timeout: The number of seconds within which the expectation
|
|
/// must be fulfilled.
|
|
/// - parameter description: A string to display in the test log for the
|
|
/// expectation, to help diagnose failures.
|
|
/// - throws: An error if the expectation fails.
|
|
public func wait<R: PublisherExpectation>(
|
|
for publisherExpectation: R,
|
|
timeout: TimeInterval,
|
|
description: String = "")
|
|
throws -> R.Output
|
|
{
|
|
let expectation = self.expectation(description: description)
|
|
publisherExpectation._setup(expectation)
|
|
if let waiter = publisherExpectation._makeWaiter() {
|
|
waiter.wait(for: [expectation], timeout: timeout)
|
|
} else {
|
|
wait(for: [expectation], timeout: timeout)
|
|
}
|
|
return try publisherExpectation.get()
|
|
}
|
|
}
|
|
#endif
|