Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ReSwift-Thunk.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
65A3D6F0218B8A300075CB92 /* Thunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A3D6EF218B8A300075CB92 /* Thunk.swift */; };
65A3D6F3218C91F20075CB92 /* ReSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A3D6F2218C91F20075CB92 /* ReSwift.framework */; };
65A3D6F5218C92420075CB92 /* createThunksMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A3D6F4218C92420075CB92 /* createThunksMiddleware.swift */; };
D28E4F562214F37100DEFA7D /* ExpectThunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28E4F552214F37100DEFA7D /* ExpectThunk.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -35,6 +36,7 @@
65A3D6EF218B8A300075CB92 /* Thunk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thunk.swift; sourceTree = "<group>"; };
65A3D6F2218C91F20075CB92 /* ReSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReSwift.framework; path = Carthage/Build/iOS/ReSwift.framework; sourceTree = "<group>"; };
65A3D6F4218C92420075CB92 /* createThunksMiddleware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = createThunksMiddleware.swift; sourceTree = "<group>"; };
D28E4F552214F37100DEFA7D /* ExpectThunk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpectThunk.swift; sourceTree = "<group>"; };
D4286E7721EFED3F00D5749B /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
D4286E7821EFED4D00D5749B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -94,6 +96,7 @@
65A3D6E2218B89A60075CB92 /* ReSwift-ThunkTests */ = {
isa = PBXGroup;
children = (
D28E4F552214F37100DEFA7D /* ExpectThunk.swift */,
65A3D6E3218B89A60075CB92 /* Tests.swift */,
65A3D6E5218B89A60075CB92 /* Info.plist */,
);
Expand Down Expand Up @@ -227,6 +230,7 @@
buildActionMask = 2147483647;
files = (
65A3D6E4218B89A60075CB92 /* Tests.swift in Sources */,
D28E4F562214F37100DEFA7D /* ExpectThunk.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
70 changes: 70 additions & 0 deletions ReSwift-ThunkTests/ExpectThunk.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//
// ExpectThunk.swift
// ReSwift-Thunk-Tests
//
// Created by Jason Prasad on 2/13/19.
// Copyright © 2019 ReSwift. All rights reserved.
//

import XCTest
import ReSwift

@testable import ReSwiftThunk

// TODO: no longer allow subclassing
public class ExpectThunk<State: StateType> {
public typealias ActionAssertion = (Action) -> Void
private var dispatch: DispatchFunction {
return { action in
let actionAssertion = self.actionAssertions.remove(at: 0)
actionAssertion(action)
if self.actionAssertions.count == 0 {
self.expectation.fulfill()
}
}
}
private var actionAssertions = [ActionAssertion]()
private var expectedStates = [State]()
private var expectation: XCTestExpectation
private var getState: () -> State? {
return {
if self.expectedStates.count > 0 {
return self.expectedStates.removeFirst()
} else {
return nil
}
}
}
private let thunk: Thunk<State>
public init(_ thunk: Thunk<State>, description: String? = nil) {
self.thunk = thunk
expectation = XCTestExpectation(description: description ?? "\(ExpectThunk.self)")
}
}

extension ExpectThunk {
public func dispatches<A: Action & Equatable>(_ expected: A, file: StaticString = #file, line: UInt = #line) -> Self {
actionAssertions.append({ received in
XCTAssert(received as? A == expected, "dispatched action does not equal expected: \(received) \(expected)", file: file, line: line)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line Length Violation: Line should be 120 characters or less: currently 143 characters (line_length)

})
return self
}
public func dispatches(_ matcher: @escaping ActionAssertion) -> Self {
actionAssertions.append(matcher)
return self
}
}

extension ExpectThunk {
func getsState(_ state: State) -> Self {
expectedStates.append(state)
return self
}
}

extension ExpectThunk {
func run() -> XCTestExpectation {
thunk.body(dispatch, getState)
return expectation
}
}
37 changes: 36 additions & 1 deletion ReSwift-ThunkTests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import XCTest
import ReSwift

private struct FakeState: StateType {}
private struct FakeAction: Action {}
private struct FakeAction: Action, Equatable {}
private struct AnotherFakeAction: Action, Equatable {}
private func fakeReducer(action: Action, state: FakeState?) -> FakeState {
return state ?? FakeState()
}
Expand Down Expand Up @@ -58,4 +59,38 @@ class Tests: XCTestCase {
store.dispatch(thunk)
XCTAssertTrue(thunkBodyCalled)
}

func testExpectThunk() {
let thunk = Thunk<FakeState> { dispatch, getState in
dispatch(FakeAction())
XCTAssertNotNil(getState())
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 0.5) {
dispatch(AnotherFakeAction())
XCTAssertNotNil(getState())
XCTAssertNil(getState())
}
dispatch(FakeAction())
}
let expect = ExpectThunk<FakeState>(thunk)
.dispatches(FakeAction())
.getsState(FakeState())
.dispatches {
XCTAssert($0 as? FakeAction == FakeAction())
}
.dispatches(AnotherFakeAction())
.getsState(FakeState())
.run()
/* NOTE: this will fail as it asserts order!
let expect = ExpectThunk<FakeState>(thunk)
.dispatches(FakeAction())
.getsState(FakeState())
.dispatches(AnotherFakeAction())
.dispatches {
XCTAssert($0 as? FakeAction == FakeAction())
}
.getsState(FakeState())
.run()
*/
wait(for: [expect], timeout: 1.0)
}
}