@@ -12,19 +12,59 @@ import Foundation
1212@testable import SwiftRex
1313import XCTest
1414
15- public enum Step < ActionType, StateType> {
16- case send(
17- ActionType ,
18- file: StaticString = #file,
19- line: UInt = #line,
20- stateChange: ( inout StateType ) -> Void = { _ in }
21- )
22- case receive(
23- ActionType ,
15+ public struct SendStep < ActionType, StateType> {
16+ public init (
17+ action: @autoclosure @escaping ( ) -> ActionType ,
2418 file: StaticString = #file,
2519 line: UInt = #line,
26- stateChange: ( inout StateType ) -> Void = { _ in }
27- )
20+ stateChange: @escaping ( inout StateType ) -> Void = { _ in }
21+ ) {
22+ self . action = action
23+ self . file = file
24+ self . line = line
25+ self . stateChange = stateChange
26+ }
27+
28+ let action : ( ) -> ActionType
29+ let file : StaticString
30+ let line : UInt
31+ let stateChange : ( inout StateType ) -> Void
32+ }
33+
34+ public struct ReceiveStep < ActionType, StateType> {
35+ public init ( isExpectedAction: @escaping ( ActionType ) -> Bool ,
36+ file: StaticString = #file,
37+ line: UInt = #line,
38+ stateChange: @escaping ( inout StateType ) -> Void = { _ in } ) {
39+ self . isExpectedAction = isExpectedAction
40+ self . file = file
41+ self . line = line
42+ self . stateChange = stateChange
43+ }
44+
45+ public init ( action: @autoclosure @escaping ( ) -> ActionType ,
46+ file: StaticString = #file,
47+ line: UInt = #line,
48+ stateChange: @escaping ( inout StateType ) -> Void = { _ in }
49+ ) where ActionType: Equatable {
50+ self . init (
51+ isExpectedAction: { $0 == action ( ) } ,
52+ file: file,
53+ line: line,
54+ stateChange: stateChange
55+ )
56+ }
57+
58+ let file : StaticString
59+ let line : UInt
60+ let stateChange : ( inout StateType ) -> Void
61+
62+ let isExpectedAction : ( ActionType ) -> Bool
63+ }
64+
65+ public enum Step < ActionType, StateType> {
66+ case send( SendStep < ActionType , StateType > )
67+ case receive( ReceiveStep < ActionType , StateType > )
2868 case sideEffectResult(
2969 do: ( ) -> Void
3070 )
@@ -39,7 +79,7 @@ extension XCTestCase {
3979 otherSteps: [ Step < M . InputActionType , M . StateType > ] = [ ] ,
4080 file: StaticString = #filePath,
4181 line: UInt = #line
42- ) where M. InputActionType == M . OutputActionType , M. InputActionType : Equatable , M . StateType: Equatable {
82+ ) where M. InputActionType == M . OutputActionType , M. StateType: Equatable {
4383 assert (
4484 initialValue: initialValue,
4585 reducer: reducer,
@@ -60,7 +100,7 @@ extension XCTestCase {
60100 stateEquating: ( M . StateType , M . StateType ) -> Bool ,
61101 file: StaticString = #filePath,
62102 line: UInt = #line
63- ) where M. InputActionType == M . OutputActionType , M . InputActionType : Equatable {
103+ ) where M. InputActionType == M . OutputActionType {
64104 assert (
65105 initialValue: initialValue,
66106 reducer: reducer,
@@ -80,7 +120,7 @@ extension XCTestCase {
80120 stateEquating: ( M . StateType , M . StateType ) -> Bool ,
81121 file: StaticString = #filePath,
82122 line: UInt = #line
83- ) where M. InputActionType == M . OutputActionType , M . InputActionType : Equatable {
123+ ) where M. InputActionType == M . OutputActionType {
84124 var state = initialValue
85125 var middlewareResponses : [ M . OutputActionType ] = [ ]
86126 let gotAction = XCTestExpectation ( description: " got action " )
@@ -91,16 +131,21 @@ extension XCTestCase {
91131 }
92132 middleware. receiveContext ( getState: { state } , output: anyActionHandler)
93133
94- steps. forEach { step in
134+ steps. forEach { outerStep in
95135 var expected = state
96136
97- switch step {
98- case let . send( action, file, line, stateChange) :
137+ switch outerStep {
138+ case let . send( step) : //action, file, line, stateChange):
139+ let file = step. file
140+ let line = step. line
141+ let stateChange = step. stateChange
142+
99143 if !middlewareResponses. isEmpty {
100144 XCTFail ( " Action sent before handling \( middlewareResponses. count) pending effect(s) " , file: file, line: line)
101145 }
102146
103147 var afterReducer : AfterReducer = . doNothing( )
148+ let action = step. action ( )
104149 middleware. handle (
105150 action: action,
106151 from: . init( file: " \( file) " , function: " " , line: line, info: nil ) ,
@@ -110,8 +155,12 @@ extension XCTestCase {
110155 afterReducer. reducerIsDone ( )
111156
112157 stateChange ( & expected)
113- ensureStateMutation ( equating: stateEquating, statusQuo: state, expected: expected)
114- case let . receive( action, file, line, stateChange) :
158+ ensureStateMutation ( equating: stateEquating, statusQuo: state, expected: expected, step: outerStep)
159+ case let . receive( step) : //action, file, line, stateChange):
160+ let file = step. file
161+ let line = step. line
162+ let stateChange = step. stateChange
163+
115164 if middlewareResponses. isEmpty {
116165 _ = XCTWaiter . wait ( for: [ gotAction] , timeout: 0.2 )
117166 }
@@ -120,19 +169,19 @@ extension XCTestCase {
120169 break
121170 }
122171 let first = middlewareResponses. removeFirst ( )
123- XCTAssertEqual ( first, action , file: file, line: line)
172+ XCTAssertTrue ( step . isExpectedAction ( first) , file: file, line: line)
124173
125174 var afterReducer : AfterReducer = . doNothing( )
126175 middleware. handle (
127- action: action ,
176+ action: first ,
128177 from: . init( file: " \( file) " , function: " " , line: line, info: nil ) ,
129178 afterReducer: & afterReducer
130179 )
131- reducer. reduce ( action , & state)
180+ reducer. reduce ( first , & state)
132181 afterReducer. reducerIsDone ( )
133182
134183 stateChange ( & expected)
135- ensureStateMutation ( equating: stateEquating, statusQuo: state, expected: expected)
184+ ensureStateMutation ( equating: stateEquating, statusQuo: state, expected: expected, step : outerStep )
136185 case let . sideEffectResult( execute) :
137186 execute ( )
138187 }
@@ -144,10 +193,11 @@ extension XCTestCase {
144193 }
145194 }
146195
147- private func ensureStateMutation< StateType> (
196+ private func ensureStateMutation< ActionType , StateType> (
148197 equating: ( StateType , StateType ) -> Bool ,
149198 statusQuo: StateType ,
150199 expected: StateType ,
200+ step: Step < ActionType , StateType > ,
151201 file: StaticString = #filePath,
152202 line: UInt = #line
153203 ) {
@@ -159,7 +209,7 @@ extension XCTestCase {
159209 dump ( expected, to: & expectedString, name: nil , indent: 2 )
160210 let difference = diff ( old: expectedString, new: stateString) ?? " "
161211
162- return " Expected state different from current state \n \( difference) "
212+ return " Expected state after step \( step ) different from current state\n \( difference) "
163213 } ( ) ,
164214 file: file,
165215 line: line
0 commit comments