-
Notifications
You must be signed in to change notification settings - Fork 2
/
test_todo.py
124 lines (99 loc) · 3.06 KB
/
test_todo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# ruff: noqa: D100, D101, D102, D103, D104, D107
from __future__ import annotations
import logging
import time
import uuid
from dataclasses import replace
from typing import TYPE_CHECKING
import pytest
from immutable import Immutable
from redux import (
BaseAction,
BaseEvent,
CompleteReducerResult,
CreateStoreOptions,
FinishAction,
InitAction,
InitializationActionError,
ReducerResult,
Store,
)
if TYPE_CHECKING:
from collections.abc import Sequence
from redux_pytest.fixtures import StoreSnapshot
# state:
class ToDoItem(Immutable):
id: str
content: str
timestamp: float
class ToDoState(Immutable):
items: Sequence[ToDoItem]
# actions:
class AddTodoItemAction(BaseAction):
content: str
timestamp: float
class RemoveTodoItemAction(BaseAction):
id: str
# events:
class CallApi(BaseEvent):
parameters: object
@pytest.fixture
def store() -> Store:
# reducer:
def reducer(
state: ToDoState | None,
action: BaseAction,
) -> ReducerResult[ToDoState, BaseAction, BaseEvent]:
if state is None:
if isinstance(action, InitAction):
return ToDoState(
items=[
ToDoItem(
id=uuid.uuid4().hex,
content='Initial Item',
timestamp=time.time(),
),
],
)
raise InitializationActionError(action)
if isinstance(action, AddTodoItemAction):
return replace(
state,
items=[
*state.items,
ToDoItem(
id=uuid.uuid4().hex,
content=action.content,
timestamp=action.timestamp,
),
],
)
if isinstance(action, RemoveTodoItemAction):
return CompleteReducerResult(
state=replace(
state,
actions=[item for item in state.items if item.id != action.id],
),
events=[CallApi(parameters={})],
)
return state
return Store(reducer, options=CreateStoreOptions(auto_init=True))
def test_todo(store_snapshot: StoreSnapshot, store: Store) -> None:
# subscription:
dummy_render = logging.getLogger().info
store.subscribe(dummy_render)
# autorun:
@store.autorun(
lambda state: state.items[0].content if len(state.items) > 0 else None,
)
def reaction(_: str | None) -> None:
store_snapshot.take()
_ = reaction
# event listener, note that this will run async in a separate thread, so it can
# include async operations like API calls, etc:
dummy_api_call = logging.getLogger().info
store.subscribe_event(CallApi, lambda event: dummy_api_call(event.parameters))
# dispatch:
store.dispatch(AddTodoItemAction(content='New Item', timestamp=time.time()))
store_snapshot.take()
store.dispatch(FinishAction())