Пример #1
0
        public void Recovers_From_Error_Within_Reducer()
        {
            var store = Redux.CreateStore(Helpers.ThrowErrorReducer, 0);

            Assert.Throws <Exception>(() => store.Dispatch(new Helpers.ErrorAction()));
            store.Dispatch(new Helpers.UnknownAction());
        }
Пример #2
0
        public void Delays_Unsubscribe_Unitl_The_End_Of_Current_Dispatch()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            var    unsubscribeHandles = new List <Action>();
            Action doUnsubscribeAll   = () => {
                foreach (var unsubscribeHandle in unsubscribeHandles)
                {
                    unsubscribeHandle();
                }
            };

            var listener1 = new Mock <Action>();
            var listener2 = new Mock <Action>();
            var listener3 = new Mock <Action>();

            unsubscribeHandles.Add(store.Subscribe(() => listener1.Object()));
            unsubscribeHandles.Add(store.Subscribe(() => {
                listener2.Object();
                doUnsubscribeAll();
            }));
            unsubscribeHandles.Add(store.Subscribe(() => listener3.Object()));

            store.Dispatch(new Helpers.UnknownAction());
            listener1.Verify(x => x(), Times.Exactly(1));
            listener2.Verify(x => x(), Times.Exactly(1));
            listener3.Verify(x => x(), Times.Exactly(1));

            store.Dispatch(new Helpers.UnknownAction());
            listener1.Verify(x => x(), Times.Exactly(1));
            listener2.Verify(x => x(), Times.Exactly(1));
            listener3.Verify(x => x(), Times.Exactly(1));
        }
Пример #3
0
        public void Applies_The_Reducer_To_Previous_State()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            Assert.Equal(new Helpers.Todo[] { }, store.GetState());

            store.Dispatch(new Helpers.UnknownAction());
            Assert.Equal(new Helpers.Todo[] { }, store.GetState());

            store.Dispatch(new Helpers.AddTodoAction("Hello"));
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                }
            }, store.GetState());

            store.Dispatch(new Helpers.AddTodoAction("World"));
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Helpers.Todo {
                    Id      = 2,
                    Message = "World"
                }
            }, store.GetState());
        }
Пример #4
0
        public static void Main()
        {
            var initialState = new TodoAppState
            {
                DescriptionInput = "",
                Visibility       = TodoVisibility.All,
                Todos            = new Todo[]
                {
                    new Todo
                    {
                        Id          = 0,
                        Description = "Learn React + Redux in C#",
                        IsCompleted = true
                    },
                    new Todo
                    {
                        Id          = 1,
                        Description = "Build an awesome app with them",
                        IsCompleted = false
                    }
                }
            };

            var store = Redux.CreateStore(Todos.Reducer(initialState));

            React.Render(Components.TodoItemList(store), Document.GetElementById("root"));
        }
Пример #5
0
        public void Does_Not_Allow_Unsubscribe_From_Within_Reducer()
        {
            var store       = Redux.CreateStore(BoundActionInMiddleReducer, 0);
            var unsubscribe = store.Subscribe(() => { });

            Assert.Throws <Exception>(() => {
                store.Dispatch(new ActionWithBoundFn(unsubscribe));
            });
        }
Пример #6
0
        public void Does_Not_Allow_GetState_From_Within_Reducer()
        {
            var store = Redux.CreateStore(BoundActionInMiddleReducer, 0);

            Assert.Throws <Exception>(() => {
                store.Dispatch(new ActionWithBoundFn(() => {
                    store.GetState();
                }));
            });
        }
Пример #7
0
        public void Does_Not_Allow_Dispatch_From_Within_Reducer()
        {
            var store = Redux.CreateStore(Helpers.DispatchInMiddleReducer, 0);

            Assert.Throws <Exception>(() => {
                store.Dispatch(new Helpers.ActionWithBoundFn(() => {
                    store.Dispatch(new Helpers.UnknownAction());
                }));
            });
        }
Пример #8
0
        public async void Is_Thread_Safe()
        {
            var store = Redux.CreateStore((state, action) => state + 1, 0);

            await Task.WhenAll(
                Enumerable
                .Range(0, 1000)
                .Select(x => Task.Factory.StartNew(() => store.Dispatch(new UnknownAction()))));

            Assert.Equal(1001, store.GetState());
        }
Пример #9
0
        public void Passes_Initial_Action_And_Initial_State()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, new[] {
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                }
            });

            Assert.Equal(1, store.GetState().Length);
            Assert.Equal(1, store.GetState().First().Id);
            Assert.Equal("Hello", store.GetState().First().Message);
        }
Пример #10
0
        public void Provides_Up_To_Date_State_When_A_Subscriber_Is_Notified()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            store.Subscribe(() => {
                Assert.Equal(new[] {
                    new Helpers.Todo {
                        Id      = 1,
                        Message = "Hello"
                    }
                }, store.GetState());
            });
            store.Dispatch(new Helpers.AddTodoAction("Hello"));
        }
Пример #11
0
        public void Supports_Multiple_Subscriptions()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            var listenerA = new Mock <Action>();
            var listenerB = new Mock <Action>();

            var unsubscribeA = store.Subscribe(listenerA.Object);

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(1));
            listenerB.Verify(x => x(), Times.Exactly(0));

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(2));
            listenerB.Verify(x => x(), Times.Exactly(0));

            var unsubscribeB = store.Subscribe(listenerB.Object);

            listenerA.Verify(x => x(), Times.Exactly(2));
            listenerB.Verify(x => x(), Times.Exactly(0));

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(3));
            listenerB.Verify(x => x(), Times.Exactly(1));

            unsubscribeA();
            listenerA.Verify(x => x(), Times.Exactly(3));
            listenerB.Verify(x => x(), Times.Exactly(1));

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(3));
            listenerB.Verify(x => x(), Times.Exactly(2));

            unsubscribeB();
            listenerA.Verify(x => x(), Times.Exactly(3));
            listenerB.Verify(x => x(), Times.Exactly(2));

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(3));
            listenerB.Verify(x => x(), Times.Exactly(2));

            store.Subscribe(listenerA.Object);
            listenerA.Verify(x => x(), Times.Exactly(3));
            listenerB.Verify(x => x(), Times.Exactly(2));

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(4));
            listenerB.Verify(x => x(), Times.Exactly(2));
        }
Пример #12
0
        public void Only_Removes_Listener_Once_When_Unsubscribe_Is_Called()
        {
            var store     = Redux.CreateStore(Helpers.TodosReducer, null);
            var listenerA = new Mock <Action>();
            var listenerB = new Mock <Action>();

            var unsubscribeA = store.Subscribe(listenerA.Object);

            store.Subscribe(listenerB.Object);

            unsubscribeA();
            unsubscribeA();

            store.Dispatch(new Helpers.UnknownAction());
            listenerA.Verify(x => x(), Times.Exactly(0));
            listenerB.Verify(x => x(), Times.Exactly(1));
        }
Пример #13
0
        public void Uses_The_Last_Snapshot_Of_Subscribers_During_Nested_Dispatch()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            var listener1 = new Mock <Action>();
            var listener2 = new Mock <Action>();
            var listener3 = new Mock <Action>();
            var listener4 = new Mock <Action>();

            Action unsubscribe4 = null;
            Action unsubscribe1 = null;

            unsubscribe1 = store.Subscribe(() => {
                listener1.Object();

                listener1.Verify(x => x(), Times.Exactly(1));
                listener2.Verify(x => x(), Times.Exactly(0));
                listener3.Verify(x => x(), Times.Exactly(0));
                listener4.Verify(x => x(), Times.Exactly(0));

                unsubscribe1?.Invoke();
                unsubscribe4 = store.Subscribe(listener4.Object);
                store.Dispatch(new Helpers.UnknownAction());

                listener1.Verify(x => x(), Times.Exactly(1));
                listener2.Verify(x => x(), Times.Exactly(1));
                listener3.Verify(x => x(), Times.Exactly(1));
                listener4.Verify(x => x(), Times.Exactly(1));
            });
            store.Subscribe(listener2.Object);
            store.Subscribe(listener3.Object);

            store.Dispatch(new Helpers.UnknownAction());
            listener1.Verify(x => x(), Times.Exactly(1));
            listener2.Verify(x => x(), Times.Exactly(2));
            listener3.Verify(x => x(), Times.Exactly(2));
            listener4.Verify(x => x(), Times.Exactly(1));

            unsubscribe4?.Invoke();
            store.Dispatch(new Helpers.UnknownAction());
            listener1.Verify(x => x(), Times.Exactly(1));
            listener2.Verify(x => x(), Times.Exactly(3));
            listener3.Verify(x => x(), Times.Exactly(3));
            listener4.Verify(x => x(), Times.Exactly(1));
        }
Пример #14
0
        public void Supports_Removing_A_Subscription_Within_A_Subscription()
        {
            var store     = Redux.CreateStore(Helpers.TodosReducer, null);
            var listenerA = new Mock <Action>();
            var listenerB = new Mock <Action>();
            var listenerC = new Mock <Action>();

            store.Subscribe(listenerA.Object);
            var unSubB = store.Subscribe(listenerB.Object);

            store.Subscribe(() => {
                unSubB();
            });
            store.Subscribe(listenerC.Object);

            store.Dispatch(new Helpers.UnknownAction());
            store.Dispatch(new Helpers.UnknownAction());

            listenerA.Verify(x => x(), Times.Exactly(2));
            listenerB.Verify(x => x(), Times.Exactly(1));
            listenerC.Verify(x => x(), Times.Exactly(2));
        }
Пример #15
0
        public void Applies_The_Reducer_To_The_Initial_State()
        {
            var store = Redux.CreateStore(TodosReducer, new[] {
                new Todo {
                    Id      = 1,
                    Message = "Hello"
                }
            });

            Assert.Equal(new[] {
                new Todo {
                    Id      = 1,
                    Message = "Hello"
                }
            }, store.GetState());

            store.Dispatch(new UnknownAction());
            Assert.Equal(new[] {
                new Todo {
                    Id      = 1,
                    Message = "Hello"
                }
            }, store.GetState());

            store.Dispatch(new AddTodoAction("World"));
            Assert.Equal(new[] {
                new Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Todo {
                    Id      = 2,
                    Message = "World"
                }
            }, store.GetState());
        }
Пример #16
0
        public void Dispatches_Once_On_Store_Creation()
        {
            var store = Redux.CreateStore((state, action) => state + 1, 0);

            Assert.Equal(1, store.GetState());
        }
Пример #17
0
        public void Preservers_The_State_When_Replacing_A_Reducer()
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            store.Dispatch(new Helpers.AddTodoAction("Hello"));
            store.Dispatch(new Helpers.AddTodoAction("World"));
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Helpers.Todo {
                    Id      = 2,
                    Message = "World"
                }
            }, store.GetState());

            store.ReplaceReducer(Helpers.TodosReducerReverse);
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Helpers.Todo {
                    Id      = 2,
                    Message = "World"
                }
            }, store.GetState());

            store.Dispatch(new Helpers.AddTodoAction("Perhaps"));
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 3,
                    Message = "Perhaps"
                },
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Helpers.Todo {
                    Id      = 2,
                    Message = "World"
                }
            }, store.GetState());

            store.ReplaceReducer(Helpers.TodosReducer);
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 3,
                    Message = "Perhaps"
                },
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Helpers.Todo {
                    Id      = 2,
                    Message = "World"
                }
            }, store.GetState());

            store.Dispatch(new Helpers.AddTodoAction("Surely"));
            Assert.Equal(new[] {
                new Helpers.Todo {
                    Id      = 3,
                    Message = "Perhaps"
                },
                new Helpers.Todo {
                    Id      = 1,
                    Message = "Hello"
                },
                new Helpers.Todo {
                    Id      = 2,
                    Message = "World"
                },
                new Helpers.Todo {
                    Id      = 4,
                    Message = "Surely"
                }
            }, store.GetState());
        }
Пример #18
0
        public static void Main()
        {
            var initialState = new TodoAppState
            {
                DescriptionInput = "",
                Visibility       = TodoVisibility.All,
                Todos            = new Todo[]
                {
                    new Todo
                    {
                        Id          = 0,
                        Description = "Have fun with Ractive and Redux",
                        IsCompleted = true
                    },
                    new Todo
                    {
                        Id          = 1,
                        Description = "Make an awesome todo app",
                        IsCompleted = false
                    }
                }
            };

            var store = Redux.CreateStore(Todos.Reducer(initialState));

            Action <TodoVisibility> show = filter => store.Dispatch(new SetVisibility {
                Visibility = filter
            });

            // events that are attached to button clicks on the template
            var eventHandlers = new EventHandlers
            {
                ToggleTodo = id => store.Dispatch(new ToggleTodoCompleted {
                    Id = id
                }),
                DeleteTodo = id => store.Dispatch(new DeleteTodo {
                    Id = id
                }),
                AddTodo        = () => store.Dispatch(new AddTodo {
                }),
                ShowAll        = () => show(TodoVisibility.All),
                ShowComplete   = () => show(TodoVisibility.Completed),
                ShowIncomplete = () => show(TodoVisibility.YetToComplete)
            };

            // functions that can be called in the template to compute smth directly
            var functions = new TemplateFunctions
            {
                Filter = (visibility, todos) =>
                {
                    if (visibility == TodoVisibility.Completed)
                    {
                        return(todos.Where(todo => todo.IsCompleted).ToArray());
                    }
                    if (visibility == TodoVisibility.YetToComplete)
                    {
                        return(todos.Where(todo => !todo.IsCompleted).ToArray());
                    }
                    return(todos);
                }
            };


            var ractive = new Ractive(new RactiveOptions
            {
                Element  = "#app",
                Template = "#app-template",
                Data     = JS.Merge(initialState, functions)
            });

            // although two-way binding is available in Ractive,
            // I will use a vanilla handler to make data-flow one directional
            ractive.Find("#txtAddTodo").OnTextChanged(input =>
            {
                store.Dispatch(new UpdateDescriptionInput {
                    Description = input
                });
            });

            // attach the events
            ractive.On(eventHandlers);

            store.Subscribe(() =>
            {
                var state = store.GetState();
                ractive.Set(JS.Merge(state, functions));
            });
        }
Пример #19
0
        public void Does_Not_Allow_Value_TypeActions(Object action)
        {
            var store = Redux.CreateStore(Helpers.TodosReducer, null);

            Assert.Throws <Exception>(() => store.Dispatch(action));
        }