From 59276b3c98630101143234080c37b8ee8e9b2246 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Wed, 19 Jul 2017 23:28:23 +0200 Subject: [PATCH 1/9] Add swiftlint config file, excluding the Carthage dir. --- .swiftlint.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .swiftlint.yml diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 000000000..31fd86d23 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,2 @@ +excluded: + - Carthage From 9ffdd4c2aefa3dd48d8db9fe63a1d7d56b791295 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Wed, 19 Jul 2017 23:40:56 +0200 Subject: [PATCH 2/9] Instead of excluding Carthage/, run Swiftlint only for Sources and Tests dirs. --- .swiftlint.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 31fd86d23..d1f1d288b 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,2 +1,3 @@ -excluded: - - Carthage +included: + - Sources + - Tests From ad249cf32aa56a42e03f411ecfa5cc91018ccbb3 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Wed, 19 Jul 2017 23:50:57 +0200 Subject: [PATCH 3/9] Run swiftlint autocorrect, fixing some formatting issues. Mostly trailing whitespace issues, 'tis true. Also disable the opening_brace rule, as it doesn't play well with arrays of closures. --- .swiftlint.yml | 2 + Sources/Atomic.swift | 2 +- Sources/Disposable.swift | 6 +- Sources/EventLogger.swift | 4 +- Sources/Flatten.swift | 27 +- Sources/Property.swift | 4 +- Sources/Scheduler.swift | 12 +- Sources/Signal.swift | 48 +- Sources/SignalProducer.swift | 26 +- Tests/LinuxMain.swift | 2 +- Tests/ReactiveSwiftTests/ActionSpec.swift | 10 +- Tests/ReactiveSwiftTests/FlattenSpec.swift | 376 +++++++------- .../SignalLifetimeSpec.swift | 1 - .../SignalProducerLiftingSpec.swift | 226 ++++----- .../SignalProducerNimbleMatchers.swift | 3 +- .../SignalProducerSpec.swift | 108 ++--- Tests/ReactiveSwiftTests/SignalSpec.swift | 457 +++++++++--------- Tests/ReactiveSwiftTests/TestError.swift | 2 - Tests/ReactiveSwiftTests/TestLogger.swift | 2 +- 19 files changed, 657 insertions(+), 661 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index d1f1d288b..60a752ef7 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,3 +1,5 @@ +disabled_rules: + - opening_brace included: - Sources - Tests diff --git a/Sources/Atomic.swift b/Sources/Atomic.swift index 0f75d1960..38bf5d6f0 100644 --- a/Sources/Atomic.swift +++ b/Sources/Atomic.swift @@ -256,7 +256,7 @@ public final class Atomic { return try action(&_value) } - + /// Atomically perform an arbitrary action using the current value of the /// variable. /// diff --git a/Sources/Disposable.swift b/Sources/Disposable.swift index 4b5c36e64..d363c6147 100644 --- a/Sources/Disposable.swift +++ b/Sources/Disposable.swift @@ -124,7 +124,7 @@ public final class CompositeDisposable: Disposable { self.disposables = Atomic(bag) self.state = UnsafeAtomicState(DisposableState.active) } - + /// Initialize a `CompositeDisposable` containing the given sequence of /// disposables. /// @@ -231,7 +231,7 @@ public final class CompositeDisposable: Disposable { /// - returns: An instance of `DisposableHandle` that can be used to opaquely /// remove the disposable later (if desired). @discardableResult - public static func +=(lhs: CompositeDisposable, rhs: @escaping () -> ()) -> Disposable? { + public static func +=(lhs: CompositeDisposable, rhs: @escaping () -> Void) -> Disposable? { return lhs.add(rhs) } } @@ -310,7 +310,7 @@ extension ScopedDisposable where Inner == CompositeDisposable { /// - returns: An instance of `DisposableHandle` that can be used to opaquely /// remove the disposable later (if desired). @discardableResult - public static func +=(lhs: ScopedDisposable, rhs: @escaping () -> ()) -> Disposable? { + public static func +=(lhs: ScopedDisposable, rhs: @escaping () -> Void) -> Disposable? { return lhs.inner.add(rhs) } } diff --git a/Sources/EventLogger.swift b/Sources/EventLogger.swift index 263101c1e..16d86a716 100644 --- a/Sources/EventLogger.swift +++ b/Sources/EventLogger.swift @@ -14,7 +14,7 @@ public enum LoggingEvent { case value, completed, failed, terminated, disposed, interrupted public static let allEvents: Set = [ - .value, .completed, .failed, .terminated, .disposed, .interrupted, + .value, .completed, .failed, .terminated, .disposed, .interrupted ] } @@ -22,7 +22,7 @@ public enum LoggingEvent { case starting, started, value, completed, failed, terminated, disposed, interrupted public static let allEvents: Set = [ - .starting, .started, .value, .completed, .failed, .terminated, .disposed, .interrupted, + .starting, .started, .value, .completed, .failed, .terminated, .disposed, .interrupted ] } } diff --git a/Sources/Flatten.swift b/Sources/Flatten.swift index bcf293d81..ae8f0910c 100644 --- a/Sources/Flatten.swift +++ b/Sources/Flatten.swift @@ -393,7 +393,7 @@ extension SignalProducer { public func concat(_ next: SignalProducer) -> SignalProducer { return SignalProducer, Error>([ self.producer, next ]).flatten(.concat) } - + /// `concat`s `value` onto `self`. /// /// - parameters: @@ -404,7 +404,7 @@ extension SignalProducer { public func concat(value: Value) -> SignalProducer { return self.concat(SignalProducer(value: value)) } - + /// `concat`s `self` onto initial `previous`. /// /// - parameters: @@ -415,7 +415,7 @@ extension SignalProducer { public func prefix(_ previous: SignalProducer) -> SignalProducer { return previous.concat(self) } - + /// `concat`s `self` onto initial `value`. /// /// - parameters: @@ -433,10 +433,10 @@ private final class ConcurrentFlattenState { /// The limit of active producers. let limit: UInt - + /// The number of active producers. var activeCount: UInt = 0 - + /// The producers waiting to be started. var queue: [Producer] = [] @@ -451,7 +451,7 @@ private final class ConcurrentFlattenState { init(limit: UInt) { self.limit = limit } - + /// Dequeue the next producer if one should be started. /// /// - returns: The `Producer` to start or `nil` if no producer should be @@ -489,7 +489,7 @@ extension Signal { .flatten(.merge) .startAndRetrieveSignal() } - + /// Merges the given signals into a single `Signal` that will emit all /// values from each of them, and complete when all of them have completed. /// @@ -511,7 +511,7 @@ extension SignalProducer { { return SignalProducer(producers).flatten(.merge) } - + /// Merges the given producers into a single `SignalProducer` that will emit /// all values from each of them, and complete when all of them have /// completed. @@ -645,7 +645,7 @@ extension SignalProducer where Value: SignalProducerConvertible, Error == Value. private struct LatestState { var outerSignalComplete: Bool = false var innerSignalComplete: Bool = true - + var replacingInnerSignal: Bool = false } @@ -790,7 +790,7 @@ extension Signal { public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == Error { return map(transform).flatten(strategy) } - + /// Maps each event from `signal` to a new signal, then flattens the /// resulting producers (into a signal of values), according to the /// semantics of the given strategy. @@ -822,7 +822,7 @@ extension Signal where Error == NoError { public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal { return map(transform).flatten(strategy) } - + /// Maps each event from `signal` to a new signal, then flattens the /// resulting signals (into a signal of values), according to the /// semantics of the given strategy. @@ -851,7 +851,7 @@ extension SignalProducer { public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == Error { return map(transform).flatten(strategy) } - + /// Maps each event from `self` to a new producer, then flattens the /// resulting producers (into a producer of values), according to the /// semantics of the given strategy. @@ -880,7 +880,7 @@ extension SignalProducer where Error == NoError { public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == Error { return map(transform).flatten(strategy) } - + /// Maps each event from `self` to a new producer, then flattens the /// resulting producers (into a producer of values), according to the /// semantics of the given strategy. @@ -897,7 +897,6 @@ extension SignalProducer where Error == NoError { } } - extension Signal { /// Catches any failure that may occur on the input signal, mapping to a new /// producer that starts in its place. diff --git a/Sources/Property.swift b/Sources/Property.swift index 4262f04f3..de5914b5f 100644 --- a/Sources/Property.swift +++ b/Sources/Property.swift @@ -375,7 +375,7 @@ extension PropertyProtocol where Value == Bool { public func negate() -> Property { return self.lift { $0.negate() } } - + /// Create a property that computes a logical AND between the latest values of `self` /// and `property`. /// @@ -386,7 +386,7 @@ extension PropertyProtocol where Value == Bool { public func and(_ property: P) -> Property where P.Value == Value { return self.lift(SignalProducer.and)(property) } - + /// Create a property that computes a logical OR between the latest values of `self` /// and `property`. /// diff --git a/Sources/Scheduler.swift b/Sources/Scheduler.swift index f8a26c5ff..5ecaa7b7e 100644 --- a/Sources/Scheduler.swift +++ b/Sources/Scheduler.swift @@ -192,11 +192,11 @@ public final class QueueScheduler: DateScheduler { } public let queue: DispatchQueue - + internal init(internalQueue: DispatchQueue) { queue = internalQueue } - + /// Initializes a scheduler that will target the given queue with its /// work. /// @@ -544,7 +544,7 @@ public final class TestScheduler: DateScheduler { public func run() { advance(to: Date.distantFuture) } - + /// Rewinds the virtualized clock by the given interval. /// This simulates that user changes device date. /// @@ -552,12 +552,12 @@ public final class TestScheduler: DateScheduler { /// - interval: An interval by which the current date will be retreated. public func rewind(by interval: DispatchTimeInterval) { lock.lock() - + let newDate = currentDate.addingTimeInterval(-interval) assert(currentDate.compare(newDate) != .orderedAscending) _currentDate = newDate - + lock.unlock() - + } } diff --git a/Sources/Signal.swift b/Sources/Signal.swift index c483ed9e8..45397c3a4 100644 --- a/Sources/Signal.swift +++ b/Sources/Signal.swift @@ -483,7 +483,7 @@ extension Signal { public func observeCompleted(_ action: @escaping () -> Void) -> Disposable? { return observe(Observer(completed: action)) } - + /// Observe `self` for its failure. /// /// - parameters: @@ -496,7 +496,7 @@ extension Signal { public func observeFailed(_ action: @escaping (Error) -> Void) -> Disposable? { return observe(Observer(failed: action)) } - + /// Observe `self` for its interruption. /// /// - note: If `self` has terminated, the closure would be invoked immediately. @@ -612,7 +612,7 @@ extension Signal { } } } - + /// Applies `transform` to values from `signal` and forwards values with non `nil` results unwrapped. /// - parameters: /// - transform: A closure that accepts a value from the `value` event and @@ -730,7 +730,7 @@ extension Signal { /// - returns: A signal that will yield an array of values when `self` /// completes. public func collect() -> Signal<[Value], Error> { - return collect { _,_ in false } + return collect { _, _ in false } } /// Collect at most `count` values from `self`, forward them as a single @@ -1096,7 +1096,7 @@ extension Signal { } private struct SampleState { - var latestValue: Value? = nil + var latestValue: Value? var isSignalCompleted: Bool = false var isSamplerCompleted: Bool = false } @@ -1136,7 +1136,7 @@ extension Signal { $0.isSignalCompleted = true return $0.isSamplerCompleted } - + if shouldComplete { observer.sendCompleted() } @@ -1145,7 +1145,7 @@ extension Signal { observer.sendInterrupted() } } - + disposable += sampler.observe { event in switch event { case .value(let samplerValue): @@ -1158,7 +1158,7 @@ extension Signal { $0.isSamplerCompleted = true return $0.isSignalCompleted } - + if shouldComplete { observer.sendCompleted() } @@ -1174,7 +1174,7 @@ extension Signal { return disposable } } - + /// Forward the latest value from `self` whenever `sampler` sends a `value` /// event. /// @@ -1323,17 +1323,17 @@ extension Signal { public func skip(until trigger: Signal<(), NoError>) -> Signal { return Signal { observer in let disposable = SerialDisposable() - + disposable.inner = trigger.observe { event in switch event { case .value, .completed: disposable.inner = self.observe(observer) - + case .failed, .interrupted: break } } - + return disposable } } @@ -1614,13 +1614,13 @@ extension Signal { while (buffer.count + 1) > count { buffer.remove(at: 0) } - + buffer.append(value) case let .failed(error): observer.send(error: error) case .completed: buffer.forEach(observer.send(value:)) - + observer.sendCompleted() case .interrupted: observer.sendInterrupted() @@ -1661,7 +1661,7 @@ extension Signal { public func zip(with other: Signal) -> Signal<(Value, U), Error> { return Signal.zip(self, other) } - + /// Forward the latest value on `scheduler` after at least `interval` /// seconds have passed since *the returned signal* last sent a value. /// @@ -1740,7 +1740,7 @@ extension Signal { } return state.pendingValue } - + if let pendingValue = pendingValue { observer.send(value: pendingValue) } @@ -1840,7 +1840,7 @@ extension Signal { return disposable } } - + /// Forward the latest value on `scheduler` after at least `interval` /// seconds have passed since `self` last sent a value. /// @@ -1871,7 +1871,7 @@ extension Signal { precondition(interval >= 0) let d = SerialDisposable() - + return Signal { observer in return self.observe { event in switch event { @@ -1906,7 +1906,7 @@ extension Signal { public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> Signal { return Signal { observer in var seenValues: Set = [] - + return self .observe { event in switch event { @@ -1916,7 +1916,7 @@ extension Signal { if inserted { fallthrough } - + case .failed, .completed, .interrupted: observer.action(event) } @@ -1940,8 +1940,8 @@ extension Signal where Value: Hashable { } private struct ThrottleState { - var previousDate: Date? = nil - var pendingValue: Value? = nil + var previousDate: Date? + var pendingValue: Value? } private enum ThrottleWhileState { @@ -2517,7 +2517,7 @@ extension Signal where Value == Bool { public func negate() -> Signal { return self.map(!) } - + /// Create a signal that computes a logical AND between the latest values of `self` /// and `signal`. /// @@ -2528,7 +2528,7 @@ extension Signal where Value == Bool { public func and(_ signal: Signal) -> Signal { return self.combineLatest(with: signal).map { $0.0 && $0.1 } } - + /// Create a signal that computes a logical OR between the latest values of `self` /// and `signal`. /// diff --git a/Sources/SignalProducer.swift b/Sources/SignalProducer.swift index 377a8e324..d9b1d755e 100644 --- a/Sources/SignalProducer.swift +++ b/Sources/SignalProducer.swift @@ -103,7 +103,7 @@ public struct SignalProducer { /// - value: A value that should be sent by the `Signal` in a `value` /// event. public init(value: Value) { - self.init { observer, lifetime in + self.init { observer, _ in observer.send(value: value) observer.sendCompleted() } @@ -120,7 +120,7 @@ public struct SignalProducer { /// - action: A action that yields a value to be sent by the `Signal` as /// a `value` event. public init(_ action: @escaping () -> Value) { - self.init { observer, lifetime in + self.init { observer, _ in observer.send(value: action()) observer.sendCompleted() } @@ -136,7 +136,7 @@ public struct SignalProducer { /// - parameters: /// - action: A closure that returns instance of `Result`. public init(_ action: @escaping () -> Result) { - self.init { observer, disposable in + self.init { observer, _ in action().analysis(ifSuccess: { value in observer.send(value: value) observer.sendCompleted() @@ -153,7 +153,7 @@ public struct SignalProducer { /// - error: An error that should be sent by the `Signal` in a `failed` /// event. public init(error: Error) { - self.init { observer, lifetime in + self.init { observer, _ in observer.send(error: error) } } @@ -194,7 +194,7 @@ public struct SignalProducer { observer.sendCompleted() } } - + /// Creates a producer for a Signal that will immediately send the values /// from the given sequence, then complete. /// @@ -209,7 +209,7 @@ public struct SignalProducer { /// A producer for a Signal that will immediately complete without sending /// any values. public static var empty: SignalProducer { - return self.init { observer, lifetime in + return self.init { observer, _ in observer.sendCompleted() } } @@ -344,7 +344,7 @@ extension SignalProducer { public func startWithCompleted(_ action: @escaping () -> Void) -> Disposable { return start(Signal.Observer(completed: action)) } - + /// Create a `Signal` from `self`, and observe its failure. /// /// - parameters: @@ -356,7 +356,7 @@ extension SignalProducer { public func startWithFailed(_ action: @escaping (Error) -> Void) -> Disposable { return start(Signal.Observer(failed: action)) } - + /// Create a `Signal` from `self`, and observe its interruption. /// /// - parameters: @@ -367,7 +367,7 @@ extension SignalProducer { public func startWithInterrupted(_ action: @escaping () -> Void) -> Disposable { return start(Signal.Observer(interrupted: action)) } - + /// Creates a `Signal` from the producer. /// /// This is equivalent to `SignalProducer.startWithSignal`, but it has @@ -380,7 +380,7 @@ extension SignalProducer { self.startWithSignal { signal, _ in result = signal } - + return result } @@ -682,7 +682,7 @@ extension SignalProducer { public func filterMap(_ transform: @escaping (Value) -> U?) -> SignalProducer { return lift { $0.filterMap(transform) } } - + /// Yield the first `count` values from the input producer. /// /// - precondition: `count` must be non-negative number. @@ -1585,7 +1585,7 @@ extension SignalProducer { /// Combines the values of all the given producers, in the manner described by /// `combineLatest(with:)`. - public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value), Error> where A.Value == Value, A.Error == Error , B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error { + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error { return .init { observer, lifetime in flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer) { Signal.combineLatest($0, $1, $2, $3, $4).observe(observer) } } @@ -2092,7 +2092,7 @@ extension SignalProducer where Value == Bool { public func negate() -> SignalProducer { return self.lift { $0.negate() } } - + /// Create a producer that computes a logical AND between the latest values of `self` /// and `producer`. /// diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 3c79b7ba1..9606abb42 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -17,5 +17,5 @@ Quick.QCKMain([ SignalLifetimeSpec.self, SignalProducerLiftingSpec.self, SignalProducerSpec.self, - SignalSpec.self, + SignalSpec.self ]) diff --git a/Tests/ReactiveSwiftTests/ActionSpec.swift b/Tests/ReactiveSwiftTests/ActionSpec.swift index debc5938f..87e8d4a89 100755 --- a/Tests/ReactiveSwiftTests/ActionSpec.swift +++ b/Tests/ReactiveSwiftTests/ActionSpec.swift @@ -62,19 +62,19 @@ class ActionSpec: QuickSpec { it("should retain the state property") { var property: MutableProperty? = MutableProperty(false) weak var weakProperty = property - + var action: Action<(), (), NoError>? = Action(state: property!, enabledIf: { _ in true }) { _, _ in return .empty } - + expect(weakProperty).toNot(beNil()) - + property = nil expect(weakProperty).toNot(beNil()) - + action = nil expect(weakProperty).to(beNil()) - + // Mute "unused variable" warning. _ = action } diff --git a/Tests/ReactiveSwiftTests/FlattenSpec.swift b/Tests/ReactiveSwiftTests/FlattenSpec.swift index ab92fa30c..92414000f 100644 --- a/Tests/ReactiveSwiftTests/FlattenSpec.swift +++ b/Tests/ReactiveSwiftTests/FlattenSpec.swift @@ -101,10 +101,10 @@ class FlattenSpec: QuickSpec { it("works with TestError and a TestError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -112,19 +112,19 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -132,38 +132,38 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -171,19 +171,19 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -191,19 +191,19 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -211,38 +211,38 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -250,23 +250,23 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with Sequence as a value") { let (signal, innerObserver) = Signal<[Int], NoError>.pipe() let sequence = [1, 2, 3] var observedValues = [Int]() - + signal .flatten() .observeValues { value in observedValues.append(value) } - + innerObserver.send(value: sequence) expect(observedValues) == sequence } @@ -286,15 +286,15 @@ class FlattenSpec: QuickSpec { .flatten(.latest) } } - + describe("SignalProducer.flatten()") { it("works with TestError and a TestError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -302,19 +302,19 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -322,38 +322,38 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -361,19 +361,19 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -381,19 +381,19 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -401,38 +401,38 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatten(.latest) @@ -440,23 +440,23 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: inner) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with Sequence as a value") { let sequence = [1, 2, 3] var observedValues = [Int]() - + let producer = SignalProducer<[Int], NoError>(value: sequence) producer .flatten() .startWithValues { value in observedValues.append(value) } - + expect(observedValues) == sequence } @@ -475,15 +475,15 @@ class FlattenSpec: QuickSpec { .flatten(.latest) } } - + describe("Signal.flatMap()") { it("works with TestError and a TestError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -491,19 +491,19 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -511,38 +511,38 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError Signal") { typealias Inner = Signal typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -550,19 +550,19 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -570,19 +570,19 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -590,38 +590,38 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = Signal - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -629,7 +629,7 @@ class FlattenSpec: QuickSpec { .observeValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 @@ -645,15 +645,15 @@ class FlattenSpec: QuickSpec { .flatMap(.latest) { _ in Property(value: 0) } } } - + describe("SignalProducer.flatMap()") { it("works with TestError and a TestError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -661,19 +661,19 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -681,38 +681,38 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError Signal") { typealias Inner = Signal typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -720,19 +720,19 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -740,19 +740,19 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a TestError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -760,38 +760,38 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with NoError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 } - + it("works with TestError and a NoError SignalProducer") { typealias Inner = SignalProducer typealias Outer = SignalProducer - + let (inner, innerObserver) = Inner.pipe() let (outer, outerObserver) = Outer.pipe() - + var observed: Int? = nil outer .flatMap(.latest) { _ in inner } @@ -799,7 +799,7 @@ class FlattenSpec: QuickSpec { .startWithValues { value in observed = value } - + outerObserver.send(value: 4) innerObserver.send(value: 4) expect(observed) == 4 @@ -815,132 +815,132 @@ class FlattenSpec: QuickSpec { .flatMap(.latest) { _ in Property(value: 0) } } } - + describe("Signal.merge()") { it("should emit values from all signals") { let (signal1, observer1) = Signal.pipe() let (signal2, observer2) = Signal.pipe() - + let mergedSignals = Signal.merge([signal1, signal2]) - + var lastValue: Int? mergedSignals.observeValues { lastValue = $0 } - + expect(lastValue).to(beNil()) - + observer1.send(value: 1) expect(lastValue) == 1 - + observer2.send(value: 2) expect(lastValue) == 2 - + observer1.send(value: 3) expect(lastValue) == 3 } - + it("should not stop when one signal completes") { let (signal1, observer1) = Signal.pipe() let (signal2, observer2) = Signal.pipe() - + let mergedSignals = Signal.merge([signal1, signal2]) - + var lastValue: Int? mergedSignals.observeValues { lastValue = $0 } - + expect(lastValue).to(beNil()) - + observer1.send(value: 1) expect(lastValue) == 1 - + observer1.sendCompleted() expect(lastValue) == 1 - + observer2.send(value: 2) expect(lastValue) == 2 } - + it("should complete when all signals complete") { let (signal1, observer1) = Signal.pipe() let (signal2, observer2) = Signal.pipe() - + let mergedSignals = Signal.merge([signal1, signal2]) - + var completed = false mergedSignals.observeCompleted { completed = true } - + expect(completed) == false - + observer1.send(value: 1) expect(completed) == false - + observer1.sendCompleted() expect(completed) == false - + observer2.sendCompleted() expect(completed) == true } } - + describe("SignalProducer.merge()") { it("should emit values from all producers") { let (signal1, observer1) = SignalProducer.pipe() let (signal2, observer2) = SignalProducer.pipe() - + let mergedSignals = SignalProducer.merge([signal1, signal2]) - + var lastValue: Int? mergedSignals.startWithValues { lastValue = $0 } - + expect(lastValue).to(beNil()) - + observer1.send(value: 1) expect(lastValue) == 1 - + observer2.send(value: 2) expect(lastValue) == 2 - + observer1.send(value: 3) expect(lastValue) == 3 } - + it("should not stop when one producer completes") { let (signal1, observer1) = SignalProducer.pipe() let (signal2, observer2) = SignalProducer.pipe() - + let mergedSignals = SignalProducer.merge([signal1, signal2]) - + var lastValue: Int? mergedSignals.startWithValues { lastValue = $0 } - + expect(lastValue).to(beNil()) - + observer1.send(value: 1) expect(lastValue) == 1 - + observer1.sendCompleted() expect(lastValue) == 1 - + observer2.send(value: 2) expect(lastValue) == 2 } - + it("should complete when all producers complete") { let (signal1, observer1) = SignalProducer.pipe() let (signal2, observer2) = SignalProducer.pipe() - + let mergedSignals = SignalProducer.merge([signal1, signal2]) - + var completed = false mergedSignals.startWithCompleted { completed = true } - + expect(completed) == false - + observer1.send(value: 1) expect(completed) == false - + observer1.sendCompleted() expect(completed) == false - + observer2.sendCompleted() expect(completed) == true } @@ -969,43 +969,43 @@ class FlattenSpec: QuickSpec { it("should emit initial value") { let (signal, observer) = SignalProducer.pipe() - + let mergedSignals = signal.prefix(SignalProducer(value: 0)) - + var lastValue: Int? mergedSignals.startWithValues { lastValue = $0 } - + expect(lastValue) == 0 - + observer.send(value: 1) expect(lastValue) == 1 - + observer.send(value: 2) expect(lastValue) == 2 - + observer.send(value: 3) expect(lastValue) == 3 } } - + describe("SignalProducer.concat(value:)") { it("should emit final value") { let (signal, observer) = SignalProducer.pipe() - + let mergedSignals = signal.concat(value: 4) - + var lastValue: Int? mergedSignals.startWithValues { lastValue = $0 } - + observer.send(value: 1) expect(lastValue) == 1 - + observer.send(value: 2) expect(lastValue) == 2 - + observer.send(value: 3) expect(lastValue) == 3 - + observer.sendCompleted() expect(lastValue) == 4 } diff --git a/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift b/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift index 03ce1bff4..20ae31aac 100644 --- a/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift @@ -37,7 +37,6 @@ class SignalLifetimeSpec: QuickSpec { expect(disposable.isDisposed) == true } - it("should automatically interrupt if the input observer is not retained, even if there are still one or more active observer") { let disposable = AnyDisposable() var isInterrupted = false diff --git a/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift b/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift index 6ff1ff4fe..5d4330f52 100644 --- a/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift @@ -37,7 +37,7 @@ class SignalProducerLiftingSpec: QuickSpec { expect(lastValue) == "2" } } - + describe("mapError") { it("should transform the errors of the signal") { let (producer, observer) = SignalProducer.pipe() @@ -276,9 +276,9 @@ class SignalProducerLiftingSpec: QuickSpec { // Subsequent values should still be held up by the scheduler // not getting run expect(output) == ["🎃"] - + scheduler.run() - + expect(output) == ["🎃", "😾"] } @@ -299,16 +299,16 @@ class SignalProducerLiftingSpec: QuickSpec { isOnTestQueue = DispatchQueue.getSpecific(key: labelKey) == "test queue" return tuple.character } - + // Start the signal, appending future values to the output array theLens.startWithValues { value in output.append(value) } testQueue.resume() - + expect(isOnTestQueue).to(beFalse()) expect(output).to(beEmpty()) - + tupleObserver.send(value: initialValue) - + expect(isOnTestQueue).toEventually(beTrue()) expect(output).toEventually(equal(["🎃"])) } @@ -641,14 +641,14 @@ class SignalProducerLiftingSpec: QuickSpec { expect(lastValue) == 1 } } - + describe("skipUntil") { var producer: SignalProducer! var observer: Signal.Observer! var triggerObserver: Signal<(), NoError>.Observer! - + var lastValue: Int? = nil - + beforeEach { let (baseProducer, baseIncomingObserver) = SignalProducer.pipe() let (triggerProducer, incomingTriggerObserver) = SignalProducer<(), NoError>.pipe() @@ -656,9 +656,9 @@ class SignalProducerLiftingSpec: QuickSpec { producer = baseProducer.skip(until: triggerProducer) observer = baseIncomingObserver triggerObserver = incomingTriggerObserver - + lastValue = nil - + producer.start { event in switch event { case let .value(value): @@ -668,30 +668,30 @@ class SignalProducerLiftingSpec: QuickSpec { } } } - + it("should skip values until the trigger fires") { expect(lastValue).to(beNil()) - + observer.send(value: 1) expect(lastValue).to(beNil()) - + observer.send(value: 2) expect(lastValue).to(beNil()) - + triggerObserver.send(value: ()) observer.send(value: 0) expect(lastValue) == 0 } - + it("should skip values until the trigger completes") { expect(lastValue).to(beNil()) - + observer.send(value: 1) expect(lastValue).to(beNil()) - + observer.send(value: 2) expect(lastValue).to(beNil()) - + triggerObserver.sendCompleted() observer.send(value: 0) expect(lastValue) == 0 @@ -727,11 +727,11 @@ class SignalProducerLiftingSpec: QuickSpec { expect(lastValue) == 2 expect(completed) == true } - + it("should complete immediately after taking given number of values") { let numbers = [ 1, 2, 4, 4, 5 ] let testScheduler = TestScheduler() - + let producer: SignalProducer = SignalProducer { observer, _ in // workaround `Class declaration cannot close over value 'observer' defined in outer scope` let observer = observer @@ -742,13 +742,13 @@ class SignalProducerLiftingSpec: QuickSpec { } } } - + var completed = false - + producer .take(first: numbers.count) .startWithCompleted { completed = true } - + expect(completed) == false testScheduler.run() expect(completed) == true @@ -917,10 +917,10 @@ class SignalProducerLiftingSpec: QuickSpec { expectedValues .flatMap { $0 } .forEach(observer.send(value:)) - + observer.sendCompleted() } - + } describe("takeUntil") { @@ -970,13 +970,13 @@ class SignalProducerLiftingSpec: QuickSpec { it("should take values until the trigger completes") { expect(lastValue).to(beNil()) - + observer.send(value: 1) expect(lastValue) == 1 - + observer.send(value: 2) expect(lastValue) == 2 - + expect(completed) == false triggerObserver.sendCompleted() expect(completed) == true @@ -1120,11 +1120,11 @@ class SignalProducerLiftingSpec: QuickSpec { producer .observe(on: testScheduler) .startWithValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) expect(result).to(beEmpty()) - + testScheduler.run() expect(result) == [ 1, 2 ] } @@ -1142,10 +1142,10 @@ class SignalProducerLiftingSpec: QuickSpec { observer.sendCompleted() } } - + var result: [Int] = [] var completed = false - + producer .delay(10, on: testScheduler) .start { event in @@ -1158,14 +1158,14 @@ class SignalProducerLiftingSpec: QuickSpec { break } } - + testScheduler.advance(by: .seconds(4)) // send initial value expect(result).to(beEmpty()) - + testScheduler.advance(by: .seconds(10)) // send second value and receive first expect(result) == [ 1 ] expect(completed) == false - + testScheduler.advance(by: .seconds(10)) // send second value and receive first expect(result) == [ 1, 2 ] expect(completed) == true @@ -1181,13 +1181,13 @@ class SignalProducerLiftingSpec: QuickSpec { observer.send(error: TestError.default) } } - + var errored = false - + producer .delay(10, on: testScheduler) .startWithFailed { _ in errored = true } - + testScheduler.advance() expect(errored) == true } @@ -1244,16 +1244,16 @@ class SignalProducerLiftingSpec: QuickSpec { scheduler.rewind(by: .seconds(2)) expect(values) == [ 0, 2, 3 ] - + observer.send(value: 6) scheduler.advance() expect(values) == [ 0, 2, 3, 6 ] - + observer.send(value: 7) observer.send(value: 8) scheduler.advance() expect(values) == [ 0, 2, 3, 6 ] - + scheduler.run() expect(values) == [ 0, 2, 3, 6, 8 ] } @@ -1291,7 +1291,7 @@ class SignalProducerLiftingSpec: QuickSpec { var sampledProducer: SignalProducer<(Int, String), NoError>! var observer: Signal.Observer! var samplerObserver: Signal.Observer! - + beforeEach { let (producer, incomingObserver) = SignalProducer.pipe() let (sampler, incomingSamplerObserver) = SignalProducer.pipe() @@ -1299,55 +1299,55 @@ class SignalProducerLiftingSpec: QuickSpec { observer = incomingObserver samplerObserver = incomingSamplerObserver } - + it("should forward the latest value when the sampler fires") { var result: [String] = [] sampledProducer.startWithValues { result.append("\($0.0)\($0.1)") } - + observer.send(value: 1) observer.send(value: 2) samplerObserver.send(value: "a") expect(result) == [ "2a" ] } - + it("should do nothing if sampler fires before signal receives value") { var result: [String] = [] sampledProducer.startWithValues { result.append("\($0.0)\($0.1)") } - + samplerObserver.send(value: "a") expect(result).to(beEmpty()) } - + it("should send lates value multiple times when sampler fires multiple times") { var result: [String] = [] sampledProducer.startWithValues { result.append("\($0.0)\($0.1)") } - + observer.send(value: 1) samplerObserver.send(value: "a") samplerObserver.send(value: "b") expect(result) == [ "1a", "1b" ] } - + it("should complete when both inputs have completed") { var completed = false sampledProducer.startWithCompleted { completed = true } - + observer.sendCompleted() expect(completed) == false - + samplerObserver.sendCompleted() expect(completed) == true } - + it("should emit an initial value if the sampler is a synchronous SignalProducer") { let producer = SignalProducer([1]) let sampler = SignalProducer(value: "a") - + let result = producer.sample(with: sampler) - + var valueReceived: String? result.startWithValues { valueReceived = "\($0.0)\($0.1)" } - + expect(valueReceived) == "1a" } } @@ -1356,7 +1356,7 @@ class SignalProducerLiftingSpec: QuickSpec { var sampledProducer: SignalProducer! var observer: Signal.Observer! var samplerObserver: Signal<(), NoError>.Observer! - + beforeEach { let (producer, incomingObserver) = SignalProducer.pipe() let (sampler, incomingSamplerObserver) = SignalProducer<(), NoError>.pipe() @@ -1364,29 +1364,29 @@ class SignalProducerLiftingSpec: QuickSpec { observer = incomingObserver samplerObserver = incomingSamplerObserver } - + it("should forward the latest value when the sampler fires") { var result: [Int] = [] sampledProducer.startWithValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) samplerObserver.send(value: ()) expect(result) == [ 2 ] } - + it("should do nothing if sampler fires before signal receives value") { var result: [Int] = [] sampledProducer.startWithValues { result.append($0) } - + samplerObserver.send(value: ()) expect(result).to(beEmpty()) } - + it("should send lates value multiple times when sampler fires multiple times") { var result: [Int] = [] sampledProducer.startWithValues { result.append($0) } - + observer.send(value: 1) samplerObserver.send(value: ()) samplerObserver.send(value: ()) @@ -1396,10 +1396,10 @@ class SignalProducerLiftingSpec: QuickSpec { it("should complete when both inputs have completed") { var completed = false sampledProducer.startWithCompleted { completed = true } - + observer.sendCompleted() expect(completed) == false - + samplerObserver.sendCompleted() expect(completed) == true } @@ -1407,12 +1407,12 @@ class SignalProducerLiftingSpec: QuickSpec { it("should emit an initial value if the sampler is a synchronous SignalProducer") { let producer = SignalProducer([1]) let sampler = SignalProducer<(), NoError>(value: ()) - + let result = producer.sample(on: sampler) - + var valueReceived: Int? result.startWithValues { valueReceived = $0 } - + expect(valueReceived) == 1 } @@ -1593,7 +1593,7 @@ class SignalProducerLiftingSpec: QuickSpec { var combinedProducer: SignalProducer<(Int, Double), NoError>! var observer: Signal.Observer! var otherObserver: Signal.Observer! - + beforeEach { let (producer, incomingObserver) = SignalProducer.pipe() let (otherSignal, incomingOtherObserver) = SignalProducer.pipe() @@ -1601,19 +1601,19 @@ class SignalProducerLiftingSpec: QuickSpec { observer = incomingObserver otherObserver = incomingOtherObserver } - + it("should forward the latest values from both inputs") { var latest: (Int, Double)? combinedProducer.startWithValues { latest = $0 } - + observer.send(value: 1) expect(latest).to(beNil()) - + // is there a better way to test tuples? otherObserver.send(value: 1.5) expect(latest?.0) == 1 expect(latest?.1) == 1.5 - + observer.send(value: 2) expect(latest?.0) == 2 expect(latest?.1) == 1.5 @@ -1622,10 +1622,10 @@ class SignalProducerLiftingSpec: QuickSpec { it("should complete when both inputs have completed") { var completed = false combinedProducer.startWithCompleted { completed = true } - + observer.sendCompleted() expect(completed) == false - + otherObserver.sendCompleted() expect(completed) == true } @@ -1705,9 +1705,9 @@ class SignalProducerLiftingSpec: QuickSpec { producer .materialize() .startWithValues { latestEvent = $0 } - + observer.send(value: 2) - + expect(latestEvent).toNot(beNil()) if let latestEvent = latestEvent { switch latestEvent { @@ -1717,7 +1717,7 @@ class SignalProducerLiftingSpec: QuickSpec { fail() } } - + observer.send(error: TestError.default) if let latestEvent = latestEvent { switch latestEvent { @@ -1734,24 +1734,24 @@ class SignalProducerLiftingSpec: QuickSpec { typealias IntEvent = Signal.Event var observer: Signal.Observer! var dematerialized: SignalProducer! - + beforeEach { let (producer, incomingObserver) = SignalProducer.pipe() observer = incomingObserver dematerialized = producer.dematerialize() } - + it("should send values for Value events") { var result: [Int] = [] dematerialized .assumeNoErrors() .startWithValues { result.append($0) } - + expect(result).to(beEmpty()) - + observer.send(value: .value(2)) expect(result) == [ 2 ] - + observer.send(value: .value(4)) expect(result) == [ 2, 4 ] } @@ -1759,9 +1759,9 @@ class SignalProducerLiftingSpec: QuickSpec { it("should error out for Error events") { var errored = false dematerialized.startWithFailed { _ in errored = true } - + expect(errored) == false - + observer.send(value: .failed(TestError.default)) expect(errored) == true } @@ -1769,7 +1769,7 @@ class SignalProducerLiftingSpec: QuickSpec { it("should complete early for Completed events") { var completed = false dematerialized.startWithCompleted { completed = true } - + expect(completed) == false observer.send(value: IntEvent.completed) expect(completed) == true @@ -1779,25 +1779,25 @@ class SignalProducerLiftingSpec: QuickSpec { describe("takeLast") { var observer: Signal.Observer! var lastThree: SignalProducer! - + beforeEach { let (producer, incomingObserver) = SignalProducer.pipe() observer = incomingObserver lastThree = producer.take(last: 3) } - + it("should send the last N values upon completion") { var result: [Int] = [] lastThree .assumeNoErrors() .startWithValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) observer.send(value: 3) observer.send(value: 4) expect(result).to(beEmpty()) - + observer.sendCompleted() expect(result) == [ 2, 3, 4 ] } @@ -1807,13 +1807,13 @@ class SignalProducerLiftingSpec: QuickSpec { lastThree .assumeNoErrors() .startWithValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) observer.sendCompleted() expect(result) == [ 1, 2 ] } - + it("should send nothing when errors") { var result: [Int] = [] var errored = false @@ -1827,12 +1827,12 @@ class SignalProducerLiftingSpec: QuickSpec { break } } - + observer.send(value: 1) observer.send(value: 2) observer.send(value: 3) expect(errored) == false - + observer.send(error: TestError.default) expect(errored) == true expect(result).to(beEmpty()) @@ -1917,93 +1917,93 @@ class SignalProducerLiftingSpec: QuickSpec { let producer = baseProducer.attempt { _ in return .success(()) } - + var current: Int? producer .assumeNoErrors() .startWithValues { value in current = value } - + for value in 1...5 { observer.send(value: value) expect(current) == value } } - + it("should error if an attempt fails") { let (baseProducer, observer) = SignalProducer.pipe() let producer = baseProducer.attempt { _ in return .failure(.default) } - + var error: TestError? producer.startWithFailed { err in error = err } - + observer.send(value: 42) expect(error) == TestError.default } } - + describe("attemptMap") { it("should forward mapped values upon success") { let (baseProducer, observer) = SignalProducer.pipe() let producer = baseProducer.attemptMap { num -> Result in return .success(num % 2 == 0) } - + var even: Bool? producer .assumeNoErrors() .startWithValues { value in even = value } - + observer.send(value: 1) expect(even) == false - + observer.send(value: 2) expect(even) == true } - + it("should error if a mapping fails") { let (baseProducer, observer) = SignalProducer.pipe() let producer = baseProducer.attemptMap { _ -> Result in return .failure(.default) } - + var error: TestError? producer.startWithFailed { err in error = err } - + observer.send(value: 42) expect(error) == TestError.default } } - + describe("combinePrevious") { var observer: Signal.Observer! let initialValue: Int = 0 var latestValues: (Int, Int)? - + beforeEach { latestValues = nil - + let (signal, baseObserver) = SignalProducer.pipe() observer = baseObserver signal.combinePrevious(initialValue).startWithValues { latestValues = $0 } } - + it("should forward the latest value with previous value") { expect(latestValues).to(beNil()) - + observer.send(value: 1) expect(latestValues?.0) == initialValue expect(latestValues?.1) == 1 - + observer.send(value: 2) expect(latestValues?.0) == 1 expect(latestValues?.1) == 2 diff --git a/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift b/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift index 707387ff4..048127b87 100644 --- a/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift +++ b/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift @@ -49,8 +49,7 @@ public func sendValues(_ values: [T], sendError mayb } return signalCompleted == complete - } - else { + } else { return false } } diff --git a/Tests/ReactiveSwiftTests/SignalProducerSpec.swift b/Tests/ReactiveSwiftTests/SignalProducerSpec.swift index bf62cfd8f..b5371c834 100644 --- a/Tests/ReactiveSwiftTests/SignalProducerSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalProducerSpec.swift @@ -19,7 +19,7 @@ class SignalProducerSpec: QuickSpec { describe("init") { it("should run the handler once per start()") { var handlerCalledTimes = 0 - let signalProducer = SignalProducer() { observer, lifetime in + let signalProducer = SignalProducer { _, _ in handlerCalledTimes += 1 return @@ -65,7 +65,7 @@ class SignalProducerSpec: QuickSpec { let addedDisposable = AnyDisposable() var observer: Signal<(), NoError>.Observer! - let producer = SignalProducer<(), NoError>() { incomingObserver, lifetime in + let producer = SignalProducer<(), NoError> { incomingObserver, lifetime in lifetime.observeEnded(addedDisposable.dispose) observer = incomingObserver } @@ -81,7 +81,7 @@ class SignalProducerSpec: QuickSpec { let addedDisposable = AnyDisposable() var observer: Signal<(), TestError>.Observer! - let producer = SignalProducer<(), TestError>() { incomingObserver, lifetime in + let producer = SignalProducer<(), TestError> { incomingObserver, lifetime in lifetime.observeEnded(addedDisposable.dispose) observer = incomingObserver } @@ -97,7 +97,7 @@ class SignalProducerSpec: QuickSpec { let addedDisposable = AnyDisposable() var observer: Signal<(), NoError>.Observer! - let producer = SignalProducer<(), NoError>() { incomingObserver, lifetime in + let producer = SignalProducer<(), NoError> { incomingObserver, lifetime in lifetime.observeEnded(addedDisposable.dispose) observer = incomingObserver } @@ -112,7 +112,7 @@ class SignalProducerSpec: QuickSpec { it("should dispose of added disposables upon start() disposal") { let addedDisposable = AnyDisposable() - let producer = SignalProducer<(), TestError>() { _, lifetime in + let producer = SignalProducer<(), TestError> { _, lifetime in lifetime.observeEnded(addedDisposable.dispose) return } @@ -452,7 +452,7 @@ class SignalProducerSpec: QuickSpec { let addedDisposable = AnyDisposable() var disposable: Disposable! - let producer = SignalProducer() { _, lifetime in + let producer = SignalProducer { _, lifetime in lifetime.observeEnded(addedDisposable.dispose) return } @@ -548,7 +548,7 @@ class SignalProducerSpec: QuickSpec { let addedDisposable = AnyDisposable() var observer: Signal.Observer! - let producer = SignalProducer() { incomingObserver, lifetime in + let producer = SignalProducer { incomingObserver, lifetime in lifetime.observeEnded(addedDisposable.dispose) observer = incomingObserver } @@ -564,7 +564,7 @@ class SignalProducerSpec: QuickSpec { let addedDisposable = AnyDisposable() var observer: Signal.Observer! - let producer = SignalProducer() { incomingObserver, lifetime in + let producer = SignalProducer { incomingObserver, lifetime in lifetime.observeEnded(addedDisposable.dispose) observer = incomingObserver } @@ -845,7 +845,7 @@ class SignalProducerSpec: QuickSpec { it("should start signal producers in order as defined") { var ids = [Int]() let createProducer = { (id: Int) -> SignalProducer in - return SignalProducer { observer, lifetime in + return SignalProducer { observer, _ in ids.append(id) observer.send(value: id) @@ -875,14 +875,14 @@ class SignalProducerSpec: QuickSpec { let producer = SignalProducer.zip([producerA, producerB]) let result = producer.collect().single() - + expect(result?.value.map { $0._bridgeToObjectiveC() }) == [[1, 3], [2, 4]]._bridgeToObjectiveC() } it("should start signal producers in order as defined") { var ids = [Int]() let createProducer = { (id: Int) -> SignalProducer in - return SignalProducer { observer, lifetime in + return SignalProducer { observer, _ in ids.append(id) observer.send(value: id) @@ -1020,13 +1020,13 @@ class SignalProducerSpec: QuickSpec { starting += 1 }, started: { started += 1 - }, event: { e in + }, event: { _ in event += 1 }, completed: { completed += 1 }, terminated: { terminated += 1 - }, value: { n in + }, value: { _ in value += 1 }) @@ -1099,7 +1099,7 @@ class SignalProducerSpec: QuickSpec { let scheduler = TestScheduler() var invoked = false - let producer = SignalProducer() { _, _ in + let producer = SignalProducer { _, _ in invoked = true } @@ -1167,7 +1167,7 @@ class SignalProducerSpec: QuickSpec { var (disposed, interrupted) = (false, false) let disposable = baseProducer - .flatMapError { (error: TestError) -> SignalProducer in + .flatMapError { (_: TestError) -> SignalProducer in return SignalProducer { _, lifetime in lifetime.observeEnded { disposed = true } } @@ -1257,22 +1257,22 @@ class SignalProducerSpec: QuickSpec { outerObserver.send(error: TestError.default) expect(error) == TestError.default } - + it("should not overflow the stack if inner producers complete immediately") { typealias Inner = SignalProducer<(), NoError> - + let depth = 10000 let inner: Inner = SignalProducer(value: ()) let (first, firstObserver) = SignalProducer<(), NoError>.pipe() let (outer, outerObserver) = SignalProducer.pipe() - + var value = 0 outer .flatten(.concat) .startWithValues { _ in value += 1 } - + outerObserver.send(value: first) for _ in 0.. { $1.observeEnded(innerDisposable.dispose) } .on(interrupted: { isInnerInterrupted = true }, disposed: { isInnerDisposed = true }) - + interrupted = false let outerDisposable = outerProducer.flatten(strategy).startWithInterrupted { interrupted = true @@ -1738,7 +1738,7 @@ class SignalProducerSpec: QuickSpec { outerObserver.send(value: innerProducer) } } - + describe("Concat") { it("should cancel inner work when disposed before the outer producer completes") { execute(.concat) @@ -1938,7 +1938,7 @@ class SignalProducerSpec: QuickSpec { let results: [Result] = [ .failure(.default), .failure(.error1), - .failure(.error2), + .failure(.error2) ] let original = SignalProducer.attemptWithResults(results) @@ -1969,7 +1969,7 @@ class SignalProducerSpec: QuickSpec { let (original, observer) = SignalProducer.pipe() var subsequentStarted = false - let subsequent = SignalProducer { observer, _ in + let subsequent = SignalProducer { _, _ in subsequentStarted = true } @@ -2001,7 +2001,7 @@ class SignalProducerSpec: QuickSpec { let (original, observer) = SignalProducer.pipe() var subsequentStarted = false - let subsequent = SignalProducer { observer, _ in + let subsequent = SignalProducer { _, _ in subsequentStarted = true } @@ -2293,9 +2293,9 @@ class SignalProducerSpec: QuickSpec { signal.observe { _ in } downstreamDisposable = innerDisposable } - + expect(upstreamLifetime.hasEnded) == false - + downstreamDisposable.dispose() expect(upstreamLifetime.hasEnded) == true } @@ -2311,13 +2311,13 @@ class SignalProducerSpec: QuickSpec { } // Delaying producer1 from sending a value to test whether producer2 is started in the mean-time. - let producer1 = SignalProducer() { handler, _ in + let producer1 = SignalProducer { handler, _ in handler.send(value: 1) handler.sendCompleted() }.start(on: scheduler) var started = false - let producer2 = SignalProducer() { handler, _ in + let producer2 = SignalProducer { handler, _ in started = true handler.send(value: 2) handler.sendCompleted() @@ -2351,7 +2351,7 @@ class SignalProducerSpec: QuickSpec { replayedProducer .assumeNoErrors() .startWithValues { last = $0 } - + expect(last).to(beNil()) observer.send(value: 1) @@ -2518,7 +2518,7 @@ class SignalProducerSpec: QuickSpec { disposable.dispose() expect(disposed) == false } - + it("does not dispose if it has active subscriptions") { var disposed = false @@ -2537,7 +2537,7 @@ class SignalProducerSpec: QuickSpec { disposable1?.dispose() expect(disposed) == false - + disposable2?.dispose() expect(disposed) == true } @@ -2583,21 +2583,21 @@ class SignalProducerSpec: QuickSpec { var replayedProducer: SignalProducer! = producer .replayLazily(upTo: 1) - + let disposable = replayedProducer .start() - + disposable.dispose() expect(deinitValues) == 0 - + producer = nil expect(deinitValues) == 0 - + replayedProducer = nil expect(deinitValues) == 1 } } - + describe("log events") { it("should output the correct event") { let expectations: [(String) -> Void] = [ @@ -2608,14 +2608,14 @@ class SignalProducerSpec: QuickSpec { { event in expect(event) == "[] terminated" }, { event in expect(event) == "[] disposed" } ] - + let logger = TestLogger(expectations: expectations) - + let (producer, observer) = SignalProducer.pipe() producer .logEvents(logger: logger.logEvent) .start() - + observer.send(value: 1) observer.sendCompleted() } @@ -2669,20 +2669,20 @@ class SignalProducerSpec: QuickSpec { expect(results) == [1, 2] } } - + describe("negated attribute") { it("should return the negate of a value in a Boolean producer") { let producer = SignalProducer { observer, _ in observer.send(value: true) observer.sendCompleted() } - + producer.negate().startWithValues { value in expect(value).to(beFalse()) } } } - + describe("and attribute") { it("should emit true when both producers emits the same value") { let producer1 = SignalProducer { observer, _ in @@ -2693,12 +2693,12 @@ class SignalProducerSpec: QuickSpec { observer.send(value: true) observer.sendCompleted() } - + producer1.and(producer2).startWithValues { value in expect(value).to(beTrue()) } } - + it("should emit false when both producers emits opposite values") { let producer1 = SignalProducer { observer, _ in observer.send(value: true) @@ -2708,12 +2708,12 @@ class SignalProducerSpec: QuickSpec { observer.send(value: false) observer.sendCompleted() } - + producer1.and(producer2).startWithValues { value in expect(value).to(beFalse()) } } - + it("should work the same way when using signal instead of a producer") { let producer1 = SignalProducer { observer, _ in observer.send(value: true) @@ -2724,12 +2724,12 @@ class SignalProducerSpec: QuickSpec { expect(value).to(beTrue()) } observer2.send(value: true) - + observer2.sendCompleted() } } - - describe("or attribute") { + + describe("or attribute") { it("should emit true when at least one of the producers emits true") { let producer1 = SignalProducer { observer, _ in observer.send(value: true) @@ -2739,12 +2739,12 @@ class SignalProducerSpec: QuickSpec { observer.send(value: false) observer.sendCompleted() } - + producer1.or(producer2).startWithValues { value in expect(value).to(beTrue()) } } - + it("should emit false when both producers emits false") { let producer1 = SignalProducer { observer, _ in observer.send(value: false) @@ -2754,12 +2754,12 @@ class SignalProducerSpec: QuickSpec { observer.send(value: false) observer.sendCompleted() } - + producer1.or(producer2).startWithValues { value in expect(value).to(beFalse()) } } - + it("should work the same way when using signal instead of a producer") { let producer1 = SignalProducer { observer, _ in observer.send(value: true) @@ -2770,7 +2770,7 @@ class SignalProducerSpec: QuickSpec { expect(value).to(beTrue()) } observer2.send(value: true) - + observer2.sendCompleted() } } diff --git a/Tests/ReactiveSwiftTests/SignalSpec.swift b/Tests/ReactiveSwiftTests/SignalSpec.swift index 8a4d6f93f..72db3874c 100755 --- a/Tests/ReactiveSwiftTests/SignalSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalSpec.swift @@ -18,24 +18,24 @@ class SignalSpec: QuickSpec { override func spec() { describe("init") { var testScheduler: TestScheduler! - + beforeEach { testScheduler = TestScheduler() } - + it("should run the generator immediately") { var didRunGenerator = false - _ = Signal { observer in + _ = Signal { _ in didRunGenerator = true return nil } - + expect(didRunGenerator) == true } it("should forward events to observers") { let numbers = [ 1, 2, 5 ] - + let signal: Signal = Signal { observer in testScheduler.schedule { for number in numbers { @@ -45,10 +45,10 @@ class SignalSpec: QuickSpec { } return nil } - + var fromSignal: [Int] = [] var completed = false - + signal.observe { event in switch event { case let .value(number): @@ -59,58 +59,58 @@ class SignalSpec: QuickSpec { break } } - + expect(completed) == false expect(fromSignal).to(beEmpty()) - + testScheduler.run() - + expect(completed) == true expect(fromSignal) == numbers } it("should dispose of returned disposable upon error") { let disposable = AnyDisposable() - + let signal: Signal = Signal { observer in testScheduler.schedule { observer.send(error: TestError.default) } return disposable } - + var errored = false - + signal.observeFailed { _ in errored = true } - + expect(errored) == false expect(disposable.isDisposed) == false - + testScheduler.run() - + expect(errored) == true expect(disposable.isDisposed) == true } it("should dispose of returned disposable upon completion") { let disposable = AnyDisposable() - + let signal: Signal = Signal { observer in testScheduler.schedule { observer.sendCompleted() } return disposable } - + var completed = false - + signal.observeCompleted { completed = true } - + expect(completed) == false expect(disposable.isDisposed) == false - + testScheduler.run() - + expect(completed) == true expect(disposable.isDisposed) == true } @@ -200,10 +200,10 @@ class SignalSpec: QuickSpec { describe("Signal.pipe") { it("should forward events to observers") { let (signal, observer) = Signal.pipe() - + var fromSignal: [Int] = [] var completed = false - + signal.observe { event in switch event { case let .value(number): @@ -214,16 +214,16 @@ class SignalSpec: QuickSpec { break } } - + expect(fromSignal).to(beEmpty()) expect(completed) == false - + observer.send(value: 1) expect(fromSignal) == [ 1 ] - + observer.send(value: 2) expect(fromSignal) == [ 1, 2 ] - + expect(completed) == false observer.sendCompleted() expect(completed) == true @@ -360,14 +360,14 @@ class SignalSpec: QuickSpec { describe("observe") { var testScheduler: TestScheduler! - + beforeEach { testScheduler = TestScheduler() } - + it("should stop forwarding events when disposed") { let disposable = AnyDisposable() - + let signal: Signal = Signal { observer in testScheduler.schedule { for number in [ 1, 2 ] { @@ -378,30 +378,30 @@ class SignalSpec: QuickSpec { } return disposable } - + var fromSignal: [Int] = [] signal.observeValues { number in fromSignal.append(number) } - + expect(disposable.isDisposed) == false expect(fromSignal).to(beEmpty()) - + testScheduler.run() - + expect(disposable.isDisposed) == true expect(fromSignal) == [ 1, 2 ] } it("should not trigger side effects") { var runCount = 0 - let signal: Signal<(), NoError> = Signal { observer in + let signal: Signal<(), NoError> = Signal { _ in runCount += 1 return nil } - + expect(runCount) == 1 - + signal.observe(Signal<(), NoError>.Observer()) expect(runCount) == 1 } @@ -529,8 +529,7 @@ class SignalSpec: QuickSpec { } #endif } - - + describe("mapError") { it("should transform the errors of the signal") { let (signal, observer) = Signal.pipe() @@ -666,91 +665,91 @@ class SignalSpec: QuickSpec { expect(lastValue) == 2 } } - + describe("filterMap") { it("should omit values from the signal that are nil after the transformation") { let (signal, observer) = Signal.pipe() let mappedSignal: Signal = signal.filterMap { Int.init($0) } - + var lastValue: Int? - + mappedSignal.observeValues { lastValue = $0 } - + expect(lastValue).to(beNil()) observer.send(value: "0") expect(lastValue) == 0 - + observer.send(value: "1") expect(lastValue) == 1 - + observer.send(value: "A") expect(lastValue) == 1 } - + it("should stop emiting values after an error") { let (signal, observer) = Signal.pipe() let mappedSignal: Signal = signal.filterMap { Int.init($0) } - + var lastValue: Int? - + mappedSignal.observeResult { result in if let value = result.value { lastValue = value } } - + expect(lastValue).to(beNil()) - + observer.send(value: "0") expect(lastValue) == 0 - + observer.send(error: .default) - + observer.send(value: "1") expect(lastValue) == 0 } - + it("should stop emiting values after a complete") { let (signal, observer) = Signal.pipe() let mappedSignal: Signal = signal.filterMap { Int.init($0) } - + var lastValue: Int? - + mappedSignal.observeValues { lastValue = $0 } - + expect(lastValue).to(beNil()) - + observer.send(value: "0") expect(lastValue) == 0 - + observer.sendCompleted() - + observer.send(value: "1") expect(lastValue) == 0 } - + it("should send completed") { let (signal, observer) = Signal.pipe() let mappedSignal: Signal = signal.filterMap { Int.init($0) } - + var completed: Bool = false - + mappedSignal.observeCompleted { completed = true } observer.sendCompleted() - + expect(completed) == true } - + it("should send failure") { let (signal, observer) = Signal.pipe() let mappedSignal: Signal = signal.filterMap { Int.init($0) } - + var failure: TestError? - + mappedSignal.observeFailed { failure = $0 } observer.send(error: .error1) - + expect(failure) == .error1 } } @@ -1054,37 +1053,37 @@ class SignalSpec: QuickSpec { expect(disposedItems) == [ true, false, false, true ] } } - + describe("uniqueValues") { it("should skip values that have been already seen") { let (baseSignal, observer) = Signal.pipe() let signal = baseSignal.uniqueValues() - + var values: [String] = [] signal.observeValues { values.append($0) } - + expect(values) == [] observer.send(value: "a") expect(values) == [ "a" ] - + observer.send(value: "b") expect(values) == [ "a", "b" ] - + observer.send(value: "a") expect(values) == [ "a", "b" ] - + observer.send(value: "b") expect(values) == [ "a", "b" ] - + observer.send(value: "c") expect(values) == [ "a", "b", "c" ] - + observer.sendCompleted() expect(values) == [ "a", "b", "c" ] } } - + describe("skipWhile") { var signal: Signal! var observer: Signal.Observer! @@ -1124,24 +1123,24 @@ class SignalSpec: QuickSpec { expect(lastValue) == 1 } } - + describe("skipUntil") { var signal: Signal! var observer: Signal.Observer! var triggerObserver: Signal<(), NoError>.Observer! - + var lastValue: Int? = nil - + beforeEach { let (baseSignal, incomingObserver) = Signal.pipe() let (triggerSignal, incomingTriggerObserver) = Signal<(), NoError>.pipe() - + signal = baseSignal.skip(until: triggerSignal) observer = incomingObserver triggerObserver = incomingTriggerObserver - + lastValue = nil - + signal.observe { event in switch event { case let .value(value): @@ -1151,10 +1150,10 @@ class SignalSpec: QuickSpec { } } } - + it("should skip values until the trigger fires") { expect(lastValue).to(beNil()) - + observer.send(value: 1) expect(lastValue).to(beNil()) @@ -1165,16 +1164,16 @@ class SignalSpec: QuickSpec { observer.send(value: 0) expect(lastValue) == 0 } - + it("should skip values until the trigger completes") { expect(lastValue).to(beNil()) - + observer.send(value: 1) expect(lastValue).to(beNil()) - + observer.send(value: 2) expect(lastValue).to(beNil()) - + triggerObserver.sendCompleted() observer.send(value: 0) expect(lastValue) == 0 @@ -1210,11 +1209,11 @@ class SignalSpec: QuickSpec { expect(lastValue) == 2 expect(completed) == true } - + it("should complete immediately after taking given number of values") { let numbers = [ 1, 2, 4, 4, 5 ] let testScheduler = TestScheduler() - + var signal: Signal = Signal { observer in testScheduler.schedule { for number in numbers { @@ -1223,12 +1222,12 @@ class SignalSpec: QuickSpec { } return nil } - + var completed = false - + signal = signal.take(first: numbers.count) signal.observeCompleted { completed = true } - + expect(completed) == false testScheduler.run() expect(completed) == true @@ -1443,16 +1442,16 @@ class SignalSpec: QuickSpec { triggerObserver.send(value: ()) expect(completed) == true } - + it("should take values until the trigger completes") { expect(lastValue).to(beNil()) - + observer.send(value: 1) expect(lastValue) == 1 - + observer.send(value: 2) expect(lastValue) == 2 - + expect(completed) == false triggerObserver.sendCompleted() expect(completed) == true @@ -1590,17 +1589,17 @@ class SignalSpec: QuickSpec { it("should send events on the given scheduler") { let testScheduler = TestScheduler() let (signal, observer) = Signal.pipe() - + var result: [Int] = [] - + signal .observe(on: testScheduler) .observeValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) expect(result).to(beEmpty()) - + testScheduler.run() expect(result) == [ 1, 2 ] } @@ -1619,10 +1618,10 @@ class SignalSpec: QuickSpec { } return nil } - + var result: [Int] = [] var completed = false - + signal .delay(10, on: testScheduler) .observe { event in @@ -1635,14 +1634,14 @@ class SignalSpec: QuickSpec { break } } - + testScheduler.advance(by: .seconds(4)) // send initial value expect(result).to(beEmpty()) - + testScheduler.advance(by: .seconds(10)) // send second value and receive first expect(result) == [ 1 ] expect(completed) == false - + testScheduler.advance(by: .seconds(10)) // send second value and receive first expect(result) == [ 1, 2 ] expect(completed) == true @@ -1656,13 +1655,13 @@ class SignalSpec: QuickSpec { } return nil } - + var errored = false - + signal .delay(10, on: testScheduler) .observeFailed { _ in errored = true } - + testScheduler.advance() expect(errored) == true } @@ -1717,14 +1716,14 @@ class SignalSpec: QuickSpec { observer.send(value: 5) scheduler.advance() expect(values) == [ 0, 2, 3 ] - + scheduler.rewind(by: .seconds(2)) expect(values) == [ 0, 2, 3 ] - + observer.send(value: 6) scheduler.advance() expect(values) == [ 0, 2, 3, 6 ] - + observer.send(value: 7) observer.send(value: 8) scheduler.advance() @@ -1950,7 +1949,7 @@ class SignalSpec: QuickSpec { var sampledSignal: Signal<(Int, String), NoError>! var observer: Signal.Observer! var samplerObserver: Signal.Observer! - + beforeEach { let (signal, incomingObserver) = Signal.pipe() let (sampler, incomingSamplerObserver) = Signal.pipe() @@ -1962,7 +1961,7 @@ class SignalSpec: QuickSpec { it("should forward the latest value when the sampler fires") { var result: [String] = [] sampledSignal.observeValues { result.append("\($0.0)\($0.1)") } - + observer.send(value: 1) observer.send(value: 2) samplerObserver.send(value: "a") @@ -1972,7 +1971,7 @@ class SignalSpec: QuickSpec { it("should do nothing if sampler fires before signal receives value") { var result: [String] = [] sampledSignal.observeValues { result.append("\($0.0)\($0.1)") } - + samplerObserver.send(value: "a") expect(result).to(beEmpty()) } @@ -1980,7 +1979,7 @@ class SignalSpec: QuickSpec { it("should send lates value with sampler value multiple times when sampler fires multiple times") { var result: [String] = [] sampledSignal.observeValues { result.append("\($0.0)\($0.1)") } - + observer.send(value: 1) samplerObserver.send(value: "a") samplerObserver.send(value: "b") @@ -1990,10 +1989,10 @@ class SignalSpec: QuickSpec { it("should complete when both inputs have completed") { var completed = false sampledSignal.observeCompleted { completed = true } - + observer.sendCompleted() expect(completed) == false - + samplerObserver.sendCompleted() expect(completed) == true } @@ -2003,7 +2002,7 @@ class SignalSpec: QuickSpec { var sampledSignal: Signal! var observer: Signal.Observer! var samplerObserver: Signal<(), NoError>.Observer! - + beforeEach { let (signal, incomingObserver) = Signal.pipe() let (sampler, incomingSamplerObserver) = Signal<(), NoError>.pipe() @@ -2011,29 +2010,29 @@ class SignalSpec: QuickSpec { observer = incomingObserver samplerObserver = incomingSamplerObserver } - + it("should forward the latest value when the sampler fires") { var result: [Int] = [] sampledSignal.observeValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) samplerObserver.send(value: ()) expect(result) == [ 2 ] } - + it("should do nothing if sampler fires before signal receives value") { var result: [Int] = [] sampledSignal.observeValues { result.append($0) } - + samplerObserver.send(value: ()) expect(result).to(beEmpty()) } - + it("should send lates value multiple times when sampler fires multiple times") { var result: [Int] = [] sampledSignal.observeValues { result.append($0) } - + observer.send(value: 1) samplerObserver.send(value: ()) samplerObserver.send(value: ()) @@ -2043,10 +2042,10 @@ class SignalSpec: QuickSpec { it("should complete when both inputs have completed") { var completed = false sampledSignal.observeCompleted { completed = true } - + observer.sendCompleted() expect(completed) == false - + samplerObserver.sendCompleted() expect(completed) == true } @@ -2191,7 +2190,7 @@ class SignalSpec: QuickSpec { var combinedSignal: Signal<(Int, Double), NoError>! var observer: Signal.Observer! var otherObserver: Signal.Observer! - + beforeEach { let (signal, incomingObserver) = Signal.pipe() let (otherSignal, incomingOtherObserver) = Signal.pipe() @@ -2199,19 +2198,19 @@ class SignalSpec: QuickSpec { observer = incomingObserver otherObserver = incomingOtherObserver } - + it("should forward the latest values from both inputs") { var latest: (Int, Double)? combinedSignal.observeValues { latest = $0 } - + observer.send(value: 1) expect(latest).to(beNil()) - + // is there a better way to test tuples? otherObserver.send(value: 1.5) expect(latest?.0) == 1 expect(latest?.1) == 1.5 - + observer.send(value: 2) expect(latest?.0) == 2 expect(latest?.1) == 1.5 @@ -2220,10 +2219,10 @@ class SignalSpec: QuickSpec { it("should complete when both inputs have completed") { var completed = false combinedSignal.observeCompleted { completed = true } - + observer.sendCompleted() expect(completed) == false - + otherObserver.sendCompleted() expect(completed) == true } @@ -2360,9 +2359,9 @@ class SignalSpec: QuickSpec { signal .materialize() .observeValues { latestEvent = $0 } - + observer.send(value: 2) - + expect(latestEvent).toNot(beNil()) if let latestEvent = latestEvent { switch latestEvent { @@ -2372,7 +2371,7 @@ class SignalSpec: QuickSpec { fail() } } - + observer.send(error: TestError.default) if let latestEvent = latestEvent { switch latestEvent { @@ -2389,24 +2388,24 @@ class SignalSpec: QuickSpec { typealias IntEvent = Signal.Event var observer: Signal.Observer! var dematerialized: Signal! - + beforeEach { let (signal, incomingObserver) = Signal.pipe() observer = incomingObserver dematerialized = signal.dematerialize() } - + it("should send values for Value events") { var result: [Int] = [] dematerialized .assumeNoErrors() .observeValues { result.append($0) } - + expect(result).to(beEmpty()) - + observer.send(value: .value(2)) expect(result) == [ 2 ] - + observer.send(value: .value(4)) expect(result) == [ 2, 4 ] } @@ -2414,9 +2413,9 @@ class SignalSpec: QuickSpec { it("should error out for Error events") { var errored = false dematerialized.observeFailed { _ in errored = true } - + expect(errored) == false - + observer.send(value: .failed(TestError.default)) expect(errored) == true } @@ -2424,7 +2423,7 @@ class SignalSpec: QuickSpec { it("should complete early for Completed events") { var completed = false dematerialized.observeCompleted { completed = true } - + expect(completed) == false observer.send(value: IntEvent.completed) expect(completed) == true @@ -2434,7 +2433,7 @@ class SignalSpec: QuickSpec { describe("takeLast") { var observer: Signal.Observer! var lastThree: Signal! - + beforeEach { let (signal, incomingObserver) = Signal.pipe() observer = incomingObserver @@ -2446,13 +2445,13 @@ class SignalSpec: QuickSpec { lastThree .assumeNoErrors() .observeValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) observer.send(value: 3) observer.send(value: 4) expect(result).to(beEmpty()) - + observer.sendCompleted() expect(result) == [ 2, 3, 4 ] } @@ -2462,13 +2461,13 @@ class SignalSpec: QuickSpec { lastThree .assumeNoErrors() .observeValues { result.append($0) } - + observer.send(value: 1) observer.send(value: 2) observer.sendCompleted() expect(result) == [ 1, 2 ] } - + it("should send nothing when errors") { var result: [Int] = [] var errored = false @@ -2482,12 +2481,12 @@ class SignalSpec: QuickSpec { break } } - + observer.send(value: 1) observer.send(value: 2) observer.send(value: 3) expect(errored) == false - + observer.send(error: TestError.default) expect(errored) == true expect(result).to(beEmpty()) @@ -2572,31 +2571,31 @@ class SignalSpec: QuickSpec { let signal = baseSignal.attempt { _ in return .success(()) } - + var current: Int? signal .assumeNoErrors() .observeValues { value in current = value } - + for value in 1...5 { observer.send(value: value) expect(current) == value } } - + it("should error if an attempt fails") { let (baseSignal, observer) = Signal.pipe() let signal = baseSignal.attempt { _ in return .failure(.default) } - + var error: TestError? signal.observeFailed { err in error = err } - + observer.send(value: 42) expect(error) == TestError.default } @@ -2657,32 +2656,32 @@ class SignalSpec: QuickSpec { let signal = baseSignal.attemptMap { num -> Result in return .success(num % 2 == 0) } - + var even: Bool? signal .assumeNoErrors() .observeValues { value in even = value } - + observer.send(value: 1) expect(even) == false - + observer.send(value: 2) expect(even) == true } - + it("should error if a mapping fails") { let (baseSignal, observer) = Signal.pipe() let signal = baseSignal.attemptMap { _ -> Result in return .failure(.default) } - + var error: TestError? signal.observeFailed { err in error = err } - + observer.send(value: 42) expect(error) == TestError.default } @@ -2743,23 +2742,23 @@ class SignalSpec: QuickSpec { var observer: Signal.Observer! let initialValue: Int = 0 var latestValues: (Int, Int)? - + beforeEach { latestValues = nil - + let (baseSignal, baseObserver) = Signal.pipe() (signal, observer) = (baseSignal, baseObserver) } - + it("should forward the latest value with previous value with an initial value") { signal.combinePrevious(initialValue).observeValues { latestValues = $0 } expect(latestValues).to(beNil()) - + observer.send(value: 1) expect(latestValues?.0) == initialValue expect(latestValues?.1) == 1 - + observer.send(value: 2) expect(latestValues?.0) == 1 expect(latestValues?.1) == 2 @@ -2890,66 +2889,66 @@ class SignalSpec: QuickSpec { var observerA: Signal.Observer! var observerB: Signal.Observer! var observerC: Signal.Observer! - + var combinedValues: [Int]? var completed: Bool! - + beforeEach { combinedValues = nil completed = false - + let (baseSignalA, baseObserverA) = Signal.pipe() let (baseSignalB, baseObserverB) = Signal.pipe() let (baseSignalC, baseObserverC) = Signal.pipe() - + signalA = baseSignalA signalB = baseSignalB signalC = baseSignalC - + observerA = baseObserverA observerB = baseObserverB observerC = baseObserverC } - + let combineLatestExampleName = "combineLatest examples" sharedExamples(combineLatestExampleName) { it("should forward the latest values from all inputs"){ expect(combinedValues).to(beNil()) - + observerA.send(value: 0) observerB.send(value: 1) observerC.send(value: 2) expect(combinedValues) == [0, 1, 2] - + observerA.send(value: 10) expect(combinedValues) == [10, 1, 2] } - + it("should not forward the latest values before all inputs"){ expect(combinedValues).to(beNil()) - + observerA.send(value: 0) expect(combinedValues).to(beNil()) - + observerB.send(value: 1) expect(combinedValues).to(beNil()) - + observerC.send(value: 2) expect(combinedValues) == [0, 1, 2] } - + it("should complete when all inputs have completed"){ expect(completed) == false - + observerA.sendCompleted() observerB.sendCompleted() expect(completed) == false - + observerC.sendCompleted() expect(completed) == true } } - + describe("tuple") { beforeEach { Signal.combineLatest(signalA, signalB, signalC) @@ -2964,10 +2963,10 @@ class SignalSpec: QuickSpec { } } } - + itBehavesLike(combineLatestExampleName) } - + describe("sequence") { beforeEach { Signal.combineLatest([signalA, signalB, signalC]) @@ -2982,11 +2981,11 @@ class SignalSpec: QuickSpec { } } } - + itBehavesLike(combineLatestExampleName) } } - + describe("zip") { var signalA: Signal! var signalB: Signal! @@ -2997,65 +2996,65 @@ class SignalSpec: QuickSpec { var zippedValues: [Int]? var completed: Bool! - + beforeEach { zippedValues = nil completed = false - + let (baseSignalA, baseObserverA) = Signal.pipe() let (baseSignalB, baseObserverB) = Signal.pipe() let (baseSignalC, baseObserverC) = Signal.pipe() - + signalA = baseSignalA signalB = baseSignalB signalC = baseSignalC - + observerA = baseObserverA observerB = baseObserverB observerC = baseObserverC } - + let zipExampleName = "zip examples" sharedExamples(zipExampleName) { it("should combine all set"){ expect(zippedValues).to(beNil()) - + observerA.send(value: 0) expect(zippedValues).to(beNil()) - + observerB.send(value: 1) expect(zippedValues).to(beNil()) - + observerC.send(value: 2) expect(zippedValues) == [0, 1, 2] - + observerA.send(value: 10) expect(zippedValues) == [0, 1, 2] - + observerA.send(value: 20) expect(zippedValues) == [0, 1, 2] - + observerB.send(value: 11) expect(zippedValues) == [0, 1, 2] - + observerC.send(value: 12) expect(zippedValues) == [10, 11, 12] } - + it("should complete when the shorter signal has completed"){ expect(completed) == false - + observerB.send(value: 1) observerC.send(value: 2) observerB.sendCompleted() observerC.sendCompleted() expect(completed) == false - + observerA.send(value: 0) expect(completed) == true } } - + describe("tuple") { beforeEach { Signal.zip(signalA, signalB, signalC) @@ -3070,10 +3069,10 @@ class SignalSpec: QuickSpec { } } } - + itBehavesLike(zipExampleName) } - + describe("sequence") { beforeEach { Signal.zip([signalA, signalB, signalC]) @@ -3088,36 +3087,36 @@ class SignalSpec: QuickSpec { } } } - + itBehavesLike(zipExampleName) } - + describe("log events") { it("should output the correct event without identifier") { let expectations: [(String) -> Void] = [ { event in expect(event) == "[] value 1" }, { event in expect(event) == "[] completed" }, { event in expect(event) == "[] terminated" }, - { event in expect(event) == "[] disposed" }, + { event in expect(event) == "[] disposed" } ] let logger = TestLogger(expectations: expectations) - + let (signal, observer) = Signal.pipe() signal .logEvents(logger: logger.logEvent) .observe { _ in } - + observer.send(value: 1) observer.sendCompleted() } - + it("should output the correct event with identifier") { let expectations: [(String) -> Void] = [ { event in expect(event) == "[test.rac] value 1" }, { event in expect(event) == "[test.rac] failed error1" }, { event in expect(event) == "[test.rac] terminated" }, - { event in expect(event) == "[test.rac] disposed" }, + { event in expect(event) == "[test.rac] disposed" } ] let logger = TestLogger(expectations: expectations) @@ -3126,29 +3125,29 @@ class SignalSpec: QuickSpec { signal .logEvents(identifier: "test.rac", logger: logger.logEvent) .observe { _ in } - + observer.send(value: 1) observer.send(error: .error1) } - + it("should only output the events specified in the `events` parameter") { let expectations: [(String) -> Void] = [ - { event in expect(event) == "[test.rac] failed error1" }, + { event in expect(event) == "[test.rac] failed error1" } ] - + let logger = TestLogger(expectations: expectations) - + let (signal, observer) = Signal.pipe() signal .logEvents(identifier: "test.rac", events: [.failed], logger: logger.logEvent) .observe { _ in } - + observer.send(value: 1) observer.send(error: .error1) } } } - + describe("negated attribute") { it("should return the negate of a value in a Boolean signal") { let (signal, observer) = Signal.pipe() @@ -3159,7 +3158,7 @@ class SignalSpec: QuickSpec { observer.sendCompleted() } } - + describe("and attribute") { it("should emit true when both signals emits the same value") { let (signal1, observer1) = Signal.pipe() @@ -3169,11 +3168,11 @@ class SignalSpec: QuickSpec { } observer1.send(value: true) observer2.send(value: true) - + observer1.sendCompleted() observer2.sendCompleted() } - + it("should emit false when both signals emits opposite values") { let (signal1, observer1) = Signal.pipe() let (signal2, observer2) = Signal.pipe() @@ -3182,12 +3181,12 @@ class SignalSpec: QuickSpec { } observer1.send(value: false) observer2.send(value: true) - + observer1.sendCompleted() observer2.sendCompleted() } } - + describe("or attribute") { it("should emit true when at least one of the signals emits true") { let (signal1, observer1) = Signal.pipe() @@ -3197,11 +3196,11 @@ class SignalSpec: QuickSpec { } observer1.send(value: true) observer2.send(value: false) - + observer1.sendCompleted() observer2.sendCompleted() } - + it("should emit false when both signals emits false") { let (signal1, observer1) = Signal.pipe() let (signal2, observer2) = Signal.pipe() @@ -3210,7 +3209,7 @@ class SignalSpec: QuickSpec { } observer1.send(value: false) observer2.send(value: false) - + observer1.sendCompleted() observer2.sendCompleted() } diff --git a/Tests/ReactiveSwiftTests/TestError.swift b/Tests/ReactiveSwiftTests/TestError.swift index cdfba3798..29672c962 100644 --- a/Tests/ReactiveSwiftTests/TestError.swift +++ b/Tests/ReactiveSwiftTests/TestError.swift @@ -18,7 +18,6 @@ internal enum TestError: Int { extension TestError: Error { } - internal extension SignalProducer { /// Halts if an error is emitted in the receiver signal. /// This is useful in tests to be able to just use `startWithNext` @@ -40,4 +39,3 @@ internal extension Signal { } } } - diff --git a/Tests/ReactiveSwiftTests/TestLogger.swift b/Tests/ReactiveSwiftTests/TestLogger.swift index bc669279b..01d17f151 100644 --- a/Tests/ReactiveSwiftTests/TestLogger.swift +++ b/Tests/ReactiveSwiftTests/TestLogger.swift @@ -11,7 +11,7 @@ import Foundation final class TestLogger { fileprivate var expectations: [(String) -> Void] - + init(expectations: [(String) -> Void]) { self.expectations = expectations } From ec3e09e8836db8217a531af64f765ae50c285368 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Wed, 19 Jul 2017 23:53:41 +0200 Subject: [PATCH 4/9] Configure swiftlint to allow lines <= 200 characters. --- .swiftlint.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.swiftlint.yml b/.swiftlint.yml index 60a752ef7..620dd3713 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,3 +3,5 @@ disabled_rules: included: - Sources - Tests + +line_length: 200 From 2de82a338013cfc2252308d2fb4ee3043e66b454 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Wed, 19 Jul 2017 23:56:34 +0200 Subject: [PATCH 5/9] Update changelog with SwiftLint addition (should it really be there?) --- CHANGELOG.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ba52411c..3ff3955d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # master -*Please add new entries at the top.* + +1. Added [SwiftLint](https://github.com/realm/SwiftLint) config file. # 2.0.0-rc.3 1. `Lifetime.+=` which ties a `Disposable` to a `Lifetime`, is now part of the public API and is no longer deprecated. @@ -38,7 +39,7 @@ 1. The performance of `SignalProducer` has been improved significantly. (#140, kudos to @andersio) All lifted `SignalProducer` operators no longer yield an extra `Signal`. As a result, the calling overhead of event delivery is generally reduced proportionally to the level of chaining of lifted operators. - + 1. `interrupted` now respects `observe(on:)`. (#140) When a produced `Signal` is interrupted, if `observe(on:)` is the last applied operator, `interrupted` would now be delivered on the `Scheduler` passed to `observe(on:)` just like other events. @@ -78,12 +79,12 @@ let producer = SignalProducer { observer, lifetime in Two `Disposable`-accepting methods `Lifetime.Type.+=` and `Lifetime.add` are provided to aid migration, and are subject to removal in a future release. -### Signal and SignalProducer +### Signal and SignalProducer 1. All `Signal` and `SignalProducer` operators now belongs to the respective concrete types. (#304) Custom operators should extend the concrete types directly. `SignalProtocol` and `SignalProducerProtocol` should be used only for constraining associated types. -1. `combineLatest` and `zip` are optimised to have a constant overhead regardless of arity, mitigating the possibility of stack overflow. (#345) +1. `combineLatest` and `zip` are optimised to have a constant overhead regardless of arity, mitigating the possibility of stack overflow. (#345) 1. `flatMap(_:transform:)` is renamed to `flatMap(_:_:)`. (#339) @@ -140,7 +141,7 @@ Two `Disposable`-accepting methods `Lifetime.Type.+=` and `Lifetime.add` are pro `concurrent` starts and flattens inner signals according to the specified concurrency limit. If an inner signal is received after the limit is reached, it would be queued and drained later as the in-flight inner signals terminate. 1. New operators: `reduce(into:)` and `scan(into:)`. (#365, kudos to @ikesyo) - + These variants pass to the closure an `inout` reference to the accumulator, which helps the performance when a large value type is used, e.g. collection. 1. `Property(initial:then:)` gains overloads that accept a producer or signal of the wrapped value type when the value type is an `Optional`. (#396) @@ -160,7 +161,7 @@ Thank you to all of @ReactiveCocoa/reactiveswift and all our contributors, but e ## Deprecation 1. `observe(_:during:)` is now deprecated. It would be removed in ReactiveSwift 2.0. Use `take(during:)` and the relevant observation API of `Signal`, `SignalProducer` and `Property` instead. (#374) - + # 1.1.2 ## Changes 1. Fixed a rare occurrence of `interrupted` events being emitted by a `Property`. (#362) @@ -214,27 +215,27 @@ This is the first major release of ReactiveSwift, a multi-platform, pure-Swift f Major changes since ReactiveCocoa 4 include: - **Updated for Swift 3** - + APIs have been updated and renamed to adhere to the Swift 3 [API Design Guidelines](https://swift.org/documentation/api-design-guidelines/). - **Signal Lifetime Semantics** - + `Signal`s now live and continue to emit events only while either (a) they have observers or (b) they are retained. This clears up a number of unexpected cases and makes Signals much less dangerous. - **Reactive Proxies** - + Types can now declare conformance to `ReactiveExtensionsProvider` to expose a `reactive` property that’s generic over `self`. This property hosts reactive extensions to the type, such as the ones provided on `NotificationCenter` and `URLSession`. - **Property Composition** - + `Property`s can now be composed. They expose many of the familiar operators from `Signal` and `SignalProducer`, including `map`, `flatMap`, `combineLatest`, etc. - **Binding Primitives** - + `BindingTargetProtocol` and `BindingSourceProtocol` have been introduced to allow binding of observable instances to targets. `BindingTarget` is a new concrete type that can be used to wrap a settable but non-observable property. - **Lifetime** - + `Lifetime` is introduced to represent the lifetime of any arbitrary reference type. This can be used with the new `take(during:)` operator, but also forms part of the new binding APIs. - **Race-free Action** - + A new `Action` initializer `Action(state:enabledIf:_:)` has been introduced. It allows the latest value of any arbitrary property to be supplied to the execution closure in addition to the input from `apply(_:)`, while having the availability being derived from the property. - + This eliminates a data race in ReactiveCocoa 4.x, when both the `enabledIf` predicate and the execution closure depend on an overlapping set of properties. Extensive use of Swift’s `@available` declaration has been used to ease migration from ReactiveCocoa 4. Xcode should have fix-its for almost all changes from older APIs. From 97d7c13b2d84adea2ea98f5374674f7507d0be7f Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Thu, 20 Jul 2017 22:27:51 +0200 Subject: [PATCH 6/9] Revert "Update changelog with SwiftLint addition (should it really be there?)" This reverts commit 2de82a338013cfc2252308d2fb4ee3043e66b454. --- CHANGELOG.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ff3955d9..0ba52411c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,5 @@ # master - -1. Added [SwiftLint](https://github.com/realm/SwiftLint) config file. +*Please add new entries at the top.* # 2.0.0-rc.3 1. `Lifetime.+=` which ties a `Disposable` to a `Lifetime`, is now part of the public API and is no longer deprecated. @@ -39,7 +38,7 @@ 1. The performance of `SignalProducer` has been improved significantly. (#140, kudos to @andersio) All lifted `SignalProducer` operators no longer yield an extra `Signal`. As a result, the calling overhead of event delivery is generally reduced proportionally to the level of chaining of lifted operators. - + 1. `interrupted` now respects `observe(on:)`. (#140) When a produced `Signal` is interrupted, if `observe(on:)` is the last applied operator, `interrupted` would now be delivered on the `Scheduler` passed to `observe(on:)` just like other events. @@ -79,12 +78,12 @@ let producer = SignalProducer { observer, lifetime in Two `Disposable`-accepting methods `Lifetime.Type.+=` and `Lifetime.add` are provided to aid migration, and are subject to removal in a future release. -### Signal and SignalProducer +### Signal and SignalProducer 1. All `Signal` and `SignalProducer` operators now belongs to the respective concrete types. (#304) Custom operators should extend the concrete types directly. `SignalProtocol` and `SignalProducerProtocol` should be used only for constraining associated types. -1. `combineLatest` and `zip` are optimised to have a constant overhead regardless of arity, mitigating the possibility of stack overflow. (#345) +1. `combineLatest` and `zip` are optimised to have a constant overhead regardless of arity, mitigating the possibility of stack overflow. (#345) 1. `flatMap(_:transform:)` is renamed to `flatMap(_:_:)`. (#339) @@ -141,7 +140,7 @@ Two `Disposable`-accepting methods `Lifetime.Type.+=` and `Lifetime.add` are pro `concurrent` starts and flattens inner signals according to the specified concurrency limit. If an inner signal is received after the limit is reached, it would be queued and drained later as the in-flight inner signals terminate. 1. New operators: `reduce(into:)` and `scan(into:)`. (#365, kudos to @ikesyo) - + These variants pass to the closure an `inout` reference to the accumulator, which helps the performance when a large value type is used, e.g. collection. 1. `Property(initial:then:)` gains overloads that accept a producer or signal of the wrapped value type when the value type is an `Optional`. (#396) @@ -161,7 +160,7 @@ Thank you to all of @ReactiveCocoa/reactiveswift and all our contributors, but e ## Deprecation 1. `observe(_:during:)` is now deprecated. It would be removed in ReactiveSwift 2.0. Use `take(during:)` and the relevant observation API of `Signal`, `SignalProducer` and `Property` instead. (#374) - + # 1.1.2 ## Changes 1. Fixed a rare occurrence of `interrupted` events being emitted by a `Property`. (#362) @@ -215,27 +214,27 @@ This is the first major release of ReactiveSwift, a multi-platform, pure-Swift f Major changes since ReactiveCocoa 4 include: - **Updated for Swift 3** - + APIs have been updated and renamed to adhere to the Swift 3 [API Design Guidelines](https://swift.org/documentation/api-design-guidelines/). - **Signal Lifetime Semantics** - + `Signal`s now live and continue to emit events only while either (a) they have observers or (b) they are retained. This clears up a number of unexpected cases and makes Signals much less dangerous. - **Reactive Proxies** - + Types can now declare conformance to `ReactiveExtensionsProvider` to expose a `reactive` property that’s generic over `self`. This property hosts reactive extensions to the type, such as the ones provided on `NotificationCenter` and `URLSession`. - **Property Composition** - + `Property`s can now be composed. They expose many of the familiar operators from `Signal` and `SignalProducer`, including `map`, `flatMap`, `combineLatest`, etc. - **Binding Primitives** - + `BindingTargetProtocol` and `BindingSourceProtocol` have been introduced to allow binding of observable instances to targets. `BindingTarget` is a new concrete type that can be used to wrap a settable but non-observable property. - **Lifetime** - + `Lifetime` is introduced to represent the lifetime of any arbitrary reference type. This can be used with the new `take(during:)` operator, but also forms part of the new binding APIs. - **Race-free Action** - + A new `Action` initializer `Action(state:enabledIf:_:)` has been introduced. It allows the latest value of any arbitrary property to be supplied to the execution closure in addition to the input from `apply(_:)`, while having the availability being derived from the property. - + This eliminates a data race in ReactiveCocoa 4.x, when both the `enabledIf` predicate and the execution closure depend on an overlapping set of properties. Extensive use of Swift’s `@available` declaration has been used to ease migration from ReactiveCocoa 4. Xcode should have fix-its for almost all changes from older APIs. From a3456c3cea2c0e666e2d720ef292c604707ee8cc Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Thu, 20 Jul 2017 22:46:41 +0200 Subject: [PATCH 7/9] Disable the "trailing_comma" rule in SwiftLint config. It makes diffs more readable, merges easier. Also, it makes it easier to rearrange stuff. --- .swiftlint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.swiftlint.yml b/.swiftlint.yml index 620dd3713..332906aa7 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,5 +1,6 @@ disabled_rules: - opening_brace + - trailing_comma included: - Sources - Tests From acf703315dca46101ab320d5667ae06a3c5896b1 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Thu, 20 Jul 2017 22:49:54 +0200 Subject: [PATCH 8/9] Reinsert trailing commas. --- Sources/EventLogger.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/EventLogger.swift b/Sources/EventLogger.swift index 16d86a716..263101c1e 100644 --- a/Sources/EventLogger.swift +++ b/Sources/EventLogger.swift @@ -14,7 +14,7 @@ public enum LoggingEvent { case value, completed, failed, terminated, disposed, interrupted public static let allEvents: Set = [ - .value, .completed, .failed, .terminated, .disposed, .interrupted + .value, .completed, .failed, .terminated, .disposed, .interrupted, ] } @@ -22,7 +22,7 @@ public enum LoggingEvent { case starting, started, value, completed, failed, terminated, disposed, interrupted public static let allEvents: Set = [ - .starting, .started, .value, .completed, .failed, .terminated, .disposed, .interrupted + .starting, .started, .value, .completed, .failed, .terminated, .disposed, .interrupted, ] } } From 83b921a75bcf01a21396d474c332c0eaffec6d57 Mon Sep 17 00:00:00 2001 From: Erich Grunewald Date: Fri, 21 Jul 2017 18:56:05 +0200 Subject: [PATCH 9/9] Make trailing_comma rule mandatory for SwiftLint. Run swiftlint autocorrect. --- .swiftlint.yml | 4 +++- Tests/LinuxMain.swift | 2 +- .../SignalProducerLiftingSpec.swift | 4 ++-- Tests/ReactiveSwiftTests/SignalProducerSpec.swift | 12 ++++++------ Tests/ReactiveSwiftTests/SignalSpec.swift | 10 +++++----- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 332906aa7..cec040a8e 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,8 +1,10 @@ disabled_rules: - opening_brace - - trailing_comma included: - Sources - Tests +trailing_comma: + mandatory_comma: true + line_length: 200 diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 9606abb42..3c79b7ba1 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -17,5 +17,5 @@ Quick.QCKMain([ SignalLifetimeSpec.self, SignalProducerLiftingSpec.self, SignalProducerSpec.self, - SignalSpec.self + SignalSpec.self, ]) diff --git a/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift b/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift index 5d4330f52..988576d3c 100644 --- a/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift @@ -878,7 +878,7 @@ class SignalProducerLiftingSpec: QuickSpec { var expectedValues = [ [5, 5], - [42, 5] + [42, 5], ] producer.startWithValues { value in @@ -903,7 +903,7 @@ class SignalProducerLiftingSpec: QuickSpec { var expectedValues = [ [1, 2, 3, 4], - [5, 6, 7, 8, 9] + [5, 6, 7, 8, 9], ] producer.startWithValues { value in diff --git a/Tests/ReactiveSwiftTests/SignalProducerSpec.swift b/Tests/ReactiveSwiftTests/SignalProducerSpec.swift index b5371c834..35e35c2bc 100644 --- a/Tests/ReactiveSwiftTests/SignalProducerSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalProducerSpec.swift @@ -1879,7 +1879,7 @@ class SignalProducerSpec: QuickSpec { let results: [Result] = [ .success(1), .success(2), - .failure(.default) + .failure(.default), ] let original = SignalProducer.attemptWithResults(results) @@ -1894,7 +1894,7 @@ class SignalProducerSpec: QuickSpec { let expectedEvents: [Signal.Event] = [ .value(1), .value(2), - .failed(.default) + .failed(.default), ] // TODO: if let result = result where result.count == expectedEvents.count @@ -1923,7 +1923,7 @@ class SignalProducerSpec: QuickSpec { let results: [Result] = [ .failure(.error1), .failure(.error2), - .success(1) + .success(1), ] let original = SignalProducer.attemptWithResults(results) @@ -1938,7 +1938,7 @@ class SignalProducerSpec: QuickSpec { let results: [Result] = [ .failure(.default), .failure(.error1), - .failure(.error2) + .failure(.error2), ] let original = SignalProducer.attemptWithResults(results) @@ -1953,7 +1953,7 @@ class SignalProducerSpec: QuickSpec { let results: [Result] = [ .success(1), .success(2), - .success(3) + .success(3), ] let original = SignalProducer.attemptWithResults(results) @@ -2606,7 +2606,7 @@ class SignalProducerSpec: QuickSpec { { event in expect(event) == "[] value 1" }, { event in expect(event) == "[] completed" }, { event in expect(event) == "[] terminated" }, - { event in expect(event) == "[] disposed" } + { event in expect(event) == "[] disposed" }, ] let logger = TestLogger(expectations: expectations) diff --git a/Tests/ReactiveSwiftTests/SignalSpec.swift b/Tests/ReactiveSwiftTests/SignalSpec.swift index 72db3874c..6be882980 100755 --- a/Tests/ReactiveSwiftTests/SignalSpec.swift +++ b/Tests/ReactiveSwiftTests/SignalSpec.swift @@ -1354,7 +1354,7 @@ class SignalSpec: QuickSpec { var expectedValues = [ [5, 5], - [42, 5] + [42, 5], ] signal.observeValues { value in @@ -1379,7 +1379,7 @@ class SignalSpec: QuickSpec { var expectedValues = [ [1, 2, 3, 4], - [5, 6, 7, 8, 9] + [5, 6, 7, 8, 9], ] signal.observeValues { value in @@ -3097,7 +3097,7 @@ class SignalSpec: QuickSpec { { event in expect(event) == "[] value 1" }, { event in expect(event) == "[] completed" }, { event in expect(event) == "[] terminated" }, - { event in expect(event) == "[] disposed" } + { event in expect(event) == "[] disposed" }, ] let logger = TestLogger(expectations: expectations) @@ -3116,7 +3116,7 @@ class SignalSpec: QuickSpec { { event in expect(event) == "[test.rac] value 1" }, { event in expect(event) == "[test.rac] failed error1" }, { event in expect(event) == "[test.rac] terminated" }, - { event in expect(event) == "[test.rac] disposed" } + { event in expect(event) == "[test.rac] disposed" }, ] let logger = TestLogger(expectations: expectations) @@ -3132,7 +3132,7 @@ class SignalSpec: QuickSpec { it("should only output the events specified in the `events` parameter") { let expectations: [(String) -> Void] = [ - { event in expect(event) == "[test.rac] failed error1" } + { event in expect(event) == "[test.rac] failed error1" }, ] let logger = TestLogger(expectations: expectations)