Accessories for Apple's Combine Framework.
Entwine consists of three libraries (over two repositories) to be used in conjuction with Apple's Combine framework:
-
The Entwine Utilities library includes additional operators, subjects and utilities for working with Combine sequences. The package currently includes a
ReplaySubject
, awithLatest(from:)
operator and aPublishers.Factory
for rapidly defining publishers inline from any source. -
The EntwineTest library consists of tools for verifying expected behavior of Combine sequences. It houses a
TestScheduler
that uses virtual time, aTestablePublisher
that schedules a user-defined sequence of elements in absolute or relative time, and aTestableSubscriber
that record a time-stamped list of events that can be compared against expected behavior. -
The EntwineRx library is a small library maintained under a separate repository that contains bridging operators from RxSwift to Combine and vice versa making RxSwift and Combine work together seamlessly.
Note: EntwineRx is maintained as a separate Swift package to minimize the SPM dependency graph.
Use the Publishers.Factory
publisher from the Entwine package to effortlessly create a publisher that
meets Combine's backpressure requirements from any source. Find out more about the Entwine Utilities library.
Inline publisher creation for PhotoKit authorization status:
import Entwine
let photoKitAuthorizationStatus = Publishers.Factory<PHAuthorizationStatus, Never> { dispatcher in
let status = PHPhotoLibrary.authorizationStatus()
dispatcher.forward(status)
switch status {
case .notDetermined:
PHPhotoLibrary.requestAuthorization { newStatus in
dispatcher.forward(newStatus)
dispatcher.forward(completion: .finished)
}
default:
dispatcher.forward(completion: .finished)
}
return AnyCancellable {}
}
Use the TestScheduler
, TestablePublisher
and TestableSubscriber
to simulate Combine sequences and test against expected output. Find out more about the EntwineTest library
Testing Combine's map(_:)
operator:
import XCTest
import EntwineTest
func testMap() {
let testScheduler = TestScheduler(initialClock: 0)
// creates a publisher that will schedule it's elements relatively, at the point of subscription
let testablePublisher: TestablePublisher<String, Never> = testScheduler.createRelativeTestablePublisher([
(100, .input("a")),
(200, .input("b")),
(300, .input("c")),
])
let subjectUnderTest = testablePublisher.map { $0.uppercased() }
// schedules a subscription at 200, to be cancelled at 900
let results = testScheduler.start { subjectUnderTest }
XCTAssertEqual(results.recordedOutput, [
(200, .subscription), // subscribed at 200
(300, .input("A")), // received uppercased input @ 100 + subscription time
(400, .input("B")), // received uppercased input @ 200 + subscription time
(500, .input("C")), // received uppercased input @ 300 + subscription time
])
}
First, make sure you add the EntwineRx Swift Package (located in an external repo) as a dependency to your project.
Example coming soon
Entwine sits on top of Apple's Combine framework and therefore requires Xcode 11 and is has minimum deployment targets of macOS 10.15, iOS 13, tvOS 13 or watchOS 6.
Entwine is delivered via a Swift Package and can be installed either as a dependency to another Swift Package by adding it to the dependencies section of a Package.swift
file
or to an Xcode 11 project by via the File -> Swift Packages -> Add package dependency...
menu in Xcode 11.
Documentation for each package is available at:
- Entwine Documentation (Operators, Publishers and Accessories)
- EntwineTest Documentation (Tools for testing Combine sequence behavior)
- EntwineRx Documentation (Bridging operators for RxSwift)
This project is released under the MIT license