Skip to content

Commit d097b8a

Browse files
authored
Merge pull request #7 from SwiftRex/StateMutationAssertWithBetterDiagnostics
State mutation assert with better diagnostics
2 parents 19a2dcf + 01bb3c5 commit d097b8a

File tree

1 file changed

+93
-22
lines changed

1 file changed

+93
-22
lines changed

Sources/TestingExtensions/UseCaseTests.swift

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,70 +60,123 @@ public struct Send<ActionType, StateType>: StepProtocol {
6060
public init(
6161
action: @autoclosure @escaping () -> ActionType,
6262
file: StaticString = #file,
63+
fileForStateMutation: StaticString = #file,
6364
line: UInt = #line,
65+
lineForStateMutation: UInt = #line,
6466
stateChange: @escaping (inout StateType) -> Void = { _ in }
6567
) {
6668
self.action = action
6769
self.file = file
70+
self.fileForStateMutation = fileForStateMutation
6871
self.line = line
72+
self.lineForStateMutation = lineForStateMutation
6973
self.stateChange = stateChange
7074
}
7175

7276
let action: () -> ActionType
7377
let file: StaticString
7478
let line: UInt
79+
let fileForStateMutation: StaticString
80+
let lineForStateMutation: UInt
7581
let stateChange: (inout StateType) -> Void
7682

7783
public var asStep: Step<ActionType, StateType> {
78-
.send(action: action(), file: file, line: line, stateChange: stateChange)
84+
.send(
85+
action: action(),
86+
file: file,
87+
fileForStateMutation: fileForStateMutation,
88+
line: line,
89+
lineForStateMutation: lineForStateMutation,
90+
stateChange: stateChange
91+
)
7992
}
8093

81-
public func expectStateToHaveChanged(_ expectedMutation: @escaping (inout StateType) -> Void = { _ in }) -> Send {
82-
.init(action: action(), file: file, line: line, stateChange: { state in
94+
public func expectStateToHaveChanged(
95+
fileForStateMutation: StaticString = #file,
96+
lineForStateMutation: UInt = #line,
97+
_ expectedMutation: @escaping (inout StateType) -> Void = { _ in }
98+
) -> Send {
99+
Send(
100+
action: action(),
101+
file: file,
102+
fileForStateMutation: fileForStateMutation,
103+
line: line,
104+
lineForStateMutation: lineForStateMutation
105+
) { state in
83106
self.stateChange(&state)
84107
expectedMutation(&state)
85-
})
108+
}
86109
}
87110
}
88111

89112
public struct Receive<ActionType, StateType>: StepProtocol {
90-
public init(isExpectedAction: @escaping (ActionType) -> Bool,
91-
file: StaticString = #file,
92-
line: UInt = #line,
93-
stateChange: @escaping (inout StateType) -> Void = { _ in }) {
113+
public init(
114+
isExpectedAction: @escaping (ActionType) -> Bool,
115+
file: StaticString = #file,
116+
fileForStateMutation: StaticString = #file,
117+
line: UInt = #line,
118+
lineForStateMutation: UInt = #line,
119+
stateChange: @escaping (inout StateType) -> Void = { _ in }
120+
) {
94121
self.isExpectedAction = isExpectedAction
95122
self.file = file
123+
self.fileForStateMutation = fileForStateMutation
96124
self.line = line
125+
self.lineForStateMutation = lineForStateMutation
97126
self.stateChange = stateChange
98127
}
99128

100-
public init(action: @autoclosure @escaping () -> ActionType,
101-
file: StaticString = #file,
102-
line: UInt = #line,
103-
stateChange: @escaping (inout StateType) -> Void = { _ in }
129+
public init(
130+
action: @autoclosure @escaping () -> ActionType,
131+
file: StaticString = #file,
132+
fileForStateMutation: StaticString = #file,
133+
line: UInt = #line,
134+
lineForStateMutation: UInt = #line,
135+
stateChange: @escaping (inout StateType) -> Void = { _ in }
104136
) where ActionType: Equatable {
105137
self.init(
106138
isExpectedAction: { $0 == action() },
107139
file: file,
140+
fileForStateMutation: fileForStateMutation,
108141
line: line,
142+
lineForStateMutation: lineForStateMutation,
109143
stateChange: stateChange
110144
)
111145
}
112146

113147
let file: StaticString
114148
let line: UInt
149+
let fileForStateMutation: StaticString
150+
let lineForStateMutation: UInt
115151
let stateChange: (inout StateType) -> Void
116152
let isExpectedAction: (ActionType) -> Bool
117153

118154
public var asStep: Step<ActionType, StateType> {
119-
.receive(isExpectedAction: isExpectedAction, file: file, line: line, stateChange: stateChange)
155+
.receive(
156+
isExpectedAction: isExpectedAction,
157+
file: file,
158+
fileForStateMutation: fileForStateMutation,
159+
line: line,
160+
lineForStateMutation: lineForStateMutation,
161+
stateChange: stateChange
162+
)
120163
}
121164

122-
public func expectStateToHaveChanged(_ expectedMutation: @escaping (inout StateType) -> Void = { _ in }) -> Receive {
123-
.init(isExpectedAction: isExpectedAction, file: file, line: line, stateChange: { state in
165+
public func expectStateToHaveChanged(
166+
fileForStateMutation: StaticString = #file,
167+
lineForStateMutation: UInt = #line,
168+
_ expectedMutation: @escaping (inout StateType) -> Void = { _ in }
169+
) -> Receive {
170+
Receive(
171+
isExpectedAction: isExpectedAction,
172+
file: file,
173+
fileForStateMutation: fileForStateMutation,
174+
line: line,
175+
lineForStateMutation: lineForStateMutation
176+
) { state in
124177
self.stateChange(&state)
125178
expectedMutation(&state)
126-
})
179+
}
127180
}
128181
}
129182

@@ -142,18 +195,22 @@ public enum Step<ActionType, StateType>: StepProtocol {
142195
case send(
143196
action: @autoclosure () -> ActionType,
144197
file: StaticString = #file,
198+
fileForStateMutation: StaticString = #file,
145199
line: UInt = #line,
200+
lineForStateMutation: UInt = #line,
146201
stateChange: (inout StateType) -> Void = { _ in }
147202
)
148203
case receive(
149204
isExpectedAction: (ActionType) -> Bool,
150205
file: StaticString = #file,
206+
fileForStateMutation: StaticString = #file,
151207
line: UInt = #line,
208+
lineForStateMutation: UInt = #line,
152209
stateChange: (inout StateType) -> Void = { _ in }
153210
)
154211
case sideEffectResult(
155-
do: () -> Void
156-
)
212+
do: () -> Void
213+
)
157214

158215
public var asStep: Step<ActionType, StateType> {
159216
self
@@ -264,7 +321,7 @@ extension XCTestCase {
264321
var expected = state
265322

266323
switch outerStep {
267-
case let .send(action, file, line, stateChange)://action, file, line, stateChange):
324+
case let .send(action, file, fileForStateMutation, line, lineForStateMutation, stateChange):
268325
if !middlewareResponses.isEmpty {
269326
XCTFail("""
270327
Action sent before handling \(middlewareResponses.count) pending effect(s):
@@ -283,8 +340,15 @@ extension XCTestCase {
283340
afterReducer.reducerIsDone()
284341

285342
stateChange(&expected)
286-
ensureStateMutation(equating: stateEquating, statusQuo: state, expected: expected, step: outerStep, file: file, line: line)
287-
case let .receive(action, file, line, stateChange)://action, file, line, stateChange):
343+
ensureStateMutation(
344+
equating: stateEquating,
345+
statusQuo: state,
346+
expected: expected,
347+
step: outerStep,
348+
file: fileForStateMutation,
349+
line: lineForStateMutation
350+
)
351+
case let .receive(action, file, fileForStateMutation, line, lineForStateMutation, stateChange)://action, file, line, stateChange):
288352
if middlewareResponses.isEmpty {
289353
_ = XCTWaiter.wait(for: [gotAction], timeout: 0.2)
290354
}
@@ -305,7 +369,14 @@ extension XCTestCase {
305369
afterReducer.reducerIsDone()
306370

307371
stateChange(&expected)
308-
ensureStateMutation(equating: stateEquating, statusQuo: state, expected: expected, step: outerStep, file: file, line: line)
372+
ensureStateMutation(
373+
equating: stateEquating,
374+
statusQuo: state,
375+
expected: expected,
376+
step: outerStep,
377+
file: fileForStateMutation,
378+
line: lineForStateMutation
379+
)
309380
case let .sideEffectResult(execute):
310381
execute()
311382
}

0 commit comments

Comments
 (0)