Created
November 5, 2020 13:00
-
-
Save atimca/bceaa1355baeaabfde9aa802d1a86e1b to your computer and use it in GitHub Desktop.
Entwine+Blocking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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()) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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