I have a problem testing coupled concatenated action/effects. To demonstrate the problem I modified the
02-Effects-Basics and 02-Effects-BasicsTests code. I added 3 rather simple actions
enum EffectsBasicsAction: Equatable {
case multiAction(Int)
case multiplyCountBy(Int)
case decrementCountBy(Int)
...
decrementCountBy is queued to multiplyCountBy and is itself concatenated multiple times in multiAction.
...
case .multiAction(var repCount):
var effects: [Effect<EffectsBasicsAction, Never>] = []
while repCount > 0 {
effects.append(Effect(value: .multiplyCountBy(state.count)))
repCount -= 1
}
return Effect.concatenate(effects).delay(for: 1, scheduler: environment.mainQueue).eraseToEffect()
case .multiplyCountBy(let factor):
state.count *= factor
return Effect(value: .decrementCountBy(5))
case .decrementCountBy(let number):
state.count -= number
return .none
...
I inserted another button into EffectsBasicsView to start multiAction and modified the starter count state.
struct EffectsBasicsState: Equatable {
var count = -3
...
struct EffectsBasicsView: View {
...
Button("Multiple actions") { viewStore.send(.multiAction(3)) }
...
To test this I created a new test.
func testMultiActionDown() {
let store = TestStore(
initialState: EffectsBasicsState(),
reducer: effectsBasicsReducer,
environment: EffectsBasicsEnvironment(
mainQueue: self.scheduler.eraseToAnyScheduler(),
numberFact: { _ in fatalError("Unimplemented") }
)
)
store.assert(
.send(.multiAction(3)) {
$0.count = -3
},
.do { self.scheduler.advance(by: 1) },
.receive(.multiplyCountBy(-3)) {
$0.count = 9
},
.receive(.multiplyCountBy(-3)) {
$0.count = -27
},
.receive(.multiplyCountBy(-3)) {
$0.count = 81
},
.receive(.decrementCountBy(5)) {
$0.count = 76
},
.receive(.decrementCountBy(5)) {
$0.count = 71
},
.receive(.decrementCountBy(5)) {
$0.count = 66
}
)
}
The order of actions in the app is multiAction->multiplyCountBy->decrementCountBy (the last two repeated).
For the test to succeed the actions have to be ordered as shown, which succeeds but results in a different state.count. The flow inside the app is correct.
Is it possible to handle such situations in TCA?