Skip to content

Commit 1769f04

Browse files
committed
Move initialEffect from Store to Reducer
1 parent f8864cf commit 1769f04

13 files changed

Lines changed: 75 additions & 33 deletions

File tree

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
- name: "publish to Maven Central"
4040
run: |
4141
cd lib
42-
./gradlew publishAndReleaseToMavenCentral --no-daemon --no-parallel --no-configuration-cache
42+
./gradlew publishToMavenCentral --no-daemon --no-parallel --no-configuration-cache
4343
env:
4444
storeVersionTag: ${{ github.ref_name }}
4545
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }}

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# changelog
22

3+
## `[0.2.0]` - 2025-08-24
4+
5+
- Remove `initialEffect` from `Store` factory functions
6+
- Add `initialEffect` to `Reducer` factory function
7+
38
## `[0.1.0]` - 2025-08-03
49

510
- initial release

lib/api/store.api

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public final class at/florianschuster/store/EffectKt {
5151
}
5252

5353
public abstract interface class at/florianschuster/store/Reducer {
54+
public abstract fun getInitialEffect ()Lat/florianschuster/store/Effect;
5455
public abstract fun reduce (Lat/florianschuster/store/Reducer$Context;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
5556
}
5657

@@ -61,7 +62,8 @@ public abstract interface class at/florianschuster/store/Reducer$Context {
6162

6263
public final class at/florianschuster/store/ReducerKt {
6364
public static final fun EmptyReducer ()Lat/florianschuster/store/Reducer;
64-
public static final fun Reducer (Lkotlin/jvm/functions/Function3;)Lat/florianschuster/store/Reducer;
65+
public static final fun Reducer (Lat/florianschuster/store/Effect;Lkotlin/jvm/functions/Function3;)Lat/florianschuster/store/Reducer;
66+
public static synthetic fun Reducer$default (Lat/florianschuster/store/Effect;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lat/florianschuster/store/Reducer;
6567
}
6668

6769
public abstract interface class at/florianschuster/store/Store {
@@ -122,10 +124,10 @@ public final class at/florianschuster/store/StoreEvents$Companion {
122124
}
123125

124126
public final class at/florianschuster/store/StoreKt {
125-
public static final fun Store (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Lat/florianschuster/store/Effect;Lat/florianschuster/store/Reducer;Lat/florianschuster/store/StoreEvents;)Lat/florianschuster/store/Store;
126-
public static final fun Store (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Lat/florianschuster/store/Effect;Ljava/util/List;Lat/florianschuster/store/StoreEvents;)Lat/florianschuster/store/Store;
127-
public static synthetic fun Store$default (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Lat/florianschuster/store/Effect;Lat/florianschuster/store/Reducer;Lat/florianschuster/store/StoreEvents;ILjava/lang/Object;)Lat/florianschuster/store/Store;
128-
public static synthetic fun Store$default (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Lat/florianschuster/store/Effect;Ljava/util/List;Lat/florianschuster/store/StoreEvents;ILjava/lang/Object;)Lat/florianschuster/store/Store;
127+
public static final fun Store (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Lat/florianschuster/store/Reducer;Lat/florianschuster/store/StoreEvents;)Lat/florianschuster/store/Store;
128+
public static final fun Store (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Ljava/util/List;Lat/florianschuster/store/StoreEvents;)Lat/florianschuster/store/Store;
129+
public static synthetic fun Store$default (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Lat/florianschuster/store/Reducer;Lat/florianschuster/store/StoreEvents;ILjava/lang/Object;)Lat/florianschuster/store/Store;
130+
public static synthetic fun Store$default (Ljava/lang/Object;Ljava/lang/Object;Lkotlinx/coroutines/CoroutineScope;Ljava/util/List;Lat/florianschuster/store/StoreEvents;ILjava/lang/Object;)Lat/florianschuster/store/Store;
129131
public static final fun component1 (Lat/florianschuster/store/Store;)Lkotlinx/coroutines/flow/StateFlow;
130132
public static final fun component2 (Lat/florianschuster/store/Store;)Lkotlin/jvm/functions/Function1;
131133
}

lib/api/store.klib.api

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ abstract interface <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotli
3030
}
3131

3232
abstract interface <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Reducer { // at.florianschuster.store/Reducer|null[0]
33+
abstract val initialEffect // at.florianschuster.store/Reducer.initialEffect|{}initialEffect[0]
34+
abstract fun <get-initialEffect>(): at.florianschuster.store/Effect<#A, #B>? // at.florianschuster.store/Reducer.initialEffect.<get-initialEffect>|<get-initialEffect>(){}[0]
35+
3336
abstract fun (at.florianschuster.store/Reducer.Context<#A, #B>).reduce(#C, #B): #C // at.florianschuster.store/Reducer.reduce|reduce@at.florianschuster.store.Reducer.Context<1:0,1:1>(1:2;1:1){}[0]
3437

3538
abstract interface <#A1: kotlin/Any?, #B1: kotlin/Any?> Context { // at.florianschuster.store/Reducer.Context|null[0]
@@ -135,9 +138,9 @@ final class <#A: kotlin/Any?, #B: kotlin/Any?> at.florianschuster.store/EffectHa
135138
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?> (at.florianschuster.store/Reducer<#D, #E, #F>).at.florianschuster.store/delegate(#F, #D, kotlinx.coroutines/CoroutineScope, kotlin/Function1<#B, #E?>, kotlin/Function3<at.florianschuster.store/DelegateStore.ExpandStateContext<#A, #B>, #C, #F, #C>, at.florianschuster.store/StoreEvents? = ...): at.florianschuster.store/DelegateStore<#A, #B, #C, #D, #E, #F> // at.florianschuster.store/delegate|delegate@at.florianschuster.store.Reducer<0:3,0:4,0:5>(0:5;0:3;kotlinx.coroutines.CoroutineScope;kotlin.Function1<0:1,0:4?>;kotlin.Function3<at.florianschuster.store.DelegateStore.ExpandStateContext<0:0,0:1>,0:2,0:5,0:2>;at.florianschuster.store.StoreEvents?){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>;3§<kotlin.Any?>;4§<kotlin.Any?>;5§<kotlin.Any?>}[0]
136139
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?> (at.florianschuster.store/Store<#D, #E, #F>).at.florianschuster.store/delegate(kotlin/Function1<#B, #E?>, kotlin/Function3<at.florianschuster.store/DelegateStore.ExpandStateContext<#A, #B>, #C, #F, #C>): at.florianschuster.store/DelegateStore<#A, #B, #C, #D, #E, #F> // at.florianschuster.store/delegate|delegate@at.florianschuster.store.Store<0:3,0:4,0:5>(kotlin.Function1<0:1,0:4?>;kotlin.Function3<at.florianschuster.store.DelegateStore.ExpandStateContext<0:0,0:1>,0:2,0:5,0:2>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>;3§<kotlin.Any?>;4§<kotlin.Any?>;5§<kotlin.Any?>}[0]
137140
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/EmptyReducer(): at.florianschuster.store/Reducer<#A, #B, #C> // at.florianschuster.store/EmptyReducer|EmptyReducer(){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
138-
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Reducer(kotlin/Function3<at.florianschuster.store/Reducer.Context<#A, #B>, #C, #B, #C>): at.florianschuster.store/Reducer<#A, #B, #C> // at.florianschuster.store/Reducer|Reducer(kotlin.Function3<at.florianschuster.store.Reducer.Context<0:0,0:1>,0:2,0:1,0:2>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
139-
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Store(#C, #A, kotlinx.coroutines/CoroutineScope, at.florianschuster.store/Effect<#A, #B>? = ..., at.florianschuster.store/Reducer<#A, #B, #C>, at.florianschuster.store/StoreEvents? = ...): at.florianschuster.store/Store<#A, #B, #C> // at.florianschuster.store/Store|Store(0:2;0:0;kotlinx.coroutines.CoroutineScope;at.florianschuster.store.Effect<0:0,0:1>?;at.florianschuster.store.Reducer<0:0,0:1,0:2>;at.florianschuster.store.StoreEvents?){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
140-
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Store(#C, #A, kotlinx.coroutines/CoroutineScope, at.florianschuster.store/Effect<#A, #B>? = ..., kotlin.collections/List<at.florianschuster.store/DelegateStore<#A, #B, #C, *, *, *>>, at.florianschuster.store/StoreEvents? = ...): at.florianschuster.store/Store<#A, #B, #C> // at.florianschuster.store/Store|Store(0:2;0:0;kotlinx.coroutines.CoroutineScope;at.florianschuster.store.Effect<0:0,0:1>?;kotlin.collections.List<at.florianschuster.store.DelegateStore<0:0,0:1,0:2,*,*,*>>;at.florianschuster.store.StoreEvents?){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
141+
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Reducer(at.florianschuster.store/Effect<#A, #B>? = ..., kotlin/Function3<at.florianschuster.store/Reducer.Context<#A, #B>, #C, #B, #C>): at.florianschuster.store/Reducer<#A, #B, #C> // at.florianschuster.store/Reducer|Reducer(at.florianschuster.store.Effect<0:0,0:1>?;kotlin.Function3<at.florianschuster.store.Reducer.Context<0:0,0:1>,0:2,0:1,0:2>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
142+
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Store(#C, #A, kotlinx.coroutines/CoroutineScope, at.florianschuster.store/Reducer<#A, #B, #C>, at.florianschuster.store/StoreEvents? = ...): at.florianschuster.store/Store<#A, #B, #C> // at.florianschuster.store/Store|Store(0:2;0:0;kotlinx.coroutines.CoroutineScope;at.florianschuster.store.Reducer<0:0,0:1,0:2>;at.florianschuster.store.StoreEvents?){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
143+
final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> at.florianschuster.store/Store(#C, #A, kotlinx.coroutines/CoroutineScope, kotlin.collections/List<at.florianschuster.store/DelegateStore<#A, #B, #C, *, *, *>>, at.florianschuster.store/StoreEvents? = ...): at.florianschuster.store/Store<#A, #B, #C> // at.florianschuster.store/Store|Store(0:2;0:0;kotlinx.coroutines.CoroutineScope;kotlin.collections.List<at.florianschuster.store.DelegateStore<0:0,0:1,0:2,*,*,*>>;at.florianschuster.store.StoreEvents?){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
141144
final fun <#A: kotlin/Any?, #B: kotlin/Any?> (at.florianschuster.store/DelegateStore.ExpandStateContext<#A, #B>).at.florianschuster.store/cancelEffect(kotlin/Any) // at.florianschuster.store/cancelEffect|cancelEffect@at.florianschuster.store.DelegateStore.ExpandStateContext<0:0,0:1>(kotlin.Any){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
142145
final fun <#A: kotlin/Any?, #B: kotlin/Any?> (at.florianschuster.store/DelegateStore.ExpandStateContext<#A, #B>).at.florianschuster.store/cancelEffects(kotlin.collections/List<kotlin/Any>) // at.florianschuster.store/cancelEffects|cancelEffects@at.florianschuster.store.DelegateStore.ExpandStateContext<0:0,0:1>(kotlin.collections.List<kotlin.Any>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
143146
final fun <#A: kotlin/Any?, #B: kotlin/Any?> (at.florianschuster.store/DelegateStore.ExpandStateContext<#A, #B>).at.florianschuster.store/effect(kotlin/Any? = ..., kotlin.coroutines/SuspendFunction1<at.florianschuster.store/EffectExecution.Context<#A, #B>, kotlin/Unit>) // at.florianschuster.store/effect|effect@at.florianschuster.store.DelegateStore.ExpandStateContext<0:0,0:1>(kotlin.Any?;kotlin.coroutines.SuspendFunction1<at.florianschuster.store.EffectExecution.Context<0:0,0:1>,kotlin.Unit>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]

lib/src/commonMain/kotlin/at/florianschuster/store/Implementation.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ internal class StoreImplementation<Environment, Action, State>(
1414
initialState: State,
1515
private val environment: Environment,
1616
effectScope: CoroutineScope,
17-
initialEffect: Effect<Environment, Action>?,
1817
private val reducer: Reducer<Environment, Action, State>,
1918
private val events: StoreEvents?,
2019
) : Store<Environment, Action, State> {
@@ -25,8 +24,14 @@ internal class StoreImplementation<Environment, Action, State>(
2524
override val state: StateFlow<State> = _state.asStateFlow()
2625

2726
init {
28-
events?.emit(StoreEvent.Initialization(initialState, environment, initialEffect != null))
29-
initialEffect?.let { effectHandler.handle(listOf(it)) }
27+
events?.emit(
28+
StoreEvent.Initialization(
29+
initialState = initialState,
30+
environment = environment,
31+
hasInitialEffect = reducer.initialEffect != null
32+
)
33+
)
34+
reducer.initialEffect?.let { effectHandler.handle(listOf(it)) }
3035
}
3136

3237
override fun dispatch(action: Action) {
@@ -61,7 +66,6 @@ internal class DelegatingStoreImplementation<Environment, Action, State>(
6166
initialState: State,
6267
private val environment: Environment,
6368
effectScope: CoroutineScope,
64-
initialEffect: Effect<Environment, Action>?,
6569
private val delegates: List<DelegateStore<Environment, Action, State, *, *, *>>,
6670
private val events: StoreEvents?,
6771
) : Store<Environment, Action, State> {
@@ -73,7 +77,7 @@ internal class DelegatingStoreImplementation<Environment, Action, State>(
7377
override val state: StateFlow<State> = _state.asStateFlow()
7478

7579
init {
76-
events?.emit(StoreEvent.Initialization(initialState, environment, initialEffect != null))
80+
events?.emit(StoreEvent.Initialization(initialState, environment, false))
7781
for (delegate in delegates) {
7882
effectScope.launch {
7983
delegate.state.collect { delegateState ->
@@ -98,7 +102,6 @@ internal class DelegatingStoreImplementation<Environment, Action, State>(
98102
}
99103
}
100104
}
101-
initialEffect?.let { effectHandler.handle(listOf(it)) }
102105
}
103106

104107
override fun dispatch(action: Action) {

lib/src/commonMain/kotlin/at/florianschuster/store/Reducer.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ interface Reducer<Environment, Action, State> {
1313
fun add(effect: Effect<Environment, Action>)
1414
}
1515

16+
/**
17+
* An optional [Effect] that is executed when the [Reducer] is initialized.
18+
*/
19+
val initialEffect: Effect<Environment, Action>?
20+
1621
/**
1722
* Reduces the [previousState] based on the [action] and returns a new [State].
1823
*
@@ -36,25 +41,28 @@ interface Reducer<Environment, Action, State> {
3641
* Creates a [Reducer].
3742
*/
3843
fun <Environment, Action, State> Reducer(
44+
initialEffect: Effect<Environment, Action>? = null,
3945
reduce: Reducer.Context<Environment, Action>.(
4046
previousState: State,
4147
action: Action,
4248
) -> State,
43-
): Reducer<Environment, Action, State> = StoreReducer(reduce = reduce)
49+
): Reducer<Environment, Action, State> = StoreReducer(initialEffect = initialEffect, reduce = reduce)
4450

4551
/**
4652
* Creates an empty [Reducer] that does not change the state.
4753
*/
4854
@Suppress("FunctionName")
4955
fun <Environment, Action, State> EmptyReducer(): Reducer<Environment, Action, State> =
5056
object : Reducer<Environment, Action, State> {
57+
override val initialEffect: Effect<Environment, Action>? = null
5158
override fun Reducer.Context<Environment, Action>.reduce(
5259
previousState: State,
5360
action: Action,
5461
): State = previousState
5562
}
5663

5764
internal class StoreReducer<Environment, Action, State>(
65+
override val initialEffect: Effect<Environment, Action>?,
5866
private val reduce: Reducer.Context<Environment, Action>.(
5967
previousState: State,
6068
action: Action,

lib/src/commonMain/kotlin/at/florianschuster/store/Store.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,19 @@ operator fun <Action> Store<*, Action, *>.component2(): (Action) -> Unit = ::dis
3030
* @param initialState The initial [State] of the [Store].
3131
* @param environment The [Environment] that is available within the contexts of [Reducer]s and [Effect]s.
3232
* @param effectScope The [CoroutineScope] in which [Effect]s are executed.
33-
* @param initialEffect An optional [Effect] that is executed when the [Store] is initialized.
3433
* @param reducer The [Reducer] that handles updating [State] based on dispatched [Action]s.
3534
* @param events An optional [StoreEvents] that emits [StoreEvent]s. Can be used for logging or testing.
3635
*/
3736
fun <Environment, Action, State> Store(
3837
initialState: State,
3938
environment: Environment,
4039
effectScope: CoroutineScope,
41-
initialEffect: Effect<Environment, Action>? = null,
4240
reducer: Reducer<Environment, Action, State>,
4341
events: StoreEvents? = null,
4442
): Store<Environment, Action, State> = StoreImplementation(
4543
effectScope = effectScope,
4644
environment = environment,
4745
initialState = initialState,
48-
initialEffect = initialEffect,
4946
reducer = reducer,
5047
events = events,
5148
)
@@ -59,7 +56,6 @@ fun <Environment, Action, State> Store(
5956
* @param initialState The initial [State] of the created parent [Store].
6057
* @param environment The [Environment] that is available within the contexts of [Reducer]s and [Effect]s.
6158
* @param effectScope The [CoroutineScope] in which [Effect]s are executed.
62-
* @param initialEffect An optional [Effect] that is executed when the [Store] is initialized.
6359
* @param delegates A list of [DelegateStore]s that this [Store] delegates [Action]s and [State] to.
6460
* The order of the list of [delegates] is important, as it determines the order in which they receive
6561
* dispatched [Action]s.
@@ -69,14 +65,12 @@ fun <Environment, Action, State> Store(
6965
initialState: State,
7066
environment: Environment,
7167
effectScope: CoroutineScope,
72-
initialEffect: Effect<Environment, Action>? = null,
7368
delegates: List<DelegateStore<Environment, Action, State, *, *, *>>,
7469
events: StoreEvents? = null,
7570
): Store<Environment, Action, State> = DelegatingStoreImplementation(
7671
initialState = initialState,
7772
environment = environment,
7873
effectScope = effectScope,
79-
initialEffect = initialEffect,
8074
delegates = delegates,
8175
events = events,
8276
)

lib/src/commonMain/kotlin/at/florianschuster/store/StoreEvents.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ sealed interface StoreEvent {
2727
val hasInitialEffect: Boolean,
2828
) : StoreEvent {
2929
override fun toString(): String =
30-
"init > (initialState = \"$initialState\", " +
31-
"environment = \"$environment\", " +
30+
"init > (initialState=\"$initialState\", " +
31+
"environment=\"$environment\", " +
3232
"initialEffect=\"$hasInitialEffect\")"
3333
}
3434

lib/src/commonTest/kotlin/at/florianschuster/store/DelegateTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,9 @@ class DelegateTest {
244244
initialState = 42,
245245
environment = 1,
246246
effectScope = backgroundScope,
247-
initialEffect = effect { dispatch(0) },
248-
reducer = Reducer { previousState, action ->
247+
reducer = Reducer(
248+
initialEffect = effect { dispatch(0) }
249+
) { previousState, action ->
249250
effect(id = "id") {
250251
delay(1.seconds)
251252
dispatch(1)

lib/src/commonTest/kotlin/at/florianschuster/store/ReducerTest.kt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package at.florianschuster.store
22

33
import kotlin.test.Test
44
import kotlin.test.assertEquals
5+
import kotlin.test.assertNull
56

67
internal class ReducerTest {
78

@@ -11,11 +12,30 @@ internal class ReducerTest {
1112
override val environment: Int = 42
1213
override fun add(effect: Effect<Int, Int>) = error("not implemented")
1314
}
14-
val reducer: Reducer<Int, Int, Int> = Reducer { previousState, action ->
15+
val reducer: Reducer<Int, Int, Int> = Reducer { previousState, _ ->
1516
previousState + 420
1617
}
1718
with(context) {
1819
with(reducer) {
20+
assertNull(initialEffect)
21+
assertEquals(420, reduce(0, 2))
22+
}
23+
}
24+
}
25+
26+
@Test
27+
fun `Reducer factory function with initialEffect`() {
28+
val context = object : Reducer.Context<Int, Int> {
29+
override val environment: Int = 42
30+
override fun add(effect: Effect<Int, Int>) = error("not implemented")
31+
}
32+
val initialEffect = effect<Int, Int> { }
33+
val reducer: Reducer<Int, Int, Int> = Reducer(initialEffect) { previousState, _ ->
34+
previousState + 420
35+
}
36+
with(context) {
37+
with(reducer) {
38+
assertEquals(initialEffect, this.initialEffect)
1939
assertEquals(420, reduce(0, 2))
2040
}
2141
}
@@ -30,6 +50,7 @@ internal class ReducerTest {
3050
val reducer: Reducer<Int, Int, Int> = EmptyReducer()
3151
with(context) {
3252
with(reducer) {
53+
assertNull(initialEffect)
3354
assertEquals(1, reduce(1, 2))
3455
}
3556
}

0 commit comments

Comments
 (0)