44import re
55from dataclasses import replace
66from typing import TYPE_CHECKING , Generator
7+ from unittest .mock import call
78
89import pytest
910from immutable import Immutable
1011
1112from redux .basic_types import (
13+ AutorunOptions ,
1214 BaseAction ,
1315 CompleteReducerResult ,
1416 CreateStoreOptions ,
2022from redux .main import Store
2123
2224if TYPE_CHECKING :
25+ from pytest_mock import MockerFixture
26+
2327 from redux_pytest .fixtures import StoreSnapshot
2428
2529
@@ -30,10 +34,15 @@ class StateType(Immutable):
3034class IncrementAction (BaseAction ): ...
3135
3236
37+ class DecrementAction (BaseAction ): ...
38+
39+
3340class IncrementByTwoAction (BaseAction ): ...
3441
3542
36- Action = IncrementAction | IncrementByTwoAction | InitAction | FinishAction
43+ Action = (
44+ IncrementAction | DecrementAction | IncrementByTwoAction | InitAction | FinishAction
45+ )
3746
3847
3948def reducer (
@@ -48,6 +57,9 @@ def reducer(
4857 if isinstance (action , IncrementAction ):
4958 return replace (state , value = state .value + 1 )
5059
60+ if isinstance (action , DecrementAction ):
61+ return replace (state , value = state .value - 1 )
62+
5163 if isinstance (action , IncrementByTwoAction ):
5264 return replace (state , value = state .value + 2 )
5365
@@ -189,3 +201,112 @@ def render(value: int) -> int:
189201 r'.*\(func: <function test_repr\.<locals>\.render at .*>, last_value: 1\)$' ,
190202 repr (render ),
191203 )
204+
205+
206+ def test_auto_call_without_reactive (store : StoreType ) -> None :
207+ with pytest .raises (
208+ ValueError ,
209+ match = '^`reactive` must be `True` if `auto_call` is `True`$' ,
210+ ):
211+
212+ @store .autorun (
213+ lambda state : state .value ,
214+ options = AutorunOptions (reactive = False , auto_call = True ),
215+ )
216+ def _ (_ : int ) -> int :
217+ pytest .fail ('This should never be called' )
218+
219+
220+ call_sequence = [
221+ # 0
222+ [
223+ (IncrementAction ()),
224+ ],
225+ # 1
226+ [
227+ (IncrementAction ()),
228+ (DecrementAction ()),
229+ (IncrementByTwoAction ()),
230+ (DecrementAction ()),
231+ (IncrementAction ()),
232+ ],
233+ # 3
234+ [
235+ (DecrementAction ()),
236+ (DecrementAction ()),
237+ ],
238+ # 1
239+ ]
240+
241+
242+ def test_no_auto_call_with_initial_call_and_reactive_set (
243+ store : StoreType ,
244+ mocker : MockerFixture ,
245+ ) -> None :
246+ def render (_ : int ) -> None : ...
247+
248+ render = mocker .create_autospec (render )
249+
250+ render_autorun = store .autorun (
251+ lambda state : state .value ,
252+ options = AutorunOptions (reactive = True , auto_call = False , initial_call = True ),
253+ )(render )
254+
255+ for actions in call_sequence :
256+ for action in actions :
257+ store .dispatch (action )
258+ render_autorun ()
259+
260+ assert render .mock_calls == [call (0 ), call (1 ), call (3 ), call (1 )]
261+
262+
263+ def test_no_auto_call_and_no_initial_call_with_reactive_set (
264+ store : StoreType ,
265+ mocker : MockerFixture ,
266+ ) -> None :
267+ def render (_ : int ) -> None : ...
268+
269+ render = mocker .create_autospec (render )
270+
271+ render_autorun = store .autorun (
272+ lambda state : state .value ,
273+ options = AutorunOptions (reactive = True , auto_call = False , initial_call = False ),
274+ )(render )
275+
276+ for actions in call_sequence :
277+ for action in actions :
278+ store .dispatch (action )
279+ render_autorun ()
280+
281+ assert render .mock_calls == [call (1 ), call (3 ), call (1 )]
282+
283+
284+ def test_with_auto_call_and_initial_call_and_reactive_set (
285+ store : StoreType ,
286+ mocker : MockerFixture ,
287+ ) -> None :
288+ def render (_ : int ) -> None : ...
289+
290+ render = mocker .create_autospec (render )
291+
292+ render_autorun = store .autorun (
293+ lambda state : state .value ,
294+ options = AutorunOptions (reactive = True , auto_call = True , initial_call = True ),
295+ )(render )
296+
297+ for actions in call_sequence :
298+ for action in actions :
299+ store .dispatch (action )
300+ render_autorun ()
301+
302+ assert render .mock_calls == [
303+ call (0 ),
304+ call (1 ),
305+ call (2 ),
306+ call (1 ),
307+ call (3 ),
308+ call (2 ),
309+ call (3 ),
310+ call (2 ),
311+ call (1 ),
312+ ]
0 commit comments