Combines multiple IUndoCommands into a single atomic transaction.
Inheritance: SimpleCommand
        public void TestWrongOrder()
        {
            var command = new CompositeCommand();

            command.Invoking(x => x.Undo()).ShouldThrow <InvalidOperationException>(because: "Should not allow Undo before Execute");

            command.Execute();
            command.Invoking(x => x.Execute()).ShouldThrow <InvalidOperationException>(because: "Should not allow two Executes without an Undo in between");
        }
        public void TestExecuteRollback()
        {
            var executeCalls = new List<int>(3);
            var undoCalls = new List<int>(3);
            var command = new CompositeCommand(
                new MockCommand(() => executeCalls.Add(0), () => undoCalls.Add(0)),
                new MockCommand(() => executeCalls.Add(1), () => undoCalls.Add(1)),
                new MockCommand(() => { throw new OperationCanceledException(); }, () => undoCalls.Add(2)));

            Assert.Throws<OperationCanceledException>(command.Execute, "Exceptions should be passed through after rollback");
            executeCalls.Should().Equal(new[] {0, 1}, because: "After an exception the rest of the commands should not be executed");
            undoCalls.Should().Equal(new[] {1, 0}, because: "After an exception all successful executions should be undone");
        }
        public void TestExecuteUndo()
        {
            var executeCalls = new List<int>(3);
            var undoCalls = new List<int>(3);
            var command = new CompositeCommand(
                new MockCommand(() => executeCalls.Add(0), () => undoCalls.Add(0)),
                new MockCommand(() => executeCalls.Add(1), () => undoCalls.Add(1)),
                new MockCommand(() => executeCalls.Add(2), () => undoCalls.Add(2)));

            command.Execute();
            executeCalls.Should().Equal(new[] {0, 1, 2}, because: "Child commands should be executed in ascending order");

            command.Undo();
            undoCalls.Should().Equal(new[] {2, 1, 0}, because: "Child commands should be undone in descending order");
        }
        public void TestExecuteUndo()
        {
            var executeCalls = new List <int>(3);
            var undoCalls    = new List <int>(3);
            var command      = new CompositeCommand(
                new MockCommand(() => executeCalls.Add(0), () => undoCalls.Add(0)),
                new MockCommand(() => executeCalls.Add(1), () => undoCalls.Add(1)),
                new MockCommand(() => executeCalls.Add(2), () => undoCalls.Add(2)));

            command.Execute();
            executeCalls.Should().Equal(new[] { 0, 1, 2 }, because: "Child commands should be executed in ascending order");

            command.Undo();
            undoCalls.Should().Equal(new[] { 2, 1, 0 }, because: "Child commands should be undone in descending order");
        }
        public void TestUndoRollback()
        {
            var executeCalls = new List<int>(3);
            var undoCalls = new List<int>(3);
            var command = new CompositeCommand(
                new MockCommand(() => executeCalls.Add(0), () => { throw new OperationCanceledException(); }),
                new MockCommand(() => executeCalls.Add(1), () => undoCalls.Add(1)),
                new MockCommand(() => executeCalls.Add(2), () => undoCalls.Add(2)));

            command.Execute();
            executeCalls.Should().Equal(new[] {0, 1, 2}, because: "Child commands should be executed in ascending order");

            executeCalls.Clear();
            Assert.Throws<OperationCanceledException>(command.Undo, "Exceptions should be passed through after rollback");
            undoCalls.Should().Equal(new[] {2, 1}, because: "After an exception the rest of the undoes should not be performed");
            executeCalls.Should().Equal(new[] {1, 2}, because: "After an exception all successful undoes should be re-executed");
        }
        public void TestWrongOrder()
        {
            var command = new CompositeCommand();
            Assert.Throws<InvalidOperationException>(command.Undo, "Should not allow Undo before Execute");

            command.Execute();
            Assert.Throws<InvalidOperationException>(command.Execute, "Should not allow two Executes without an Undo in between");
        }