/// <summary>
        /// 
        /// </summary>
        /// <param name="canExecute"></param>
        /// <param name="executed"></param>
        /// <param name="scheduler"></param>
        /// <returns></returns>
        public static ReactiveCommand Create(Func<object, bool> canExecute, Action<object> executed = null, IScheduler scheduler = null)
        {
            var ret = new ReactiveCommand(canExecute, scheduler);
            if (executed != null) {
                ret.Subscribe(executed);
            }

            return ret;
        }
        public void ObservableCanExecuteShouldShowUpInCommand()
        {
            var input = new[] {true, false, false, true, false, true};
            var result = (new TestScheduler()).With(sched => {
                var can_execute = new Subject<bool>();
                var fixture = new ReactiveCommand(can_execute, null);
                var changes_as_observable = new ListObservable<bool>(fixture.CanExecuteObservable);

                int change_event_count = 0;
                fixture.CanExecuteChanged += (o, e) => { change_event_count++; };
                input.Run(x => {
                    can_execute.OnNext(x);
                    sched.Run();
                    Assert.AreEqual(x, fixture.CanExecute(null));
                });

                // N.B. We check against '5' instead of 6 because we're supposed to
                // suppress changes that aren't actually changes i.e. false => false
                can_execute.OnCompleted();
                sched.Run();
                Assert.AreEqual(5, change_event_count);

                return changes_as_observable;
            });

            input.AssertAreEqual(result.ToList());
        }
        public void MultipleSubscribesShouldntResultInMultipleNotifications()
        {
            var input = new[] { 1, 2, 1, 2 };
            var sched = new TestScheduler();
            var fixture = new ReactiveCommand(null, sched);

            var odd_list = new List<int>();
            var even_list = new List<int>();
            fixture.Where(x => ((int)x) % 2 != 0).Subscribe(x => odd_list.Add((int)x));
            fixture.Where(x => ((int)x) % 2 == 0).Subscribe(x => even_list.Add((int)x));

            input.Run(x => fixture.Execute(x));
            sched.RunToMilliseconds(1000);

            new[]{1,1}.AssertAreEqual(odd_list);
            new[]{2,2}.AssertAreEqual(even_list);
        }
        public void CompletelyDefaultReactiveCommandShouldFire()
        {
            var sched = new TestScheduler();
            var fixture = new ReactiveCommand(null, sched);
            Assert.IsTrue(fixture.CanExecute(null));

            string result = null;
            fixture.Subscribe(x => result = x as string);

            fixture.Execute("Test");
            sched.Run();
            Assert.AreEqual("Test", result);
            fixture.Execute("Test2");
            sched.Run();
            Assert.AreEqual("Test2", result);
        }
        public void ObservableExecuteFuncShouldBeObservableAndAct()
        {
            var executed_params = new List<object>();
            var fixture = new ReactiveCommand(x => executed_params.Add(x));

            var observed_params = new ReplaySubject<object>();
            fixture.Subscribe(observed_params.OnNext, observed_params.OnError, observed_params.OnCompleted);

            var range = Enumerable.Range(0, 5);
            range.Run(x => fixture.Execute(x));

            range.Zip(executed_params, (expected, actual) => new { expected, actual })
                 .Run(x => Assert.AreEqual(x.expected, x.actual));

            range.ToObservable()
                .Zip(observed_params, (expected, actual) => new { expected, actual })
                .Do(Console.WriteLine)
                .Subscribe(x => Assert.AreEqual(x.expected, x.actual));
        }
        public void ObservableCanExecuteShouldShowUpInCommand()
        {
            var can_execute = new Subject<bool>();
            var fixture = new ReactiveCommand(can_execute, null);
            var changes_as_observable = new ListObservable<bool>(fixture.CanExecuteObservable);

            var input = new[] { true, false, false, true, false, true };

            int change_event_count = 0;
            fixture.CanExecuteChanged += (o, e) => { change_event_count++; };
            input.Run(x => {
                can_execute.OnNext(x);
                Assert.AreEqual(x, fixture.CanExecute(null));
            });

            // N.B. We check against '5' instead of 6 because we're supposed to
            // suppress changes that aren't actually changes i.e. false => false
            can_execute.OnCompleted();
            Assert.AreEqual(5, change_event_count);

            input.Zip(changes_as_observable.ToList(), (expected, actual) => new { expected, actual })
                 .Do(Console.WriteLine)
                 .Run(x => Assert.AreEqual(x.expected, x.actual));
        }
        public void ObservableCanExecuteFuncShouldShowUpInCommand()
        {
            int counter = 1;
            var fixture = new ReactiveCommand(_ => (++counter % 2 == 0), null);
            var changes_as_observable = new ListObservable<bool>(fixture.CanExecuteObservable);

            int change_event_count = 0;
            fixture.CanExecuteChanged += (o, e) => { change_event_count++; };
            Enumerable.Range(0, 6).Run(x => {
                Assert.AreEqual(x % 2 == 0, fixture.CanExecute(null));
            });

            Assert.AreEqual(6, change_event_count);
        }
        public void MultipleSubscribesShouldntResultInMultipleNotifications()
        {
            var input = new[] { 1, 2, 1, 2 };
            var fixture = new ReactiveCommand(null, null);

            var odd_list = new List<int>();
            var even_list = new List<int>();
            fixture.Where(x => ((int)x) % 2 != 0).Subscribe(x => odd_list.Add((int)x));
            fixture.Where(x => ((int)x) % 2 == 0).Subscribe(x => even_list.Add((int)x));

            input.Run(x => fixture.Execute(x));

            new[]{1,1}.Zip(odd_list, (expected, actual) => new { expected, actual })
                .Run(x => Assert.AreEqual(x.expected, x.actual));

            new[]{2,2}.Zip(even_list, (expected, actual) => new { expected, actual })
                .Run(x => Assert.AreEqual(x.expected, x.actual));
        }
        public void ActionExceptionShouldntPermabreakCommands()
        {
            var input = new[] {1,2,3,4};
            var fixture = new ReactiveCommand(x => {
                if (((int)x) == 2)
                    throw new Exception("Die!");
            });

            var exception_list = new List<Exception>();
            var out_list = new List<int>();

            fixture.Subscribe(x => out_list.Add((int)x), ex => exception_list.Add(ex));
            bool we_threw = false;
            foreach (int i in input) {
                try {
                    fixture.Execute(i);
                } catch {
                    we_threw = true;
                    if (i != 2)
                        throw;
                }
            }

            Assert.IsTrue(we_threw);
            input.Zip(out_list, (expected, actual) => new { expected, actual })
                 .Run(x => Assert.AreEqual(x.expected, x.actual));

            // Now, make sure that the command isn't broken
            fixture.Execute(5);
            Console.WriteLine(String.Join(",", out_list));
            Assert.AreEqual(5, out_list.Count);
        }