Skip to content

Instantly share code, notes, and snippets.

@atimca
Created November 5, 2020 13:00
Show Gist options
  • Save atimca/bceaa1355baeaabfde9aa802d1a86e1b to your computer and use it in GitHub Desktop.
Save atimca/bceaa1355baeaabfde9aa802d1a86e1b to your computer and use it in GitHub Desktop.
Entwine+Blocking
//
// Copyright © 2020 maximsmirnov. All rights reserved.
//
import Entwine
public extension Signal {
var error: Failure? {
guard case .completion(.failure(let error)) = self else { return nil }
return error
}
}
//
// Copyright © 2020 maximsmirnov. All rights reserved.
//
import Combine
import Entwine
import EntwineTest
// todo: - Generalize examples
/**
Testable helper inspired by https://github.com/ReactiveX/RxSwift/tree/master/RxBlocking
```
// Example 1: When you want to test a closed system.
// Create a publisher testable publisher.
let testablePublisher = viewModel.statePublisher.asTesbalePublisher()
// Do your stuff which you want to test.
viewModel.accept(action: .loadPageData)
// Assert
XCTAssertEqual(
testablePublisher.toBlockingArray().last?.loadingState,
.loading
)
// Example 2: When you want to test a system which returns a publisher.
// Call an action from your "service" create a testable publisher from it.
let testablePublisher = service
.loadFeeds(categoryId: categoryId, location: location)
.asTestablePublisher()
// Assert
XCTAssertEqual(testablePublisher.toBlockingArray().count, 1)
XCTAssertEqual(testablePublisher.toBlockingArray().first, expectedFeeds)
```
*/
public struct TestablePublisher<Output, Failure: Error> {
private let scheduler: TestScheduler
private let subscriber: TestableSubscriber<Output, Failure>
public init(from publisher: AnyPublisher<Output, Failure>) {
self.scheduler = TestScheduler()
self.subscriber = scheduler.createTestableSubscriber(Output.self, Failure.self)
publisher.receive(subscriber: subscriber)
}
public func toBlockingArray() -> [Output] {
scheduler.resume()
return subscriber.recordedOutput.values
}
public func materialize() -> [Signal<Output, Failure>] {
scheduler.resume()
return subscriber.recordedOutput.events
}
}
public extension Publisher {
func asTestablePublisher() -> TestablePublisher<Output, Failure> {
TestablePublisher(from: self.eraseToAnyPublisher())
}
}
//
// Copyright © 2020 maximsmirnov. All rights reserved.
//
import Entwine
import EntwineTest
public extension TestSequence {
var events: [Signal<Input, Failure>] {
map(\.1)
}
var values: [Input] {
compactMap { (_, signal) -> Input? in
guard case .input(let value) = signal else { return nil }
return value
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment