TRAVIS_OS_NAME=osx default= <<<<<< ENV ./codecov.yml .jazzy.json .scripts/doc-preprocessor .scripts/generate-docs BuildPhases/run-swiftlint Cartfile.resolved Docs/img/reswift_concept.graffle Docs/jazzy-theme/assets/css/highlight.css.scss Docs/jazzy-theme/assets/css/jazzy.css.scss Docs/jazzy-theme/assets/js/jazzy.js Docs/jazzy-theme/assets/js/jquery.min.js Docs/jazzy-theme/templates/doc.mustache Docs/jazzy-theme/templates/footer.mustache Docs/jazzy-theme/templates/header.mustache Docs/jazzy-theme/templates/nav.mustache Docs/jazzy-theme/templates/parameter.mustache Docs/jazzy-theme/templates/task.mustache Docs/jazzy-theme/templates/tasks.mustache Package.swift Package@swift-5.0.swift Podfile Podfile.lock ReSwift.podspec ReSwift.xcodeproj/project.pbxproj ReSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata ReSwift.xcodeproj/xcshareddata/xcbaselines/25DBCF861C30C4DB00D63A58.xcbaseline/8A5AF011-A17C-4780-8B4D-183154BA1DDA.plist ReSwift.xcodeproj/xcshareddata/xcbaselines/25DBCF861C30C4DB00D63A58.xcbaseline/CA98BC4B-4A03-4B07-BF9E-12C3F6A52195.plist ReSwift.xcodeproj/xcshareddata/xcbaselines/25DBCF861C30C4DB00D63A58.xcbaseline/Info.plist ReSwift.xcodeproj/xcshareddata/xcschemes/ReSwift-iOS.xcscheme ReSwift.xcodeproj/xcshareddata/xcschemes/ReSwift-macOS.xcscheme ReSwift.xcodeproj/xcshareddata/xcschemes/ReSwift-tvOS.xcscheme ReSwift.xcodeproj/xcshareddata/xcschemes/ReSwift-watchOS.xcscheme ReSwift.xcworkspace/contents.xcworkspacedata ReSwift.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ReSwift/CoreTypes/Action.swift ReSwift/CoreTypes/DispatchingStoreType.swift ReSwift/CoreTypes/Middleware.swift ReSwift/CoreTypes/Reducer.swift ReSwift/CoreTypes/State.swift ReSwift/CoreTypes/Store.swift ReSwift/CoreTypes/StoreSubscriber.swift ReSwift/CoreTypes/StoreType.swift ReSwift/CoreTypes/Subscription.swift ReSwift/Info.plist ReSwift/ReSwift.h ReSwift/Utils/Assertions.swift ReSwift/Utils/Coding.swift ReSwift/Utils/Synchronized.swift ReSwift/Utils/TypeHelper.swift ReSwiftTests/AutomaticallySkipRepeatsTests.swift ReSwiftTests/Info.plist ReSwiftTests/PerformanceTests.swift ReSwiftTests/StoreDispatchTests.swift ReSwiftTests/StoreMiddlewareTests.swift ReSwiftTests/StoreSubscriberTests.swift ReSwiftTests/StoreSubscriptionTests.swift ReSwiftTests/StoreTests.swift ReSwiftTests/SynchronizedTests.swift ReSwiftTests/TestFakes.swift ReSwiftTests/TypeHelperTests.swift ReSwiftTests/XCTest+Assertions.swift ReSwiftTests/XCTest+Compatibility.swift SwiftLintIntegration/Info.plist SwiftLintIntegration/SwiftLintIntegration.swift <<<<<< network # path=./ReSwift.framework.coverage.txt /Users/travis/build/ReSwift/ReSwift/ReSwift/CoreTypes/Store.swift: 1| |// 2| |// Store.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 11/11/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |/** 10| | This class is the default implementation of the `StoreType` protocol. You will use this store in most 11| | of your applications. You shouldn't need to implement your own store. 12| | You initialize the store with a reducer and an initial application state. If your app has multiple 13| | reducers you can combine them by initializng a `MainReducer` with all of your reducers as an 14| | argument. 15| | */ 16| |open class Store: StoreType { 17| | 18| | typealias SubscriptionType = SubscriptionBox 19| | 20| | private(set) public var state: State! { 21| 69| didSet { 22| 30.0k| subscriptions.forEach { 23| 30.0k| if $0.subscriber == nil { 24| 2| subscriptions.remove($0) 25| 30.0k| } else { 26| 30.0k| $0.newValues(oldState: oldValue, newState: state) 27| 30.0k| } 28| 30.0k| } 29| 69| } 30| | } 31| | 32| | public lazy var dispatchFunction: DispatchFunction! = createDispatchFunction() 33| | 34| | private var reducer: Reducer 35| | 36| 57| var subscriptions: Set = [] 37| | 38| 57| private var isDispatching = Synchronized(false) 39| | 40| | /// Indicates if new subscriptions attempt to apply `skipRepeats` 41| | /// by default. 42| | fileprivate let subscriptionsAutomaticallySkipRepeats: Bool 43| | 44| | public var middleware: [Middleware] { 45| 2| didSet { 46| 2| dispatchFunction = createDispatchFunction() 47| 2| } 48| | } 49| | 50| | /// Initializes the store with a reducer, an initial state and a list of middleware. 51| | /// 52| | /// Middleware is applied in the order in which it is passed into this constructor. 53| | /// 54| | /// - parameter reducer: Main reducer that processes incoming actions. 55| | /// - parameter state: Initial state, if any. Can be `nil` and will be 56| | /// provided by the reducer in that case. 57| | /// - parameter middleware: Ordered list of action pre-processors, acting 58| | /// before the root reducer. 59| | /// - parameter automaticallySkipsRepeats: If `true`, the store will attempt 60| | /// to skip idempotent state updates when a subscriber's state type 61| | /// implements `Equatable`. Defaults to `true`. 62| | public required init( 63| | reducer: @escaping Reducer, 64| | state: State?, 65| | middleware: [Middleware] = [], 66| | automaticallySkipsRepeats: Bool = true 67| 57| ) { 68| 57| self.subscriptionsAutomaticallySkipRepeats = automaticallySkipsRepeats 69| 57| self.reducer = reducer 70| 57| self.middleware = middleware 71| 57| 72| 57| if let state = state { 73| 56| self.state = state 74| 57| } else { 75| 1| dispatch(ReSwiftInit()) 76| 57| } 77| 57| } 78| | 79| 41| private func createDispatchFunction() -> DispatchFunction! { 80| 41| // Wrap the dispatch function with all middlewares 81| 41| return middleware 82| 41| .reversed() 83| 41| .reduce( 84| 70| { [unowned self] action in 85| 70| self._defaultDispatch(action: action) }, 86| 41| { dispatchFunction, middleware in 87| 7| // If the store get's deinitialized before the middleware is complete; drop 88| 7| // the action without dispatching. 89| 7| let dispatch: (Action) -> Void = { [weak self] in self?.dispatch($0) } 90| 7| let getState: () -> State? = { [weak self] in self?.state } 91| 7| return middleware(dispatch, getState)(dispatchFunction) 92| 7| }) 93| 41| } 94| | 95| | fileprivate func _subscribe( 96| | _ subscriber: S, originalSubscription: Subscription, 97| | transformedSubscription: Subscription?) 98| | where S.StoreSubscriberStateType == SelectedState 99| 33.0k| { 100| 33.0k| let subscriptionBox = self.subscriptionBox( 101| 33.0k| originalSubscription: originalSubscription, 102| 33.0k| transformedSubscription: transformedSubscription, 103| 33.0k| subscriber: subscriber 104| 33.0k| ) 105| 33.0k| 106| 33.0k| subscriptions.update(with: subscriptionBox) 107| 33.0k| 108| 33.0k| if let state = self.state { 109| 33.0k| originalSubscription.newValues(oldState: nil, newState: state) 110| 33.0k| } 111| 33.0k| } 112| | 113| | open func subscribe(_ subscriber: S) 114| 33.0k| where S.StoreSubscriberStateType == State { 115| 33.0k| subscribe(subscriber, transform: nil) 116| 33.0k| } 117| | 118| | open func subscribe( 119| | _ subscriber: S, transform: ((Subscription) -> Subscription)? 120| | ) where S.StoreSubscriberStateType == SelectedState 121| 33.0k| { 122| 33.0k| // Create a subscription for the new subscriber. 123| 33.0k| let originalSubscription = Subscription() 124| 33.0k| // Call the optional transformation closure. This allows callers to modify 125| 33.0k| // the subscription, e.g. in order to subselect parts of the store's state. 126| 33.0k| let transformedSubscription = transform?(originalSubscription) 127| 33.0k| 128| 33.0k| _subscribe(subscriber, originalSubscription: originalSubscription, 129| 33.0k| transformedSubscription: transformedSubscription) 130| 33.0k| } 131| | 132| | func subscriptionBox( 133| | originalSubscription: Subscription, 134| | transformedSubscription: Subscription?, 135| | subscriber: AnyStoreSubscriber 136| 33.0k| ) -> SubscriptionBox { 137| 33.0k| 138| 33.0k| return SubscriptionBox( 139| 33.0k| originalSubscription: originalSubscription, 140| 33.0k| transformedSubscription: transformedSubscription, 141| 33.0k| subscriber: subscriber 142| 33.0k| ) 143| 33.0k| } 144| | 145| 3| open func unsubscribe(_ subscriber: AnyStoreSubscriber) { 146| 3| #if swift(>=5.0) 147| 3| if let index = subscriptions.firstIndex(where: { return $0.subscriber === subscriber }) { 148| 3| subscriptions.remove(at: index) 149| 3| } 150| 3| #else 151| 3| if let index = subscriptions.index(where: { return $0.subscriber === subscriber }) { 152| 3| subscriptions.remove(at: index) 153| 3| } 154| 3| #endif 155| 3| } 156| | 157| | // swiftlint:disable:next identifier_name 158| 70| open func _defaultDispatch(action: Action) { 159| 70| guard !isDispatching.value else { 160| 1| raiseFatalError( 161| 1| "ReSwift:ConcurrentMutationError- Action has been dispatched while" + 162| 1| " a previous action is being processed. A reducer" + 163| 1| " is dispatching an action, or ReSwift is used in a concurrent context" + 164| 1| " (e.g. from multiple threads). Action: \(action)" 165| 1| ) 166| 70| } 167| 70| 168| 70| isDispatching.value { $0 = true } 169| 70| let newState = reducer(action, state) 170| 70| isDispatching.value { $0 = false } 171| 70| 172| 70| state = newState 173| 70| } 174| | 175| 71| open func dispatch(_ action: Action) { 176| 71| dispatchFunction(action) 177| 71| } 178| | 179| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 180| 1| open func dispatch(_ actionCreatorProvider: @escaping ActionCreator) { 181| 1| if let action = actionCreatorProvider(state, self) { 182| 1| dispatch(action) 183| 1| } 184| 1| } 185| | 186| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 187| 1| open func dispatch(_ asyncActionCreatorProvider: @escaping AsyncActionCreator) { 188| 1| dispatch(asyncActionCreatorProvider, callback: nil) 189| 1| } 190| | 191| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 192| | open func dispatch(_ actionCreatorProvider: @escaping AsyncActionCreator, 193| 2| callback: DispatchCallback?) { 194| 2| actionCreatorProvider(state, self) { actionProvider in 195| 2| let action = actionProvider(self.state, self) 196| 2| 197| 2| if let action = action { 198| 2| self.dispatch(action) 199| 2| callback?(self.state) 200| 2| } 201| 2| } 202| 2| } 203| | 204| | public typealias DispatchCallback = (State) -> Void 205| | 206| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 207| | public typealias ActionCreator = (_ state: State, _ store: Store) -> Action? 208| | 209| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 210| | public typealias AsyncActionCreator = ( 211| | _ state: State, 212| | _ store: Store, 213| | _ actionCreatorCallback: @escaping ((ActionCreator) -> Void) 214| | ) -> Void 215| |} 216| | 217| |// MARK: Skip Repeats for Equatable States 218| | 219| |extension Store { 220| | open func subscribe( 221| | _ subscriber: S, transform: ((Subscription) -> Subscription)? 222| | ) where S.StoreSubscriberStateType == SelectedState 223| 16| { 224| 16| let originalSubscription = Subscription() 225| 16| 226| 16| var transformedSubscription = transform?(originalSubscription) 227| 16| if subscriptionsAutomaticallySkipRepeats { 228| 12| transformedSubscription = transformedSubscription?.skipRepeats() 229| 16| } 230| 16| _subscribe(subscriber, originalSubscription: originalSubscription, 231| 16| transformedSubscription: transformedSubscription) 232| 16| } 233| |} 234| | 235| |extension Store where State: Equatable { 236| | open func subscribe(_ subscriber: S) 237| 4| where S.StoreSubscriberStateType == State { 238| 4| guard subscriptionsAutomaticallySkipRepeats else { 239| 1| subscribe(subscriber, transform: nil) 240| 1| return 241| 3| } 242| 3| subscribe(subscriber, transform: { $0.skipRepeats() }) 243| 3| } 244| |} /Users/travis/build/ReSwift/ReSwift/ReSwift/CoreTypes/StoreSubscriber.swift: 1| |// 2| |// StoreSubscriber.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 12/14/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |public protocol AnyStoreSubscriber: AnyObject { 10| | // swiftlint:disable:next identifier_name 11| | func _newState(state: Any) 12| |} 13| | 14| |public protocol StoreSubscriber: AnyStoreSubscriber { 15| | associatedtype StoreSubscriberStateType 16| | 17| | func newState(state: StoreSubscriberStateType) 18| |} 19| | 20| |extension StoreSubscriber { 21| | // swiftlint:disable:next identifier_name 22| 63.0k| public func _newState(state: Any) { 23| 63.0k| if let typedState = state as? StoreSubscriberStateType { 24| 63.0k| newState(state: typedState) 25| 63.0k| } 26| 63.0k| } 27| |} /Users/travis/build/ReSwift/ReSwift/ReSwift/CoreTypes/Subscription.swift: 1| |// 2| |// SubscriberWrapper.swift 3| |// ReSwift 4| |// 5| |// Created by Virgilio Favero Neto on 4/02/2016. 6| |// Copyright © 2016 ReSwift Community. All rights reserved. 7| |// 8| | 9| |/// A box around subscriptions and subscribers. 10| |/// 11| |/// Acts as a type-erasing wrapper around a subscription and its transformed subscription. 12| |/// The transformed subscription has a type argument that matches the selected substate of the 13| |/// subscriber; however that type cannot be exposed to the store. 14| |/// 15| |/// The box subscribes either to the original subscription, or if available to the transformed 16| |/// subscription and passes any values that come through this subscriptions to the subscriber. 17| |class SubscriptionBox: Hashable { 18| | 19| | private let originalSubscription: Subscription 20| | weak var subscriber: AnyStoreSubscriber? 21| | private let objectIdentifier: ObjectIdentifier 22| | 23| | #if swift(>=5.0) 24| 39.2k| func hash(into hasher: inout Hasher) { 25| 39.2k| hasher.combine(self.objectIdentifier) 26| 39.2k| } 27| | #elseif swift(>=4.2) 28| | #if compiler(>=5.0) 29| | func hash(into hasher: inout Hasher) { 30| | hasher.combine(self.objectIdentifier) 31| | } 32| | #else 33| | var hashValue: Int { 34| | return self.objectIdentifier.hashValue 35| | } 36| | #endif 37| | #else 38| | var hashValue: Int { 39| | return self.objectIdentifier.hashValue 40| | } 41| | #endif 42| | 43| | init( 44| | originalSubscription: Subscription, 45| | transformedSubscription: Subscription?, 46| | subscriber: AnyStoreSubscriber 47| 33.0k| ) { 48| 33.0k| self.originalSubscription = originalSubscription 49| 33.0k| self.subscriber = subscriber 50| 33.0k| self.objectIdentifier = ObjectIdentifier(subscriber) 51| 33.0k| 52| 33.0k| // If we received a transformed subscription, we subscribe to that subscription 53| 33.0k| // and forward all new values to the subscriber. 54| 33.0k| if let transformedSubscription = transformedSubscription { 55| 44| transformedSubscription.observer = { [unowned self] _, newState in 56| 44| self.subscriber?._newState(state: newState as Any) 57| 44| } 58| 29| // If we haven't received a transformed subscription, we forward all values 59| 29| // from the original subscription. 60| 33.0k| } else { 61| 63.0k| originalSubscription.observer = { [unowned self] _, newState in 62| 63.0k| self.subscriber?._newState(state: newState as Any) 63| 63.0k| } 64| 33.0k| } 65| 33.0k| } 66| | 67| 30.0k| func newValues(oldState: State, newState: State) { 68| 30.0k| // We pass all new values through the original subscription, which accepts 69| 30.0k| // values of type ``. If present, transformed subscriptions will 70| 30.0k| // receive this update and transform it before passing it on to the subscriber. 71| 30.0k| self.originalSubscription.newValues(oldState: oldState, newState: newState) 72| 30.0k| } 73| | 74| 79.8k| static func == (left: SubscriptionBox, right: SubscriptionBox) -> Bool { 75| 79.8k| return left.objectIdentifier == right.objectIdentifier 76| 79.8k| } 77| |} 78| | 79| |/// Represents a subscription of a subscriber to the store. The subscription determines which new 80| |/// values from the store are forwarded to the subscriber, and how they are transformed. 81| |/// The subscription acts as a very-light weight signal/observable that you might know from 82| |/// reactive programming libraries. 83| |public class Subscription { 84| | 85| | private func _select( 86| | _ selector: @escaping (State) -> Substate 87| | ) -> Subscription 88| 21| { 89| 21| return Subscription { sink in 90| 45| self.observer = { oldState, newState in 91| 45| sink(oldState.map(selector) ?? nil, selector(newState)) 92| 45| } 93| 21| } 94| 21| } 95| | 96| | // MARK: Public Interface 97| | 98| | /// Initializes a subscription with a sink closure. The closure provides a way to send 99| | /// new values over this subscription. 100| 49| public init(sink: @escaping (@escaping (State?, State) -> Void) -> Void) { 101| 49| // Provide the caller with a closure that will forward all values 102| 49| // to observers of this subscription. 103| 83| sink { old, new in 104| 83| self.newValues(oldState: old, newState: new) 105| 83| } 106| 49| } 107| | 108| | /// Provides a subscription that selects a substate of the state of the original subscription. 109| | /// - parameter selector: A closure that maps a state to a selected substate 110| | public func select( 111| | _ selector: @escaping (State) -> Substate 112| | ) -> Subscription 113| 11| { 114| 11| return self._select(selector) 115| 11| } 116| | 117| | /// Provides a subscription that selects a substate of the state of the original subscription. 118| | /// - parameter keyPath: A key path from a state to a substate 119| | public func select( 120| | _ keyPath: KeyPath 121| | ) -> Subscription 122| 10| { 123| 32| return self._select { $0[keyPath: keyPath] } 124| 10| } 125| | 126| | /// Provides a subscription that skips certain state updates of the original subscription. 127| | /// - parameter isRepeat: A closure that determines whether a given state update is a repeat and 128| | /// thus should be skipped and not forwarded to subscribers. 129| | /// - parameter oldState: The store's old state, before the action is reduced. 130| | /// - parameter newState: The store's new state, after the action has been reduced. 131| | public func skipRepeats(_ isRepeat: @escaping (_ oldState: State, _ newState: State) -> Bool) 132| 28| -> Subscription { 133| 28| return Subscription { sink in 134| 58| self.observer = { oldState, newState in 135| 58| switch (oldState, newState) { 136| 58| case let (old?, new): 137| 30| if !isRepeat(old, new) { 138| 10| sink(oldState, newState) 139| 30| } else { 140| 20| return 141| 58| } 142| 58| default: 143| 28| sink(oldState, newState) 144| 58| } 145| 58| } 146| 28| } 147| 28| } 148| | 149| | /// The closure called with changes from the store. 150| | /// This closure can be written to for use in extensions to Subscription similar to `skipRepeats` 151| | public var observer: ((State?, State) -> Void)? 152| | 153| | // MARK: Internals 154| | 155| 33.0k| init() {} 156| | 157| | /// Sends new values over this subscription. Observers will be notified of these new values. 158| 63.1k| func newValues(oldState: State?, newState: State) { 159| 63.1k| self.observer?(oldState, newState) 160| 63.1k| } 161| |} 162| | 163| |extension Subscription where State: Equatable { 164| 17| public func skipRepeats() -> Subscription{ 165| 32| return self.skipRepeats(==) ------------------ | $s7ReSwift12SubscriptionCAASQRzlE11skipRepeatsACyxGyFSbx_xtcxmcfu_: | 165| 17| return self.skipRepeats(==) ------------------ | $s7ReSwift12SubscriptionCAASQRzlE11skipRepeatsACyxGyFSbx_xtcxmcfu_Sbx_xtcfu0_: | 165| 15| return self.skipRepeats(==) ------------------ 166| 17| } 167| |} 168| | 169| |/// Subscription skipping convenience methods 170| |extension Subscription { 171| | 172| | /// Provides a subscription that skips certain state updates of the original subscription. 173| | /// 174| | /// This is identical to `skipRepeats` and is provided simply for convenience. 175| | /// - parameter when: A closure that determines whether a given state update is a repeat and 176| | /// thus should be skipped and not forwarded to subscribers. 177| | /// - parameter oldState: The store's old state, before the action is reduced. 178| | /// - parameter newState: The store's new state, after the action has been reduced. 179| 3| public func skip(when: @escaping (_ oldState: State, _ newState: State) -> Bool) -> Subscription { 180| 3| return self.skipRepeats(when) 181| 3| } 182| | 183| | /// Provides a subscription that only updates for certain state changes. 184| | /// 185| | /// This is effectively the inverse of `skip(when:)` / `skipRepeats(:)` 186| | /// - parameter when: A closure that determines whether a given state update should notify 187| | /// - parameter oldState: The store's old state, before the action is reduced. 188| | /// - parameter newState: The store's new state, after the action has been reduced. 189| | /// the subscriber. 190| 3| public func only(when: @escaping (_ oldState: State, _ newState: State) -> Bool) -> Subscription { 191| 4| return self.skipRepeats { oldState, newState in 192| 4| return !when(oldState, newState) 193| 4| } 194| 3| } 195| |} /Users/travis/build/ReSwift/ReSwift/ReSwift/Utils/Assertions.swift: 1| |// 2| |// Assertions 3| |// Copyright © 2015 mohamede1945. All rights reserved. 4| |// https://github.com/mohamede1945/AssertionsTestingExample 5| |// 6| | 7| |import Foundation 8| | 9| |/// drop-in fatalError replacement for testing 10| | 11| |/** 12| | Swift.fatalError wrapper for catching in tests 13| | 14| | - parameter message: Message to be wrapped 15| | - parameter file: Calling file 16| | - parameter line: Calling line 17| | */ 18| 0|func raiseFatalError(_ message: @autoclosure () -> String = "", 19| 1| file: StaticString = #file, line: UInt = #line) -> Never { 20| 1| Assertions.fatalErrorClosure(message(), file, line) 21| 1.36M| repeat { 22| 1.36M| RunLoop.current.run() 23| 1.36M| } while (true) 24| 1|} 25| | 26| |/// Stores custom assertions closures, by default it points to Swift functions. But test target can 27| |/// override them. 28| |class Assertions { 29| | static var fatalErrorClosure = swiftFatalErrorClosure 30| | static let swiftFatalErrorClosure: (String, StaticString, UInt) -> Void 31| 0| = { Swift.fatalError($0, file: $1, line: $2) } 32| |} /Users/travis/build/ReSwift/ReSwift/ReSwift/Utils/Synchronized.swift: 1| |// 2| |// Synchronized.swift 3| |// ReSwift 4| |// 5| |// Created by Basem Emara on 2020-08-18. 6| |// https://basememara.com/creating-thread-safe-generic-values-in-swift/ 7| |// 8| |// Copyright © 2020 ReSwift Community. All rights reserved. 9| |// 10| | 11| |import Foundation 12| | 13| |/// An object that manages the execution of tasks atomically. 14| |struct Synchronized { 15| 60| private let mutex = DispatchQueue(label: "reswift.github.io.ReSwift.Utils.Synchronized", attributes: .concurrent) 16| | private var _value: Value 17| 60| init(_ value: Value) { 18| 60| self._value = value 19| 60| } 20| | /// Returns or modify the thread-safe value. 21| 90| var value: Value { return mutex.sync { return _value } } 22| | /// Submits a block for synchronous, thread-safe execution. 23| 2.15k| mutating func value(execute task: (inout Value) throws -> T) rethrows -> T { 24| 2.15k| return try mutex.sync(flags: .barrier) { return try task(&_value) } 25| 2.15k| } 26| |} /Users/travis/build/ReSwift/ReSwift/ReSwift/Utils/TypeHelper.swift: 1| |// 2| |// TypeHelper.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 11/27/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |/** 10| | Method is only used internally in ReSwift to cast the generic `StateType` to a specific 11| | type expected by reducers / store subscribers. 12| | 13| | - parameter action: An action that will be passed to `handleAction`. 14| | - parameter state: A generic state type that will be casted to `SpecificStateType`. 15| | - parameter function: The `handleAction` method. 16| | - returns: A `StateType` from `handleAction` or the original `StateType` if it cannot be 17| | casted to `SpecificStateType`. 18| | */ 19| |@discardableResult 20| |func withSpecificTypes( 21| | _ action: Action, 22| | state genericStateType: Any?, 23| | function: (_ action: Action, _ state: SpecificStateType?) -> SpecificStateType 24| 3| ) -> Any { 25| 3| guard let genericStateType = genericStateType else { 26| 1| return function(action, nil) as Any 27| 2| } 28| 2| 29| 2| guard let specificStateType = genericStateType as? SpecificStateType else { 30| 1| return genericStateType 31| 1| } 32| 1| 33| 1| return function(action, specificStateType) as Any 34| 2|} <<<<<< EOF # path=./ReSwift-macOSTests.xctest.coverage.txt /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/PerformanceTests.swift: 1| |// Copyright © 2019 ReSwift Community. All rights reserved. 2| | 3| |import XCTest 4| |import ReSwift 5| | 6| |final class PerformanceTests: XCTestCase { 7| | struct MockState {} 8| | struct MockAction: Action {} 9| | 10| 6.00k| let subscribers: [MockSubscriber] = (0..<3000).map { _ in MockSubscriber() } 11| 2| let store = Store( 12| 10| reducer: { _, state in return state ?? MockState() }, 13| 2| state: MockState(), 14| 2| automaticallySkipsRepeats: false 15| 2| ) 16| | 17| | class MockSubscriber: StoreSubscriber { 18| 63.0k| func newState(state: MockState) { 19| 63.0k| // Do nothing 20| 63.0k| } 21| | } 22| | 23| 1| func testNotify() { 24| 3.00k| self.subscribers.forEach(self.store.subscribe) ------------------ | $s18ReSwift_macOSTests16PerformanceTestsC10testNotifyyyFyAC14MockSubscriberCc0aB05StoreCyAC0I5StateVGcfu_: | 24| 1| self.subscribers.forEach(self.store.subscribe) ------------------ | $s18ReSwift_macOSTests16PerformanceTestsC10testNotifyyyFyAC14MockSubscriberCc0aB05StoreCyAC0I5StateVGcfu_yAFcfu0_: | 24| 3.00k| self.subscribers.forEach(self.store.subscribe) ------------------ 25| 10| self.measure { 26| 10| self.store.dispatch(MockAction()) 27| 10| } 28| 1| } 29| | 30| 1| func testSubscribe() { 31| 10| self.measure { 32| 30.0k| self.subscribers.forEach(self.store.subscribe) ------------------ | $s18ReSwift_macOSTests16PerformanceTestsC13testSubscribeyyFyyXEfU_yAC14MockSubscriberCc0aB05StoreCyAC0I5StateVGcfu_: | 32| 10| self.subscribers.forEach(self.store.subscribe) ------------------ | $s18ReSwift_macOSTests16PerformanceTestsC13testSubscribeyyFyyXEfU_yAC14MockSubscriberCc0aB05StoreCyAC0I5StateVGcfu_yAFcfu0_: | 32| 30.0k| self.subscribers.forEach(self.store.subscribe) ------------------ 33| 10| } 34| 1| } 35| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/StoreDispatchTests.swift: 1| |// 2| |// StoreDispatchTests.swift 3| |// ReSwift 4| |// 5| |// Created by Karl Bowden on 20/07/2016. 6| |// Copyright © 2016 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |@testable import ReSwift 11| | 12| |class StoreDispatchTests: XCTestCase { 13| | 14| | typealias TestSubscriber = TestStoreSubscriber 15| | typealias CallbackSubscriber = CallbackStoreSubscriber 16| | 17| | var store: Store! 18| | var reducer: TestReducer! 19| | 20| 4| override func setUp() { 21| 4| super.setUp() 22| 4| reducer = TestReducer() 23| 8| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests18StoreDispatchTestsC5setUpyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0J7ReducerVcfu_: | 23| 4| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests18StoreDispatchTestsC5setUpyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0J7ReducerVcfu_AfgH_p_AItcfu0_: | 23| 4| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 24| 4| } 25| | 26| | /** 27| | it throws an exception when a reducer dispatches an action 28| | */ 29| 1| func testThrowsExceptionWhenReducersDispatch() { 30| 1| // Expectation lives in the `DispatchingReducer` class 31| 1| let reducer = DispatchingReducer() 32| 2| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests18StoreDispatchTestsC031testThrowsExceptionWhenReducersF0yyFAA12TestAppStateV0aB06Action_p_AFSgtcAA18DispatchingReducerCcfu_: | 32| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests18StoreDispatchTestsC031testThrowsExceptionWhenReducersF0yyFAA12TestAppStateV0aB06Action_p_AFSgtcAA18DispatchingReducerCcfu_AfgH_p_AItcfu0_: | 32| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 33| 1| reducer.store = store 34| 1| store.dispatch(SetValueAction(10)) 35| 1| } 36| | 37| | /** 38| | it accepts action creators 39| | */ 40| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 41| 1| func testAcceptsActionCreators() { 42| 1| store.dispatch(SetValueAction(5)) 43| 1| 44| 1| let doubleValueActionCreator: Store.ActionCreator = { state, store in 45| 1| return SetValueAction(state.testValue! * 2) 46| 1| } 47| 1| 48| 1| store.dispatch(doubleValueActionCreator) 49| 1| 50| 1| XCTAssertEqual(store.state.testValue, 10) 51| 1| } 52| | 53| | /** 54| | it accepts async action creators 55| | */ 56| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 57| 1| func testAcceptsAsyncActionCreators() { 58| 1| 59| 1| let asyncExpectation = futureExpectation( 60| 1| withDescription: "It accepts async action creators") 61| 1| 62| 1| let asyncActionCreator: Store.AsyncActionCreator = { _, _, callback in 63| 1| dispatchAsync { 64| 1| // Provide the callback with an action creator 65| 1| callback { _, _ in 66| 1| return SetValueAction(5) 67| 1| } 68| 1| } 69| 1| } 70| 1| 71| 2| let subscriber = CallbackSubscriber { [unowned self] state in 72| 2| if self.store.state.testValue != nil { 73| 1| XCTAssertEqual(self.store.state.testValue, 5) 74| 1| asyncExpectation.fulfill() 75| 2| } 76| 2| } 77| 1| 78| 1| store.subscribe(subscriber) 79| 1| store.dispatch(asyncActionCreator) 80| 1| waitForFutureExpectations(withTimeout: 1) { error in 81| 1| if let error = error { 82| 0| XCTFail("waitForExpectationsWithTimeout errored: \(error)") 83| 1| } 84| 1| } 85| 1| } 86| | 87| | /** 88| | it calls the callback once state update from async action is complete 89| | */ 90| | @available(*, deprecated, message: "Deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk") 91| 1| func testCallsCalbackOnce() { 92| 1| let asyncExpectation = futureExpectation(withDescription: 93| 1| "It calls the callback once state update from async action is complete") 94| 1| 95| 1| let asyncActionCreator: Store.AsyncActionCreator = { _, _, callback in 96| 1| dispatchAsync { 97| 1| // Provide the callback with an action creator 98| 1| callback { _, _ in 99| 1| return SetValueAction(5) 100| 1| } 101| 1| } 102| 1| } 103| 1| 104| 1| store.dispatch(asyncActionCreator) { newState in 105| 1| XCTAssertEqual(self.store.state.testValue, 5) 106| 1| if newState.testValue == 5 { 107| 1| asyncExpectation.fulfill() 108| 1| } 109| 1| } 110| 1| 111| 1| waitForFutureExpectations(withTimeout: 1) { error in 112| 1| if let error = error { 113| 0| XCTFail("waitForExpectationsWithTimeout errored: \(error)") 114| 1| } 115| 1| } 116| 1| } 117| |} 118| | 119| |// Needs to be class so that shared reference can be modified to inject store 120| |class DispatchingReducer: XCTestCase { 121| | var store: Store? 122| | 123| 1| func handleAction(action: Action, state: TestAppState?) -> TestAppState { 124| 1| expectFatalError { 125| 1| self.store?.dispatch(SetValueAction(20)) 126| 1| } 127| 1| return state ?? TestAppState() 128| 1| } 129| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/StoreMiddlewareTests.swift: 1| |// 2| |// StoreMiddlewareTests.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 12/24/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |@testable import ReSwift 11| | 12| 2|let firstMiddleware: Middleware = { dispatch, getState in 13| 2| return { next in 14| 3| return { action in 15| 3| 16| 3| if var action = action as? SetValueStringAction { 17| 2| action.value += " First Middleware" 18| 2| next(action) 19| 3| } else { 20| 1| next(action) 21| 3| } 22| 3| } 23| 2| } 24| 2|} 25| | 26| 2|let secondMiddleware: Middleware = { dispatch, getState in 27| 2| return { next in 28| 3| return { action in 29| 3| 30| 3| if var action = action as? SetValueStringAction { 31| 2| action.value += " Second Middleware" 32| 2| next(action) 33| 3| } else { 34| 1| next(action) 35| 3| } 36| 3| } 37| 2| } 38| 2|} 39| | 40| 1|let dispatchingMiddleware: Middleware = { dispatch, getState in 41| 1| return { next in 42| 2| return { action in 43| 2| 44| 2| if var action = action as? SetValueAction { 45| 1| dispatch(SetValueStringAction("\(action.value ?? 0)")) 46| 2| } 47| 2| 48| 2| next(action) 49| 2| } 50| 1| } 51| 1|} 52| | 53| 1|let stateAccessingMiddleware: Middleware = { dispatch, getState in 54| 1| return { next in 55| 2| return { action in 56| 2| 57| 2| let appState = getState(), 58| 2| stringAction = action as? SetValueStringAction 59| 2| 60| 2| // avoid endless recursion by checking if we've dispatched exactly this action 61| 2| if appState?.testValue == "OK" && stringAction?.value != "Not OK" { 62| 1| // dispatch a new action 63| 1| dispatch(SetValueStringAction("Not OK")) 64| 1| 65| 1| // and swallow the current one 66| 1| next(NoOpAction()) 67| 2| } else { 68| 1| next(action) 69| 2| } 70| 2| } 71| 1| } 72| 1|} 73| | 74| 1|func middleware(executing block: @escaping () -> Void) -> Middleware { 75| 1| return { dispatch, getState in 76| 1| return { next in 77| 1| return { action in 78| 1| block() 79| 1| } 80| 1| } 81| 1| } 82| 1|} 83| | 84| |class StoreMiddlewareTests: XCTestCase { 85| | 86| | /** 87| | it can decorate dispatch function 88| | */ 89| 1| func testDecorateDispatch() { 90| 1| let reducer = TestValueStringReducer() 91| 1| // Swift 4.1 fails to cast this from Middleware to Middleware 92| 1| // as expected during runtime, see: 93| 1| let middleware: [Middleware] = [ 94| 1| firstMiddleware, 95| 1| secondMiddleware 96| 1| ] 97| 2| let store = Store(reducer: reducer.handleAction, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC20testDecorateDispatchyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0k5ValueL7ReducerVcfu_: | 97| 1| let store = Store(reducer: reducer.handleAction, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC20testDecorateDispatchyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0k5ValueL7ReducerVcfu_AfgH_p_AItcfu0_: | 97| 1| let store = Store(reducer: reducer.handleAction, ------------------ 98| 1| state: TestStringAppState(), 99| 1| middleware: middleware) 100| 1| 101| 1| let subscriber = TestStoreSubscriber() 102| 1| store.subscribe(subscriber) 103| 1| 104| 1| let action = SetValueStringAction("OK") 105| 1| store.dispatch(action) 106| 1| 107| 1| XCTAssertEqual(store.state.testValue, "OK First Middleware Second Middleware") 108| 1| } 109| | 110| | /** 111| | it can dispatch actions 112| | */ 113| 1| func testCanDispatch() { 114| 1| let reducer = TestValueStringReducer() 115| 1| // Swift 4.1 fails to cast this from Middleware to Middleware 116| 1| // as expected during runtime, see: 117| 1| let middleware: [Middleware] = [ 118| 1| firstMiddleware, 119| 1| secondMiddleware, 120| 1| dispatchingMiddleware 121| 1| ] 122| 3| let store = Store(reducer: reducer.handleAction, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC15testCanDispatchyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0k5ValueL7ReducerVcfu_: | 122| 1| let store = Store(reducer: reducer.handleAction, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC15testCanDispatchyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0k5ValueL7ReducerVcfu_AfgH_p_AItcfu0_: | 122| 2| let store = Store(reducer: reducer.handleAction, ------------------ 123| 1| state: TestStringAppState(), 124| 1| middleware: middleware) 125| 1| 126| 1| let subscriber = TestStoreSubscriber() 127| 1| store.subscribe(subscriber) 128| 1| 129| 1| let action = SetValueAction(10) 130| 1| store.dispatch(action) 131| 1| 132| 1| XCTAssertEqual(store.state.testValue, "10 First Middleware Second Middleware") 133| 1| } 134| | 135| | /** 136| | it middleware can access the store's state 137| | */ 138| 1| func testMiddlewareCanAccessState() { 139| 1| let reducer = TestValueStringReducer() 140| 1| var state = TestStringAppState() 141| 1| state.testValue = "OK" 142| 1| 143| 3| let store = Store(reducer: reducer.handleAction, state: state, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC04testF14CanAccessStateyyFAA013TestStringAppK0V0aB06Action_p_AFSgtcAA0l5ValueM7ReducerVcfu_: | 143| 1| let store = Store(reducer: reducer.handleAction, state: state, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC04testF14CanAccessStateyyFAA013TestStringAppK0V0aB06Action_p_AFSgtcAA0l5ValueM7ReducerVcfu_AfgH_p_AItcfu0_: | 143| 2| let store = Store(reducer: reducer.handleAction, state: state, ------------------ 144| 1| middleware: [stateAccessingMiddleware]) 145| 1| 146| 1| store.dispatch(SetValueStringAction("Action That Won't Go Through")) 147| 1| 148| 1| XCTAssertEqual(store.state.testValue, "Not OK") 149| 1| } 150| | 151| 1| func testCanMutateMiddlewareAfterInit() { 152| 1| 153| 1| let reducer = TestValueStringReducer() 154| 1| let state = TestStringAppState() 155| 2| let store = Store(reducer: reducer.handleAction, state: state, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC013testCanMutateF9AfterInityyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0m5ValueN7ReducerVcfu_: | 155| 1| let store = Store(reducer: reducer.handleAction, state: state, ------------------ | $s18ReSwift_macOSTests20StoreMiddlewareTestsC013testCanMutateF9AfterInityyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0m5ValueN7ReducerVcfu_AfgH_p_AItcfu0_: | 155| 1| let store = Store(reducer: reducer.handleAction, state: state, ------------------ 156| 1| middleware: []) 157| 1| 158| 1| // Adding 159| 1| var added = false 160| 1| store.middleware.append(middleware(executing: { added = true })) 161| 1| store.dispatch(SetValueStringAction("")) 162| 1| XCTAssertTrue(added) 163| 1| 164| 1| // Removing 165| 1| added = false 166| 1| store.middleware = [] 167| 1| store.dispatch(SetValueStringAction("")) 168| 1| XCTAssertFalse(added) 169| 1| } 170| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/StoreSubscriberTests.swift: 1| |// 2| |// StoreSubscriberTests.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 1/23/16. 6| |// Copyright © 2016 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |import ReSwift 11| | 12| |class StoreSubscriberTests: XCTestCase { 13| | 14| | /** 15| | it allows to pass a state selector closure 16| | */ 17| 1| func testAllowsSelectorClosure() { 18| 1| let reducer = TestReducer() 19| 3| let store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC25testAllowsSelectorClosureyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_: | 19| 1| let store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC25testAllowsSelectorClosureyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_AfgH_p_AItcfu0_: | 19| 2| let store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 20| 1| let subscriber = TestFilteredSubscriber() 21| 1| 22| 1| store.subscribe(subscriber) { 23| 5| $0.select { $0.testValue } 24| 1| } 25| 1| 26| 1| store.dispatch(SetValueAction(3)) 27| 1| 28| 1| XCTAssertEqual(subscriber.receivedValue, 3) 29| 1| 30| 1| store.dispatch(SetValueAction(nil)) 31| 1| 32| 1| XCTAssertEqual(subscriber.receivedValue, .some(.none)) 33| 1| } 34| | 35| | /** 36| | it allows to pass a state selector key path 37| | */ 38| 1| func testAllowsSelectorKeyPath() { 39| 1| let reducer = TestReducer() 40| 3| let store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC25testAllowsSelectorKeyPathyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_: | 40| 1| let store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC25testAllowsSelectorKeyPathyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_AfgH_p_AItcfu0_: | 40| 2| let store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 41| 1| let subscriber = TestFilteredSubscriber() 42| 1| 43| 1| store.subscribe(subscriber) { 44| 1| $0.select(\.testValue) 45| 1| } 46| 1| 47| 1| store.dispatch(SetValueAction(3)) 48| 1| 49| 1| XCTAssertEqual(subscriber.receivedValue, 3) 50| 1| 51| 1| store.dispatch(SetValueAction(nil)) 52| 1| 53| 1| #if swift(>=4.1) 54| 1| XCTAssertEqual(subscriber.receivedValue, .some(.none)) 55| 1| #else 56| 1| XCTAssertEqual(subscriber.receivedValue, nil) 57| 1| #endif 58| 1| } 59| | 60| | /** 61| | it supports complex state selector closures 62| | */ 63| 1| func testComplexStateSelector() { 64| 1| let reducer = TestComplexAppStateReducer() 65| 3| let store = Store(reducer: reducer.handleAction, state: TestComplexAppState()) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC24testComplexStateSelectoryyFAA04Testi3AppJ0V0aB06Action_p_AFSgtcAA0limJ7ReducerVcfu_: | 65| 1| let store = Store(reducer: reducer.handleAction, state: TestComplexAppState()) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC24testComplexStateSelectoryyFAA04Testi3AppJ0V0aB06Action_p_AFSgtcAA0limJ7ReducerVcfu_AfgH_p_AItcfu0_: | 65| 2| let store = Store(reducer: reducer.handleAction, state: TestComplexAppState()) ------------------ 66| 1| let subscriber = TestSelectiveSubscriber() 67| 1| 68| 1| store.subscribe(subscriber) { 69| 5| $0.select { 70| 5| ($0.testValue, $0.otherState?.name) 71| 5| } 72| 1| } 73| 1| store.dispatch(SetValueAction(5)) 74| 1| store.dispatch(SetOtherStateAction( 75| 1| otherState: OtherState(name: "TestName", age: 99) 76| 1| )) 77| 1| 78| 1| XCTAssertEqual(subscriber.receivedValue.0, 5) 79| 1| XCTAssertEqual(subscriber.receivedValue.1, "TestName") 80| 1| } 81| | 82| | /** 83| | it does not notify subscriber for unchanged substate state when using `skipRepeats`. 84| | */ 85| 1| func testUnchangedStateWithRegularSubstateSelection() { 86| 1| let reducer = TestReducer() 87| 1| var state = TestAppState() 88| 1| state.testValue = 3 89| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC46testUnchangedStateWithRegularSubstateSelectionyyFAA07TestAppJ0V0aB06Action_p_AFSgtcAA0O7ReducerVcfu_: | 89| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC46testUnchangedStateWithRegularSubstateSelectionyyFAA07TestAppJ0V0aB06Action_p_AFSgtcAA0O7ReducerVcfu_AfgH_p_AItcfu0_: | 89| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 90| 1| let subscriber = TestFilteredSubscriber() 91| 1| 92| 1| store.subscribe(subscriber) { 93| 1| $0 94| 3| .select { $0.testValue } 95| 1| .skipRepeats { $0 == $1 } 96| 1| } 97| 1| 98| 1| XCTAssertEqual(subscriber.receivedValue, 3) 99| 1| 100| 1| store.dispatch(SetValueAction(3)) 101| 1| 102| 1| XCTAssertEqual(subscriber.receivedValue, 3) 103| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 104| 1| } 105| | 106| 1| func testUnchangedStateWithKeyPath() { 107| 1| let reducer = TestReducer() 108| 1| var state = TestAppState() 109| 1| state.testValue = 3 110| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC29testUnchangedStateWithKeyPathyyFAA07TestAppJ0V0aB06Action_p_AFSgtcAA0N7ReducerVcfu_: | 110| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC29testUnchangedStateWithKeyPathyyFAA07TestAppJ0V0aB06Action_p_AFSgtcAA0N7ReducerVcfu_AfgH_p_AItcfu0_: | 110| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 111| 1| let subscriber = TestFilteredSubscriber() 112| 1| 113| 1| store.subscribe(subscriber) { 114| 1| $0 115| 1| .select(\.testValue) 116| 1| .skipRepeats { $0 == $1 } 117| 1| } 118| 1| 119| 1| XCTAssertEqual(subscriber.receivedValue, 3) 120| 1| 121| 1| store.dispatch(SetValueAction(3)) 122| 1| 123| 1| XCTAssertEqual(subscriber.receivedValue, 3) 124| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 125| 1| } 126| | 127| | /** 128| | it does not notify subscriber for unchanged substate state when using the default 129| | `skipRepeats` implementation. 130| | */ 131| 1| func testUnchangedStateDefaultSkipRepeatsWithRegularSubstateSelection() { 132| 1| let reducer = TestValueStringReducer() 133| 1| let state = TestStringAppState() 134| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC64testUnchangedStateDefaultSkipRepeatsWithRegularSubstateSelectionyyFAA013TestStringAppJ0V0aB06Action_p_AFSgtcAA0r5ValueS7ReducerVcfu_: | 134| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC64testUnchangedStateDefaultSkipRepeatsWithRegularSubstateSelectionyyFAA013TestStringAppJ0V0aB06Action_p_AFSgtcAA0r5ValueS7ReducerVcfu_AfgH_p_AItcfu0_: | 134| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 135| 1| let subscriber = TestFilteredSubscriber() 136| 1| 137| 1| store.subscribe(subscriber) { 138| 1| $0 139| 3| .select { $0.testValue } 140| 1| .skipRepeats() 141| 1| } 142| 1| 143| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 144| 1| 145| 1| store.dispatch(SetValueStringAction("Initial")) 146| 1| 147| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 148| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 149| 1| } 150| | 151| 1| func testUnchangedStateDefaultSkipRepeatsWithKeyPath() { 152| 1| let reducer = TestValueStringReducer() 153| 1| let state = TestStringAppState() 154| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC47testUnchangedStateDefaultSkipRepeatsWithKeyPathyyFAA013TestStringAppJ0V0aB06Action_p_AFSgtcAA0q5ValueR7ReducerVcfu_: | 154| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC47testUnchangedStateDefaultSkipRepeatsWithKeyPathyyFAA013TestStringAppJ0V0aB06Action_p_AFSgtcAA0q5ValueR7ReducerVcfu_AfgH_p_AItcfu0_: | 154| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 155| 1| let subscriber = TestFilteredSubscriber() 156| 1| 157| 1| store.subscribe(subscriber) { 158| 1| $0 159| 1| .select(\.testValue) 160| 1| .skipRepeats() 161| 1| } 162| 1| 163| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 164| 1| 165| 1| store.dispatch(SetValueStringAction("Initial")) 166| 1| 167| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 168| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 169| 1| } 170| | 171| | /** 172| | it skips repeated state values by when `skipRepeats` returns `true`. 173| | */ 174| 1| func testSkipsStateUpdatesForCustomEqualityChecksWithRegularSubstateSelection() { 175| 1| let reducer = TestCustomAppStateReducer() 176| 1| let state = TestCustomAppState(substateValue: 5) 177| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC72testSkipsStateUpdatesForCustomEqualityChecksWithRegularSubstateSelectionyyFAA04Testm3AppJ0V0aB06Action_p_AFSgtcAA0tmuJ7ReducerVcfu_: | 177| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC72testSkipsStateUpdatesForCustomEqualityChecksWithRegularSubstateSelectionyyFAA04Testm3AppJ0V0aB06Action_p_AFSgtcAA0tmuJ7ReducerVcfu_AfgH_p_AItcfu0_: | 177| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 178| 1| let subscriber = TestFilteredSubscriber() 179| 1| 180| 1| store.subscribe(subscriber) { 181| 1| $0 182| 3| .select { $0.substate } 183| 1| .skipRepeats { $0.value == $1.value } 184| 1| } 185| 1| 186| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 187| 1| 188| 1| store.dispatch(SetCustomSubstateAction(5)) 189| 1| 190| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 191| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 192| 1| } 193| | 194| 1| func testSkipsStateUpdatesForCustomEqualityChecksWithKeyPath() { 195| 1| let reducer = TestCustomAppStateReducer() 196| 1| let state = TestCustomAppState(substateValue: 5) 197| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC55testSkipsStateUpdatesForCustomEqualityChecksWithKeyPathyyFAA04Testm3AppJ0V0aB06Action_p_AFSgtcAA0smtJ7ReducerVcfu_: | 197| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC55testSkipsStateUpdatesForCustomEqualityChecksWithKeyPathyyFAA04Testm3AppJ0V0aB06Action_p_AFSgtcAA0smtJ7ReducerVcfu_AfgH_p_AItcfu0_: | 197| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 198| 1| let subscriber = TestFilteredSubscriber() 199| 1| 200| 1| store.subscribe(subscriber) { 201| 1| $0 202| 1| .select(\.substate) 203| 1| .skipRepeats { $0.value == $1.value } 204| 1| } 205| 1| 206| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 207| 1| 208| 1| store.dispatch(SetCustomSubstateAction(5)) 209| 1| 210| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 211| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 212| 1| } 213| | 214| 1| func testPassesOnDuplicateSubstateUpdatesByDefaultWithRegularSubstateSelection() { 215| 1| let reducer = TestNonEquatableReducer() 216| 1| let state = TestNonEquatable() 217| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC056testPassesOnDuplicateSubstateUpdatesByDefaultWithRegularL9SelectionyyFAA16TestNonEquatableV0aB06Action_p_AFSgtcAA0stU7ReducerVcfu_: | 217| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC056testPassesOnDuplicateSubstateUpdatesByDefaultWithRegularL9SelectionyyFAA16TestNonEquatableV0aB06Action_p_AFSgtcAA0stU7ReducerVcfu_AfgH_p_AItcfu0_: | 217| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 218| 1| let subscriber = TestFilteredSubscriber() 219| 1| 220| 1| store.subscribe(subscriber) { 221| 3| $0.select { $0.testValue } 222| 1| } 223| 1| 224| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 225| 1| 226| 1| store.dispatch(SetNonEquatableAction(NonEquatable())) 227| 1| 228| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 229| 1| XCTAssertEqual(subscriber.newStateCallCount, 2) 230| 1| } 231| | 232| 1| func testPassesOnDuplicateSubstateUpdatesByDefaultWithKeyPath() { 233| 1| let reducer = TestNonEquatableReducer() 234| 1| let state = TestNonEquatable() 235| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC56testPassesOnDuplicateSubstateUpdatesByDefaultWithKeyPathyyFAA16TestNonEquatableV0aB06Action_p_AFSgtcAA0stU7ReducerVcfu_: | 235| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC56testPassesOnDuplicateSubstateUpdatesByDefaultWithKeyPathyyFAA16TestNonEquatableV0aB06Action_p_AFSgtcAA0stU7ReducerVcfu_AfgH_p_AItcfu0_: | 235| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 236| 1| let subscriber = TestFilteredSubscriber() 237| 1| 238| 1| store.subscribe(subscriber) { 239| 1| $0.select(\.testValue) 240| 1| } 241| 1| 242| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 243| 1| 244| 1| store.dispatch(SetNonEquatableAction(NonEquatable())) 245| 1| 246| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 247| 1| XCTAssertEqual(subscriber.newStateCallCount, 2) 248| 1| } 249| | 250| 1| func testPassesOnDuplicateSubstateWhenSkipsFalseWithRegularSubstateSelection() { 251| 1| let reducer = TestValueStringReducer() 252| 1| let state = TestStringAppState() 253| 2| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC054testPassesOnDuplicateSubstateWhenSkipsFalseWithRegularL9SelectionyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0s5ValueT7ReducerVcfu_: | 253| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC054testPassesOnDuplicateSubstateWhenSkipsFalseWithRegularL9SelectionyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0s5ValueT7ReducerVcfu_AfgH_p_AItcfu0_: | 253| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ 254| 1| let subscriber = TestFilteredSubscriber() 255| 1| 256| 1| store.subscribe(subscriber) { 257| 3| $0.select { $0.testValue } 258| 1| } 259| 1| 260| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 261| 1| 262| 1| store.dispatch(SetValueStringAction("Initial")) 263| 1| 264| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 265| 1| XCTAssertEqual(subscriber.newStateCallCount, 2) 266| 1| } 267| | 268| 1| func testPassesOnDuplicateSubstateWhenSkipsFalseWithKeyPath() { 269| 1| let reducer = TestValueStringReducer() 270| 1| let state = TestStringAppState() 271| 2| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC54testPassesOnDuplicateSubstateWhenSkipsFalseWithKeyPathyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0s5ValueT7ReducerVcfu_: | 271| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC54testPassesOnDuplicateSubstateWhenSkipsFalseWithKeyPathyyFAA18TestStringAppStateV0aB06Action_p_AFSgtcAA0s5ValueT7ReducerVcfu_AfgH_p_AItcfu0_: | 271| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ 272| 1| let subscriber = TestFilteredSubscriber() 273| 1| 274| 1| store.subscribe(subscriber) { 275| 1| $0.select(\.testValue) 276| 1| } 277| 1| 278| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 279| 1| 280| 1| store.dispatch(SetValueStringAction("Initial")) 281| 1| 282| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 283| 1| XCTAssertEqual(subscriber.newStateCallCount, 2) 284| 1| } 285| | 286| 1| func testSkipsStateUpdatesForEquatableStateByDefault() { 287| 1| let reducer = TestValueStringReducer() 288| 1| let state = TestStringAppState() 289| 2| let store = Store(reducer: reducer.handleAction, state: state, middleware: []) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC033testSkipsStateUpdatesForEquatableJ9ByDefaultyyFAA013TestStringAppJ0V0aB06Action_p_AFSgtcAA0p5ValueQ7ReducerVcfu_: | 289| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: []) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC033testSkipsStateUpdatesForEquatableJ9ByDefaultyyFAA013TestStringAppJ0V0aB06Action_p_AFSgtcAA0p5ValueQ7ReducerVcfu_AfgH_p_AItcfu0_: | 289| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: []) ------------------ 290| 1| let subscriber = TestFilteredSubscriber() 291| 1| 292| 1| store.subscribe(subscriber) 293| 1| 294| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 295| 1| 296| 1| store.dispatch(SetValueStringAction("Initial")) 297| 1| 298| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 299| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 300| 1| } 301| | 302| 1| func testSkipsStateUpdatesForEquatableSubStateByDefaultWithRegularSubstateSelection() { 303| 1| let reducer = TestNonEquatableReducer() 304| 1| let state = TestNonEquatable() 305| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC036testSkipsStateUpdatesForEquatableSubJ37ByDefaultWithRegularSubstateSelectionyyFAA07TestNonM0V0aB06Action_p_AFSgtcAA0uvM7ReducerVcfu_: | 305| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC036testSkipsStateUpdatesForEquatableSubJ37ByDefaultWithRegularSubstateSelectionyyFAA07TestNonM0V0aB06Action_p_AFSgtcAA0uvM7ReducerVcfu_AfgH_p_AItcfu0_: | 305| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 306| 1| let subscriber = TestFilteredSubscriber() 307| 1| 308| 1| store.subscribe(subscriber) { 309| 3| $0.select { $0.testValue.testValue } 310| 1| } 311| 1| 312| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 313| 1| 314| 1| store.dispatch(SetValueStringAction("Initial")) 315| 1| 316| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 317| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 318| 1| } 319| | 320| 1| func testSkipsStateUpdatesForEquatableSubStateByDefaultWithKeyPathOnGenericStoreType() { 321| 1| let reducer = TestNonEquatableReducer() 322| 1| let state = TestNonEquatable() 323| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC036testSkipsStateUpdatesForEquatableSubj29ByDefaultWithKeyPathOnGenericE4TypeyyFAA07TestNonM0V0aB06Action_p_AFSgtcAA0wxM7ReducerVcfu_: | 323| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC036testSkipsStateUpdatesForEquatableSubj29ByDefaultWithKeyPathOnGenericE4TypeyyFAA07TestNonM0V0aB06Action_p_AFSgtcAA0wxM7ReducerVcfu_AfgH_p_AItcfu0_: | 323| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 324| 1| 325| 1| func runTests(store: S) where S.State == TestNonEquatable { 326| 1| let subscriber = TestFilteredSubscriber() 327| 1| 328| 1| store.subscribe(subscriber) { 329| 1| $0.select(\.testValue.testValue) 330| 1| } 331| 1| 332| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 333| 1| 334| 1| store.dispatch(SetValueStringAction("Initial")) 335| 1| 336| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 337| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 338| 1| } 339| 1| 340| 1| runTests(store: store) 341| 1| } 342| | 343| 1| func testSkipsStateUpdatesForEquatableSubStateByDefaultWithKeyPath() { 344| 1| let reducer = TestNonEquatableReducer() 345| 1| let state = TestNonEquatable() 346| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC036testSkipsStateUpdatesForEquatableSubJ20ByDefaultWithKeyPathyyFAA07TestNonM0V0aB06Action_p_AFSgtcAA0tuM7ReducerVcfu_: | 346| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC036testSkipsStateUpdatesForEquatableSubJ20ByDefaultWithKeyPathyyFAA07TestNonM0V0aB06Action_p_AFSgtcAA0tuM7ReducerVcfu_AfgH_p_AItcfu0_: | 346| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 347| 1| let subscriber = TestFilteredSubscriber() 348| 1| 349| 1| store.subscribe(subscriber) { 350| 1| $0.select(\.testValue.testValue) 351| 1| } 352| 1| 353| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 354| 1| 355| 1| store.dispatch(SetValueStringAction("Initial")) 356| 1| 357| 1| XCTAssertEqual(subscriber.receivedValue, "Initial") 358| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 359| 1| } 360| | 361| 1| func testPassesOnDuplicateStateUpdatesInCustomizedStore() { 362| 1| let reducer = TestValueStringReducer() 363| 1| let state = TestStringAppState() 364| 2| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC045testPassesOnDuplicateStateUpdatesInCustomizedE0yyFAA013TestStringAppL0V0aB06Action_p_AFSgtcAA0p5ValueQ7ReducerVcfu_: | 364| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC045testPassesOnDuplicateStateUpdatesInCustomizedE0yyFAA013TestStringAppL0V0aB06Action_p_AFSgtcAA0p5ValueQ7ReducerVcfu_AfgH_p_AItcfu0_: | 364| 1| let store = Store(reducer: reducer.handleAction, state: state, middleware: [], automaticallySkipsRepeats: false) ------------------ 365| 1| let subscriber = TestFilteredSubscriber() 366| 1| 367| 1| store.subscribe(subscriber) 368| 1| 369| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 370| 1| 371| 1| store.dispatch(SetValueStringAction("Initial")) 372| 1| 373| 1| XCTAssertEqual(subscriber.receivedValue.testValue, "Initial") 374| 1| XCTAssertEqual(subscriber.newStateCallCount, 2) 375| 1| } 376| | 377| 1| func testSkipWhenWithRegularSubstateSelection() { 378| 1| let reducer = TestCustomAppStateReducer() 379| 1| let state = TestCustomAppState(substateValue: 5) 380| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC40testSkipWhenWithRegularSubstateSelectionyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0opqR7ReducerVcfu_: | 380| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC40testSkipWhenWithRegularSubstateSelectionyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0opqR7ReducerVcfu_AfgH_p_AItcfu0_: | 380| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 381| 1| let subscriber = TestFilteredSubscriber() 382| 1| 383| 1| store.subscribe(subscriber) { 384| 1| $0 385| 3| .select { $0.substate } 386| 1| .skip { $0.value == $1.value } 387| 1| } 388| 1| 389| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 390| 1| 391| 1| store.dispatch(SetCustomSubstateAction(5)) 392| 1| 393| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 394| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 395| 1| } 396| | 397| 1| func testSkipWhenWithKeyPath() { 398| 1| let reducer = TestCustomAppStateReducer() 399| 1| let state = TestCustomAppState(substateValue: 5) 400| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC23testSkipWhenWithKeyPathyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0nopQ7ReducerVcfu_: | 400| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC23testSkipWhenWithKeyPathyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0nopQ7ReducerVcfu_AfgH_p_AItcfu0_: | 400| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 401| 1| let subscriber = TestFilteredSubscriber() 402| 1| 403| 1| store.subscribe(subscriber) { 404| 1| $0 405| 1| .select(\.substate) 406| 1| .skip { $0.value == $1.value } 407| 1| } 408| 1| 409| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 410| 1| 411| 1| store.dispatch(SetCustomSubstateAction(5)) 412| 1| 413| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 414| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 415| 1| } 416| | 417| 1| func testOnlyWhenWithRegularSubstateSelection() { 418| 1| let reducer = TestCustomAppStateReducer() 419| 1| let state = TestCustomAppState(substateValue: 5) 420| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC40testOnlyWhenWithRegularSubstateSelectionyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0opqR7ReducerVcfu_: | 420| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC40testOnlyWhenWithRegularSubstateSelectionyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0opqR7ReducerVcfu_AfgH_p_AItcfu0_: | 420| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 421| 1| let subscriber = TestFilteredSubscriber() 422| 1| 423| 1| store.subscribe(subscriber) { 424| 1| $0 425| 3| .select { $0.substate } 426| 1| .only { $0.value != $1.value } 427| 1| } 428| 1| 429| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 430| 1| 431| 1| store.dispatch(SetCustomSubstateAction(5)) 432| 1| 433| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 434| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 435| 1| } 436| | 437| 1| func testOnlyWhenWithKeyPath() { 438| 1| let reducer = TestCustomAppStateReducer() 439| 1| let state = TestCustomAppState(substateValue: 5) 440| 2| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC23testOnlyWhenWithKeyPathyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0nopQ7ReducerVcfu_: | 440| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ | $s18ReSwift_macOSTests20StoreSubscriberTestsC23testOnlyWhenWithKeyPathyyFAA18TestCustomAppStateV0aB06Action_p_AFSgtcAA0nopQ7ReducerVcfu_AfgH_p_AItcfu0_: | 440| 1| let store = Store(reducer: reducer.handleAction, state: state) ------------------ 441| 1| let subscriber = TestFilteredSubscriber() 442| 1| 443| 1| store.subscribe(subscriber) { 444| 1| $0 445| 1| .select(\.substate) 446| 1| .only { $0.value != $1.value } 447| 1| } 448| 1| 449| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 450| 1| 451| 1| store.dispatch(SetCustomSubstateAction(5)) 452| 1| 453| 1| XCTAssertEqual(subscriber.receivedValue.value, 5) 454| 1| XCTAssertEqual(subscriber.newStateCallCount, 1) 455| 1| } 456| |} 457| | 458| |class TestFilteredSubscriber: StoreSubscriber { 459| | var receivedValue: T! 460| | var newStateCallCount = 0 461| | 462| 30| func newState(state: T) { 463| 30| receivedValue = state 464| 30| newStateCallCount += 1 465| 30| } 466| | 467| |} 468| | 469| |/** 470| | Example of how you can select a substate. The return value from 471| | `selectSubstate` and the argument for `newState` need to match up. 472| | */ 473| |class TestSelectiveSubscriber: StoreSubscriber { 474| | var receivedValue: (Int?, String?) 475| | 476| 3| func newState(state: (Int?, String?)) { 477| 3| receivedValue = state 478| 3| } 479| |} 480| | 481| |struct TestComplexAppState { 482| | var testValue: Int? 483| | var otherState: OtherState? 484| |} 485| | 486| |struct OtherState { 487| | var name: String? 488| | var age: Int? 489| |} 490| | 491| |struct TestComplexAppStateReducer { 492| 2| func handleAction(action: Action, state: TestComplexAppState?) -> TestComplexAppState { 493| 2| var state = state ?? TestComplexAppState() 494| 2| 495| 2| switch action { 496| 2| case let action as SetValueAction: 497| 1| state.testValue = action.value 498| 1| return state 499| 2| case let action as SetOtherStateAction: 500| 1| state.otherState = action.otherState 501| 2| default: 502| 0| break 503| 2| } 504| 2| 505| 2| return state 506| 2| } 507| |} 508| | 509| |struct SetOtherStateAction: Action { 510| | var otherState: OtherState 511| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/StoreSubscriptionTests.swift: 1| |// 2| |// StoreSubscriptionTests.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 11/27/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |/** 11| | @testable import for testing of `Store.subscriptions` 12| | */ 13| |@testable import ReSwift 14| | 15| |class StoreSubscriptionTests: XCTestCase { 16| | 17| | typealias TestSubscriber = TestStoreSubscriber 18| | 19| | var store: Store! 20| | var reducer: TestReducer! 21| | 22| 11| override func setUp() { 23| 11| super.setUp() 24| 11| reducer = TestReducer() 25| 11| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC5setUpyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0J7ReducerVcfu_: | 25| 11| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | Unexecuted instantiation: $s18ReSwift_macOSTests22StoreSubscriptionTestsC5setUpyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0J7ReducerVcfu_AfgH_p_AItcfu0_ ------------------ 26| 11| } 27| | 28| | /** 29| | It does not strongly capture an observer 30| | */ 31| 1| func testDoesNotCaptureStrongly() { 32| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC26testDoesNotCaptureStronglyyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_: | 32| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | Unexecuted instantiation: $s18ReSwift_macOSTests22StoreSubscriptionTestsC26testDoesNotCaptureStronglyyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_AfgH_p_AItcfu0_ ------------------ 33| 1| var subscriber: TestSubscriber? = TestSubscriber() 34| 1| 35| 1| store.subscribe(subscriber!) 36| 1| XCTAssertEqual(store.subscriptions.compactMap({ $0.subscriber }).count, 1) 37| 1| // Ensure `subscriber` is accessed at least once to prevent it being optimised 38| 1| // away when tests are built using 'release' scheme. #459 refers. 39| 1| XCTAssertNotNil(subscriber) 40| 1| 41| 1| subscriber = nil 42| 1| XCTAssertEqual(store.subscriptions.compactMap({ $0.subscriber }).count, 0) 43| 1| } 44| | 45| | /** 46| | it removes deferenced subscribers before notifying state changes 47| | */ 48| 1| func testRemoveSubscribers() { 49| 4| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC21testRemoveSubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0K7ReducerVcfu_: | 49| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC21testRemoveSubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0K7ReducerVcfu_AfgH_p_AItcfu0_: | 49| 3| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 50| 1| var subscriber1: TestSubscriber? = TestSubscriber() 51| 1| var subscriber2: TestSubscriber? = TestSubscriber() 52| 1| 53| 1| store.subscribe(subscriber1!) 54| 1| store.subscribe(subscriber2!) 55| 1| store.dispatch(SetValueAction(3)) 56| 1| XCTAssertEqual(store.subscriptions.count, 2) 57| 1| XCTAssertEqual(subscriber1?.receivedStates.last?.testValue, 3) 58| 1| XCTAssertEqual(subscriber2?.receivedStates.last?.testValue, 3) 59| 1| 60| 1| subscriber1 = nil 61| 1| store.dispatch(SetValueAction(5)) 62| 1| XCTAssertEqual(store.subscriptions.count, 1) 63| 1| XCTAssertEqual(subscriber2?.receivedStates.last?.testValue, 5) 64| 1| 65| 1| subscriber2 = nil 66| 1| store.dispatch(SetValueAction(8)) 67| 1| XCTAssertEqual(store.subscriptions.count, 0) 68| 1| } 69| | 70| | /** 71| | it replaces the subscription of an existing subscriber with the new one. 72| | */ 73| 1| func testDuplicateSubscription() { 74| 5| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC013testDuplicateF0yyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0J7ReducerVcfu_: | 74| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC013testDuplicateF0yyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0J7ReducerVcfu_AfgH_p_AItcfu0_: | 74| 4| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 75| 1| let subscriber = TestSubscriber() 76| 1| 77| 1| // Initial subscription. 78| 1| store.subscribe(subscriber) 79| 1| // Subsequent subscription that skips repeated updates. 80| 4| store.subscribe(subscriber) { $0.skipRepeats { $0.testValue == $1.testValue } } 81| 1| 82| 1| // One initial state update for every subscription. 83| 1| XCTAssertEqual(subscriber.receivedStates.count, 2) 84| 1| 85| 1| store.dispatch(SetValueAction(3)) 86| 1| store.dispatch(SetValueAction(3)) 87| 1| store.dispatch(SetValueAction(3)) 88| 1| store.dispatch(SetValueAction(3)) 89| 1| 90| 1| // Only a single further state update, since latest subscription skips repeated values. 91| 1| XCTAssertEqual(subscriber.receivedStates.count, 3) 92| 1| } 93| | /** 94| | it dispatches initial value upon subscription 95| | */ 96| 1| func testDispatchInitialValue() { 97| 2| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC24testDispatchInitialValueyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_: | 97| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC24testDispatchInitialValueyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_AfgH_p_AItcfu0_: | 97| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 98| 1| let subscriber = TestSubscriber() 99| 1| 100| 1| store.subscribe(subscriber) 101| 1| store.dispatch(SetValueAction(3)) 102| 1| 103| 1| XCTAssertEqual(subscriber.receivedStates.last?.testValue, 3) 104| 1| } 105| | 106| | /** 107| | it allows dispatching from within an observer 108| | */ 109| 1| func testAllowDispatchWithinObserver() { 110| 4| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC31testAllowDispatchWithinObserveryyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_: | 110| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC31testAllowDispatchWithinObserveryyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_AfgH_p_AItcfu0_: | 110| 3| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 111| 1| let subscriber = DispatchingSubscriber(store: store) 112| 1| 113| 1| store.subscribe(subscriber) 114| 1| store.dispatch(SetValueAction(2)) 115| 1| 116| 1| XCTAssertEqual(store.state.testValue, 5) 117| 1| } 118| | 119| | /** 120| | it does not dispatch value after subscriber unsubscribes 121| | */ 122| 1| func testDontDispatchToUnsubscribers() { 123| 6| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC31testDontDispatchToUnsubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_: | 123| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC31testDontDispatchToUnsubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_AfgH_p_AItcfu0_: | 123| 5| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 124| 1| let subscriber = TestSubscriber() 125| 1| 126| 1| store.dispatch(SetValueAction(5)) 127| 1| store.subscribe(subscriber) 128| 1| store.dispatch(SetValueAction(10)) 129| 1| 130| 1| store.unsubscribe(subscriber) 131| 1| // Following value is missed due to not being subscribed: 132| 1| store.dispatch(SetValueAction(15)) 133| 1| store.dispatch(SetValueAction(25)) 134| 1| 135| 1| store.subscribe(subscriber) 136| 1| 137| 1| store.dispatch(SetValueAction(20)) 138| 1| 139| 1| XCTAssertEqual(subscriber.receivedStates.count, 4) 140| 1| XCTAssertEqual(subscriber.receivedStates[subscriber.receivedStates.count - 4].testValue, 5) 141| 1| XCTAssertEqual(subscriber.receivedStates[subscriber.receivedStates.count - 3].testValue, 10) 142| 1| XCTAssertEqual(subscriber.receivedStates[subscriber.receivedStates.count - 2].testValue, 25) 143| 1| XCTAssertEqual(subscriber.receivedStates[subscriber.receivedStates.count - 1].testValue, 20) 144| 1| } 145| | 146| | /** 147| | it ignores identical subscribers 148| | */ 149| 1| func testIgnoreIdenticalSubscribers() { 150| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC30testIgnoreIdenticalSubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_: | 150| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | Unexecuted instantiation: $s18ReSwift_macOSTests22StoreSubscriptionTestsC30testIgnoreIdenticalSubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_AfgH_p_AItcfu0_ ------------------ 151| 1| let subscriber = TestSubscriber() 152| 1| 153| 1| store.subscribe(subscriber) 154| 1| store.subscribe(subscriber) 155| 1| 156| 1| XCTAssertEqual(store.subscriptions.count, 1) 157| 1| } 158| | 159| | /** 160| | it ignores identical subscribers that provide substate selectors 161| | */ 162| 1| func testIgnoreIdenticalSubstateSubscribers() { 163| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC38testIgnoreIdenticalSubstateSubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_: | 163| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | Unexecuted instantiation: $s18ReSwift_macOSTests22StoreSubscriptionTestsC38testIgnoreIdenticalSubstateSubscribersyyFAA12TestAppStateV0aB06Action_p_AFSgtcAA0M7ReducerVcfu_AfgH_p_AItcfu0_ ------------------ 164| 1| let subscriber = TestSubscriber() 165| 1| 166| 1| store.subscribe(subscriber) { $0 } 167| 1| store.subscribe(subscriber) { $0 } 168| 1| 169| 1| XCTAssertEqual(store.subscriptions.count, 1) 170| 1| } 171| | 172| 1| func testNewStateModifyingSubscriptionsDoesNotDiscardNewSubscription() { 173| 1| // This was built as a failing test due to a bug introduced by #325 174| 1| // The bug occured by adding a subscriber during `newState` 175| 1| // The bug was caused by creating a copy of `subscriptions` before calling 176| 1| // `newState`, and then assigning that copy back to `subscriptions`, losing 177| 1| // the mutation that occured during `newState` 178| 1| 179| 3| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC048testNewStateModifyingSubscriptionsDoesNotDiscardiF0yyFAA07TestAppJ0V0aB06Action_p_AFSgtcAA0P7ReducerVcfu_: | 179| 1| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC048testNewStateModifyingSubscriptionsDoesNotDiscardiF0yyFAA07TestAppJ0V0aB06Action_p_AFSgtcAA0P7ReducerVcfu_AfgH_p_AItcfu0_: | 179| 2| store = Store(reducer: reducer.handleAction, state: TestAppState()) ------------------ 180| 1| 181| 1| let subscriber2 = BlockSubscriber { _ in 182| 1| self.store.dispatch(SetValueAction(2)) 183| 1| } 184| 1| 185| 2| let subscriber1 = BlockSubscriber { [unowned self] state in 186| 2| if state.testValue == 1 { 187| 1| self.store.subscribe(subscriber2) { 188| 1| $0.skip(when: { _, _ in return true }) 189| 1| } 190| 2| } 191| 2| } 192| 1| 193| 1| store.subscribe(subscriber1) { 194| 2| $0.only(when: { _, new in new.testValue.map { $0 == 1 } ?? false }) 195| 1| } 196| 1| 197| 1| store.dispatch(SetValueAction(1)) 198| 1| 199| 1| XCTAssertTrue(store.subscriptions.contains(where: { 200| 1| guard let subscriber = $0.subscriber else { 201| 0| XCTFail("expecting non-nil subscriber") 202| 0| return false 203| 1| } 204| 1| return subscriber === subscriber1 205| 1| })) 206| 2| XCTAssertTrue(store.subscriptions.contains(where: { 207| 2| guard let subscriber = $0.subscriber else { 208| 0| XCTFail("expecting non-nil subscriber") 209| 0| return false 210| 2| } 211| 2| return subscriber === subscriber2 212| 2| })) 213| 1| 214| 1| // Have a subscriber (#1) 215| 1| // #1 adds sub #2 in newState 216| 1| // #1 dispatches in newState 217| 1| // Test that store.subscribers == [#1, #2] // this should fail 218| 1| } 219| |} 220| | 221| |// MARK: Retain Cycle Detection 222| | 223| |private struct TracerAction: Action { } 224| | 225| |private class TestSubscriptionBox: SubscriptionBox { 226| | override init( 227| | originalSubscription: Subscription, 228| | transformedSubscription: Subscription?, 229| | subscriber: AnyStoreSubscriber 230| 2| ) { 231| 2| super.init(originalSubscription: originalSubscription, 232| 2| transformedSubscription: transformedSubscription, 233| 2| subscriber: subscriber) 234| 2| } 235| | 236| | var didDeinit: (() -> Void)? 237| 2| deinit { 238| 2| didDeinit?() 239| 2| } 240| |} 241| | 242| |private class TestStore: Store { 243| | override func subscriptionBox( 244| | originalSubscription: Subscription, 245| | transformedSubscription: Subscription?, 246| 2| subscriber: AnyStoreSubscriber) -> SubscriptionBox { 247| 2| return TestSubscriptionBox( 248| 2| originalSubscription: originalSubscription, 249| 2| transformedSubscription: transformedSubscription, 250| 2| subscriber: subscriber 251| 2| ) 252| 2| } 253| |} 254| | 255| |extension StoreSubscriptionTests { 256| | 257| 1| func testRetainCycle_OriginalSubscription() { 258| 1| 259| 1| var didDeinit = false 260| 1| 261| 1| autoreleasepool { 262| 1| 263| 3| store = TestStore(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC024testRetainCycle_OriginalF0yyFyyXEfU_AA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_: | 263| 1| store = TestStore(reducer: reducer.handleAction, state: TestAppState()) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC024testRetainCycle_OriginalF0yyFyyXEfU_AA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_AfgH_p_AItcfu0_: | 263| 2| store = TestStore(reducer: reducer.handleAction, state: TestAppState()) ------------------ 264| 1| let subscriber: TestSubscriber = TestSubscriber() 265| 1| 266| 1| // Preconditions 267| 1| XCTAssertEqual(subscriber.receivedStates.count, 0) 268| 1| XCTAssertEqual(store.subscriptions.count, 0) 269| 1| 270| 1| autoreleasepool { 271| 1| 272| 1| store.subscribe(subscriber) 273| 1| XCTAssertEqual(subscriber.receivedStates.count, 1) 274| 1| let subscriptionBox = store.subscriptions.first! as! TestSubscriptionBox 275| 1| subscriptionBox.didDeinit = { didDeinit = true } 276| 1| 277| 1| store.dispatch(TracerAction()) 278| 1| XCTAssertEqual(subscriber.receivedStates.count, 2) 279| 1| store.unsubscribe(subscriber) 280| 1| } 281| 1| 282| 1| XCTAssertEqual(store.subscriptions.count, 0) 283| 1| store.dispatch(TracerAction()) 284| 1| XCTAssertEqual(subscriber.receivedStates.count, 2) 285| 1| 286| 1| store = nil 287| 1| } 288| 1| 289| 1| XCTAssertTrue(didDeinit) 290| 1| } 291| | 292| 1| func testRetainCycle_TransformedSubscription() { 293| 1| 294| 1| var didDeinit = false 295| 1| 296| 1| autoreleasepool { 297| 1| 298| 3| store = TestStore(reducer: reducer.handleAction, state: TestAppState(), automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC027testRetainCycle_TransformedF0yyFyyXEfU_AA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_: | 298| 1| store = TestStore(reducer: reducer.handleAction, state: TestAppState(), automaticallySkipsRepeats: false) ------------------ | $s18ReSwift_macOSTests22StoreSubscriptionTestsC027testRetainCycle_TransformedF0yyFyyXEfU_AA12TestAppStateV0aB06Action_p_AFSgtcAA0L7ReducerVcfu_AfgH_p_AItcfu0_: | 298| 2| store = TestStore(reducer: reducer.handleAction, state: TestAppState(), automaticallySkipsRepeats: false) ------------------ 299| 1| let subscriber = TestStoreSubscriber() 300| 1| 301| 1| // Preconditions 302| 1| XCTAssertEqual(subscriber.receivedStates.count, 0) 303| 1| XCTAssertEqual(store.subscriptions.count, 0) 304| 1| 305| 1| autoreleasepool { 306| 1| 307| 1| store.subscribe(subscriber, transform: { 308| 3| $0.select { $0.testValue } 309| 1| }) 310| 1| XCTAssertEqual(subscriber.receivedStates.count, 1) 311| 1| let subscriptionBox = store.subscriptions.first! as! TestSubscriptionBox 312| 1| subscriptionBox.didDeinit = { didDeinit = true } 313| 1| 314| 1| store.dispatch(TracerAction()) 315| 1| XCTAssertEqual(subscriber.receivedStates.count, 2) 316| 1| store.unsubscribe(subscriber) 317| 1| } 318| 1| 319| 1| XCTAssertEqual(store.subscriptions.count, 0) 320| 1| store.dispatch(TracerAction()) 321| 1| XCTAssertEqual(subscriber.receivedStates.count, 2) 322| 1| 323| 1| store = nil 324| 1| } 325| 1| 326| 1| XCTAssertTrue(didDeinit) 327| 1| } 328| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/StoreTests.swift: 1| |// 2| |// StoreTests.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 11/27/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |@testable import ReSwift 11| | 12| |class StoreTests: XCTestCase { 13| | 14| | /** 15| | it dispatches an Init action when it doesn't receive an initial state 16| | */ 17| 1| func testInit() { 18| 1| let reducer = MockReducer() 19| 2| _ = Store(reducer: reducer.handleAction, state: nil) ------------------ | $s18ReSwift_macOSTests10StoreTestsC8testInityyFAA12CounterStateV0aB06Action_p_AFSgtcAA11MockReducerCcfu_: | 19| 1| _ = Store(reducer: reducer.handleAction, state: nil) ------------------ | $s18ReSwift_macOSTests10StoreTestsC8testInityyFAA12CounterStateV0aB06Action_p_AFSgtcAA11MockReducerCcfu_AfgH_p_AItcfu0_: | 19| 1| _ = Store(reducer: reducer.handleAction, state: nil) ------------------ 20| 1| 21| 1| XCTAssert(reducer.calledWithAction[0] is ReSwiftInit) 22| 1| } 23| | 24| | /** 25| | it deinitializes when no reference is held 26| | */ 27| 1| func testDeinit() { 28| 1| var deInitCount = 0 29| 1| 30| 1| autoreleasepool { 31| 1| let reducer = TestReducer() 32| 1| _ = DeInitStore( 33| 1| reducer: reducer.handleAction, ------------------ | $s18ReSwift_macOSTests10StoreTestsC10testDeinityyFyyXEfU_AA12TestAppStateV0aB06Action_p_AFSgtcAA0I7ReducerVcfu_: | 33| 1| reducer: reducer.handleAction, ------------------ | Unexecuted instantiation: $s18ReSwift_macOSTests10StoreTestsC10testDeinityyFyyXEfU_AA12TestAppStateV0aB06Action_p_AFSgtcAA0I7ReducerVcfu_AfgH_p_AItcfu0_ ------------------ 34| 1| state: TestAppState(), 35| 1| deInitAction: { deInitCount += 1 }) 36| 1| } 37| 1| 38| 1| XCTAssertEqual(deInitCount, 1) 39| 1| } 40| | 41| |} 42| | 43| |// Used for deinitialization test 44| |class DeInitStore: Store { 45| | var deInitAction: (() -> Void)? 46| | 47| 1| deinit { 48| 1| deInitAction?() 49| 1| } 50| | 51| | required convenience init( 52| | reducer: @escaping Reducer, 53| | state: State?, 54| 1| deInitAction: (() -> Void)?) { 55| 1| self.init( 56| 1| reducer: reducer, 57| 1| state: state, 58| 1| middleware: [], 59| 1| automaticallySkipsRepeats: false) 60| 1| self.deInitAction = deInitAction 61| 1| } 62| | 63| | required init( 64| | reducer: @escaping Reducer, 65| | state: State?, 66| | middleware: [Middleware], 67| 1| automaticallySkipsRepeats: Bool) { 68| 1| super.init( 69| 1| reducer: reducer, 70| 1| state: state, 71| 1| middleware: middleware, 72| 1| automaticallySkipsRepeats: automaticallySkipsRepeats) 73| 1| } 74| |} 75| | 76| |struct CounterState { 77| | var count: Int = 0 78| |} 79| | 80| |class MockReducer { 81| | 82| 1| var calledWithAction: [Action] = [] 83| | 84| 1| func handleAction(action: Action, state: CounterState?) -> CounterState { 85| 1| calledWithAction.append(action) 86| 1| 87| 1| return state ?? CounterState() 88| 1| } 89| | 90| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/SynchronizedTests.swift: 1| |// 2| |// SynchronizedTests.swift 3| |// ReSwift 4| |// 5| |// Created by Basem Emara on 2020-08-18. 6| |// Copyright © 2020 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |/** 11| | @testable import for testing of `Utils.Synchronized` 12| | */ 13| |@testable import ReSwift 14| | 15| |class SynchronizedTests: XCTestCase { 16| | private let iterations = 100 // 1_000_000 17| | private let writeMultipleOf = 10 // 1000 18| |} 19| | 20| |extension SynchronizedTests { 21| 1| func testSharedVariable() { 22| 100| DispatchQueue.concurrentPerform(iterations: iterations) { _ in 23| 100| Database.shared.set(key: "test", value: true) 24| 100| } 25| 1| } 26| | private class Database { 27| | static let shared = Database() 28| 1| private var data = Synchronized<[String: Any]>([:]) 29| 0| func get(key: String) -> Any? { 30| 0| return data.value { $0[key] } 31| 0| } 32| 100| func set(key: String, value: Any) { 33| 100| data.value { $0[key] = value } 34| 100| } 35| | } 36| |} 37| | 38| |extension SynchronizedTests { 39| 1| func testWritePerformance() { 40| 1| var temp = Synchronized(0) 41| 10| measure { 42| 10| temp.value { $0 = 0 } // Reset 43| 1.00k| DispatchQueue.concurrentPerform(iterations: iterations) { _ in 44| 1.00k| temp.value { $0 += 1 } 45| 1.00k| } 46| 10| XCTAssertEqual(temp.value, iterations) 47| 10| } 48| 1| } 49| |} 50| | 51| |extension SynchronizedTests { 52| 1| func testReadPerformance() { 53| 1| var temp = Synchronized(0) 54| 10| measure { 55| 10| temp.value { $0 = 0 } // Reset 56| 1.00k| DispatchQueue.concurrentPerform(iterations: iterations) { 57| 1.00k| guard $0 % writeMultipleOf != 0 else { return } 58| 900| temp.value { $0 += 1 } 59| 900| } 60| 10| XCTAssertGreaterThanOrEqual(temp.value, iterations / writeMultipleOf) 61| 10| } 62| 1| } 63| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/TestFakes.swift: 1| |// 2| |// TestFakes.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 12/24/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import Foundation 10| |import ReSwift 11| | 12| |struct TestAppState { 13| | var testValue: Int? 14| | 15| 32| init() { 16| 32| testValue = nil 17| 32| } 18| |} 19| | 20| |struct TestStringAppState { 21| | var testValue: String 22| | 23| 10| init() { 24| 10| testValue = "Initial" 25| 10| } 26| |} 27| | 28| |extension TestStringAppState: Equatable { 29| 6| static func == (lhs: TestStringAppState, rhs: TestStringAppState) -> Bool { 30| 6| return lhs.testValue == rhs.testValue 31| 6| } 32| |} 33| | 34| |struct TestNonEquatable { 35| | var testValue: NonEquatable 36| | 37| 5| init() { 38| 5| testValue = NonEquatable() 39| 5| } 40| |} 41| | 42| |struct NonEquatable { 43| | var testValue: String 44| | 45| 7| init() { 46| 7| testValue = "Initial" 47| 7| } 48| |} 49| | 50| |struct TestCustomAppState { 51| | var substate: TestCustomSubstate 52| | 53| 0| init(substate: TestCustomSubstate) { 54| 0| self.substate = substate 55| 0| } 56| | 57| 6| init(substateValue value: Int = 0) { 58| 6| self.substate = TestCustomSubstate(value: value) 59| 6| } 60| | 61| | struct TestCustomSubstate { 62| | var value: Int 63| | } 64| |} 65| | 66| |struct NoOpAction: Action {} 67| | 68| |struct SetValueAction: Action { 69| | 70| | let value: Int? 71| | static let type = "SetValueAction" 72| | 73| 32| init (_ value: Int?) { 74| 32| self.value = value 75| 32| } 76| |} 77| | 78| |struct SetValueStringAction: Action { 79| | 80| | var value: String 81| | static let type = "SetValueStringAction" 82| | 83| 15| init (_ value: String) { 84| 15| self.value = value 85| 15| } 86| |} 87| | 88| |struct SetCustomSubstateAction: Action { 89| | 90| | var value: Int 91| | static let type = "SetCustomSubstateAction" 92| | 93| 6| init (_ value: Int) { 94| 6| self.value = value 95| 6| } 96| |} 97| | 98| |struct SetNonEquatableAction: Action { 99| | var value: NonEquatable 100| | static let type = "SetNonEquatableAction" 101| | 102| 2| init (_ value: NonEquatable) { 103| 2| self.value = value 104| 2| } 105| |} 106| | 107| |struct TestReducer { 108| 32| func handleAction(action: Action, state: TestAppState?) -> TestAppState { 109| 32| var state = state ?? TestAppState() 110| 32| 111| 32| switch action { 112| 32| case let action as SetValueAction: 113| 28| state.testValue = action.value 114| 28| return state 115| 32| default: 116| 4| return state 117| 32| } 118| 32| } 119| |} 120| | 121| |struct TestValueStringReducer { 122| 12| func handleAction(action: Action, state: TestStringAppState?) -> TestStringAppState { 123| 12| var state = state ?? TestStringAppState() 124| 12| 125| 12| switch action { 126| 12| case let action as SetValueStringAction: 127| 10| state.testValue = action.value 128| 10| return state 129| 12| default: 130| 2| return state 131| 12| } 132| 12| } 133| |} 134| | 135| |struct TestCustomAppStateReducer { 136| 6| func handleAction(action: Action, state: TestCustomAppState?) -> TestCustomAppState { 137| 6| var state = state ?? TestCustomAppState() 138| 6| 139| 6| switch action { 140| 6| case let action as SetCustomSubstateAction: 141| 6| state.substate.value = action.value 142| 6| return state 143| 6| default: 144| 0| return state 145| 6| } 146| 6| } 147| |} 148| | 149| |struct TestNonEquatableReducer { 150| | func handleAction(action: Action, state: TestNonEquatable?) -> 151| 5| TestNonEquatable { 152| 5| var state = state ?? TestNonEquatable() 153| 5| 154| 5| switch action { 155| 5| case let action as SetNonEquatableAction: 156| 2| state.testValue = action.value 157| 2| return state 158| 5| default: 159| 3| return state 160| 5| } 161| 5| } 162| |} 163| | 164| |class TestStoreSubscriber: StoreSubscriber { 165| 12| var receivedStates: [T] = [] 166| | 167| 27| func newState(state: T) { 168| 27| receivedStates.append(state) 169| 27| } 170| |} 171| | 172| |class BlockSubscriber: StoreSubscriber { 173| | typealias StoreSubscriberStateType = S 174| | private let block: (S) -> Void 175| | 176| 2| init(block: @escaping (S) -> Void) { 177| 2| self.block = block 178| 2| } 179| | 180| 3| func newState(state: S) { 181| 3| self.block(state) 182| 3| } 183| |} 184| | 185| |class DispatchingSubscriber: StoreSubscriber { 186| | var store: Store 187| | 188| 1| init(store: Store) { 189| 1| self.store = store 190| 1| } 191| | 192| 4| func newState(state: TestAppState) { 193| 4| // Test if we've already dispatched this action to 194| 4| // avoid endless recursion 195| 4| if state.testValue != 5 { 196| 2| self.store.dispatch(SetValueAction(5)) 197| 4| } 198| 4| } 199| |} 200| | 201| |class CallbackStoreSubscriber: StoreSubscriber { 202| | 203| | let handler: (T) -> Void 204| | 205| 1| init(handler: @escaping (T) -> Void) { 206| 1| self.handler = handler 207| 1| } 208| | 209| 2| func newState(state: T) { 210| 2| handler(state) 211| 2| } 212| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/TypeHelperTests.swift: 1| |// 2| |// TypeHelperTests.swift 3| |// ReSwift 4| |// 5| |// Created by Benjamin Encz on 12/20/15. 6| |// Copyright © 2015 ReSwift Community. All rights reserved. 7| |// 8| | 9| |import XCTest 10| |/** 11| | @testable import for testing of `withSpecificTypes` 12| | */ 13| |@testable import ReSwift 14| | 15| |struct AppState1 {} 16| |struct AppState2 {} 17| | 18| |class TypeHelperTests: XCTestCase { 19| | 20| | /** 21| | it calls methods if the source type can be casted into the function signature type 22| | */ 23| 1| func testSourceTypeCasting() { 24| 1| var called = false 25| 1| let reducerFunction: (Action, AppState1?) -> AppState1 = { action, state in 26| 1| called = true 27| 1| 28| 1| return state ?? AppState1() 29| 1| } 30| 1| 31| 1| withSpecificTypes(NoOpAction(), state: AppState1(), function: reducerFunction) 32| 1| 33| 1| XCTAssertTrue(called) 34| 1| } 35| | 36| | /** 37| | it calls the method if the source type is nil 38| | */ 39| 1| func testCallsIfSourceTypeIsNil() { 40| 1| var called = false 41| 1| let reducerFunction: (Action, AppState1?) -> AppState1 = { action, state in 42| 1| called = true 43| 1| 44| 1| return state ?? AppState1() 45| 1| } 46| 1| 47| 1| withSpecificTypes(NoOpAction(), state: nil, function: reducerFunction) 48| 1| 49| 1| XCTAssertTrue(called) 50| 1| } 51| | 52| | /** 53| | it doesn't call if source type can't be casted to function signature type 54| | */ 55| 1| func testDoesntCallIfCastFails() { 56| 1| var called = false 57| 1| let reducerFunction: (Action, AppState1?) -> AppState1 = { action, state in 58| 0| called = true 59| 0| 60| 0| return state ?? AppState1() 61| 0| } 62| 1| 63| 1| withSpecificTypes(NoOpAction(), state: AppState2(), function: reducerFunction) 64| 1| 65| 1| XCTAssertFalse(called) 66| 1| } 67| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/XCTest+Assertions.swift: 1| |// 2| |// Assertions 3| |// Copyright © 2015 mohamede1945. All rights reserved. 4| |// https://github.com/mohamede1945/AssertionsTestingExample 5| |// 6| | 7| |import Foundation 8| |import XCTest 9| |/** 10| | @testable import for testing of `Assertions.fatalErrorClosure` 11| | */ 12| |@testable import ReSwift 13| | 14| |private let noReturnFailureWaitTime = 0.1 15| | 16| |public extension XCTestCase { 17| | /** 18| | Expects an `fatalError` to be called. 19| | If `fatalError` not called, the test case will fail. 20| | 21| | - parameter expectedMessage: The expected message to be asserted to the one passed to the 22| | `fatalError`. If nil, then ignored. 23| | - parameter file: The file name that called the method. 24| | - parameter line: The line number that called the method. 25| | - parameter testCase: The test case to be executed that expected to fire the assertion 26| | method. 27| | */ 28| | func expectFatalError(expectedMessage: String? = nil, file: StaticString = #file, 29| 1| line: UInt = #line, testCase: @escaping () -> Void) { 30| 1| expectAssertionNoReturnFunction( 31| 1| functionName: "fatalError", 32| 1| file: file, 33| 1| line: line, 34| 1| function: { (caller: @escaping (String) -> Void) -> Void in 35| 1| Assertions.fatalErrorClosure = { message, _, _ in caller(message) } 36| 1| }, 37| 1| expectedMessage: expectedMessage, 38| 1| testCase: testCase, 39| 1| cleanUp: { 40| 1| Assertions.fatalErrorClosure = Assertions.swiftFatalErrorClosure 41| 1| }) 42| 1| } 43| | 44| | // MARK: Private Methods 45| | 46| | // swiftlint:disable function_parameter_count 47| | private func expectAssertionNoReturnFunction( 48| | functionName funcName: String, 49| | file: StaticString, 50| | line: UInt, 51| | function: (_ caller: @escaping (String) -> Void) -> Void, 52| | expectedMessage: String? = nil, 53| | testCase: @escaping () -> Void, 54| 1| cleanUp: @escaping () -> Void) { 55| 1| 56| 1| let asyncExpectation = futureExpectation(withDescription: funcName + "-Expectation") 57| 1| var assertionMessage: String? 58| 1| 59| 1| function { (message) -> Void in 60| 1| assertionMessage = message 61| 1| asyncExpectation.fulfill() 62| 1| } 63| 1| 64| 1| // act, perform on separate thead because a call to function runs forever 65| 1| dispatchUserInitiatedAsync(execute: testCase) 66| 1| 67| 1| waitForFutureExpectations(withTimeout: noReturnFailureWaitTime) { _ in 68| 1| defer { cleanUp() } 69| 1| guard let assertionMessage = assertionMessage else { 70| 0| XCTFail(funcName + " is expected to be called.", file: file, line: line) 71| 0| return 72| 1| } 73| 1| if let expectedMessage = expectedMessage { 74| 0| XCTAssertEqual(assertionMessage, expectedMessage, funcName + 75| 0| " called with incorrect message.", file: file, line: line) 76| 1| } 77| 1| } 78| 1| } 79| | // swiftlint:enable function_parameter_count 80| |} /Users/travis/build/ReSwift/ReSwift/ReSwiftTests/XCTest+Compatibility.swift: 1| |// Copyright © 2019 ReSwift Community. All rights reserved. 2| | 3| |import XCTest 4| | 5| 2|func dispatchAsync(execute work: @escaping @convention(block) () -> Swift.Void) { 6| 2| DispatchQueue.global(qos: .default).async(execute: work) 7| 2|} 8| | 9| |func dispatchUserInitiatedAsync 10| 1| (execute work: @escaping @convention(block) () -> Swift.Void) { 11| 1| DispatchQueue.global(qos: .userInitiated).async(execute: work) 12| 1|} 13| | 14| |extension XCTestCase { 15| | 16| 3| func futureExpectation(withDescription description: String) -> XCTestExpectation { 17| 3| return expectation(description: description) 18| 3| } 19| | 20| | func waitForFutureExpectations( 21| | withTimeout timeout: TimeInterval, 22| 3| handler: XCWaitCompletionHandler? = nil) { 23| 3| 24| 3| waitForExpectations(timeout: timeout, handler: handler) 25| 3| } 26| |} <<<<<< EOF # path=fixes ./SwiftLintIntegration/SwiftLintIntegration.swift:8 ./Package@swift-5.0.swift:3,11 ./ReSwiftTests/SynchronizedTests.swift:8,14,18,19,24,25,31,34,35,36,37,45,47,48,49,50,59,61,62,63 ./ReSwiftTests/XCTest+Compatibility.swift:2,4,7,8,12,13,15,18,19,23,25,26 ./ReSwiftTests/StoreSubscriptionTests.swift:8,14,16,18,21,26,27,34,40,43,44,52,59,64,68,69,76,81,84,89,92,99,102,104,105,112,115,117,118,125,129,134,136,138,144,145,152,155,157,158,165,168,170,171,178,180,183,184,189,190,191,192,195,196,198,203,210,213,218,219,220,222,224,234,235,239,240,241,252,253,254,256,258,260,262,265,269,271,276,280,281,285,287,288,290,291,293,295,297,300,304,306,313,317,318,322,324,325,327,328 ./ReSwiftTests/TestFakes.swift:8,11,14,17,18,19,22,25,26,27,31,32,33,36,39,40,41,44,47,48,49,52,55,56,59,60,63,64,65,67,69,72,75,76,77,79,82,85,86,87,89,92,95,96,97,101,104,105,106,110,117,118,119,120,124,131,132,133,134,138,145,146,147,148,153,160,161,162,163,166,169,170,171,175,178,179,182,183,184,187,190,191,197,198,199,200,202,204,207,208,211,212 ./ReSwiftTests/StoreSubscriberTests.swift:8,11,13,21,24,25,27,29,31,33,34,42,45,46,48,50,52,58,59,67,71,72,77,80,81,91,96,97,99,101,104,105,112,117,118,120,122,125,126,136,141,142,144,146,149,150,156,161,162,164,166,169,170,179,184,185,187,189,192,193,199,204,205,207,209,212,213,219,222,223,225,227,230,231,237,240,241,243,245,248,249,255,258,259,261,263,266,267,273,276,277,279,281,284,285,291,293,295,297,300,301,307,310,311,313,315,318,319,324,327,330,331,333,335,338,339,341,342,348,351,352,354,356,359,360,366,368,370,372,375,376,382,387,388,390,392,395,396,402,407,408,410,412,415,416,422,427,428,430,432,435,436,442,447,448,450,452,455,456,457,461,465,466,467,468,475,478,479,480,484,485,489,490,494,503,504,506,507,508,511 ./ReSwiftTests/PerformanceTests.swift:2,5,9,16,20,21,22,27,28,29,33,34,35 ./ReSwiftTests/AutomaticallySkipRepeatsTests.swift:10,12,15,21,22,28,29,33,34,38,39,45,46,52,53,59,60,66,67,68,69,73,74,75,79,80,84,85,86,89,90,92,100,101 ./ReSwiftTests/StoreTests.swift:8,11,13,20,22,23,29,36,37,39,40,41,42,46,49,50,61,62,73,74,75,78,79,81,83,86,88,89,90 ./ReSwiftTests/TypeHelperTests.swift:8,14,17,19,27,29,30,32,34,35,43,45,46,48,50,51,59,61,62,64,66,67 ./ReSwiftTests/StoreMiddlewareTests.swift:8,11,15,21,22,23,24,25,29,35,36,37,38,39,43,46,47,49,50,51,52,56,59,64,69,70,71,72,73,79,80,81,82,83,85,100,103,106,108,109,125,128,131,133,134,142,145,147,149,150,152,157,163,169,170 ./ReSwiftTests/StoreDispatchTests.swift:8,11,13,16,19,24,25,35,36,43,46,47,49,51,52,58,61,67,68,69,70,75,76,77,83,84,85,86,94,100,101,102,103,108,109,110,114,115,116,117,118,122,126,128,129 ./ReSwiftTests/XCTest+Assertions.swift:6,13,15,20,42,43,45,55,58,62,63,66,72,76,77,78,80 ./Package.swift:3 ./ReSwift/ReSwift.h:8,10,13,16 ./ReSwift/CoreTypes/StoreType.swift:8,16,18,21,27,32,37,43,53,59,62,72,76,80,85,89,91,100,101,102,104,106,112,118,123,126,131,140,144,146,155,156,157,159,162,167 ./ReSwift/CoreTypes/Reducer.swift:8 ./ReSwift/CoreTypes/DispatchingStoreType.swift:2,4,11,14,16,20,24 ./ReSwift/CoreTypes/State.swift:8 ./ReSwift/CoreTypes/Subscription.swift:8,18,22,26,31,35,40,42,51,57,63,64,65,66,72,73,76,77,78,84,88,92,93,94,95,97,105,106,107,113,115,116,122,124,125,141,144,145,146,147,148,152,154,156,160,161,162,166,167,168,171,181,182,193,194,195 ./ReSwift/CoreTypes/Middleware.swift:8 ./ReSwift/CoreTypes/Store.swift:8,17,19,27,28,29,30,31,33,35,37,39,43,47,48,49,71,76,77,78,93,94,99,105,107,110,111,112,116,117,121,127,130,131,137,143,144,149,153,155,156,166,167,171,173,174,177,178,183,184,185,189,190,196,200,201,202,203,205,208,215,216,218,223,225,229,232,233,234,241,243,244 ./ReSwift/CoreTypes/StoreSubscriber.swift:8,12,13,16,18,19,25,26,27 ./ReSwift/CoreTypes/Action.swift:8,12 ./ReSwift/Utils/Coding.swift:8,12 ./ReSwift/Utils/Synchronized.swift:10,12,19,25,26 ./ReSwift/Utils/Assertions.swift:6,8,10,13,24,25,32 ./ReSwift/Utils/TypeHelper.swift:8,12,27,28,31,32,34 <<<<<< EOF