public void You_cannot_log_a_failure_without_a_started_operation()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);

                Assert.Throws <InvalidOperationException>(() => sut.OperationFailed(new FakeOperation(), new Exception()));
            }
        }
        public void You_cannot_log_a_failure_when_the_last_operation_has_been_logged_as_finished()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);
                sut.OperationStarted(new FakeOperation());
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);

                Assert.Throws <InvalidOperationException>(() => sut.OperationFailed(new FakeOperation(), new Exception()));
            }
        }
        public void Failures_are_logged_nested_between_braces()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);

                sut.OperationStarted(new FakeOperation());
                sut.OperationFailed(new FakeOperation(), new InvalidOperationException("MESSAGE"));
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);

                Assert.Equal($"FakeOperation {{{NL}  Error [InvalidOperationException]: MESSAGE{NL}}} [duration: 0ms]", sw.ToString());
            }
        }
        public void Failures_are_correctly_indented_after_a_sibling_operation()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);

                sut.OperationStarted(new FakeOperation());
                sut.OperationStarted(new FakeOperation());
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);
                sut.OperationFailed(new FakeOperation(), new InvalidOperationException("MESSAGE"));
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);

                Assert.Equal($"FakeOperation {{{NL}  FakeOperation [duration: 0ms]{NL}{NL}  Error [InvalidOperationException]: MESSAGE{NL}}} [duration: 0ms]", sw.ToString());
            }
        }
        public void You_cannot_log_a_failure_when_the_last_operation_has_been_logged_as_finished()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);
                sut.OperationStarted(new FakeOperation());
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);

                Assert.Throws<InvalidOperationException>(() => sut.OperationFailed(new FakeOperation(), new Exception()));
            }
        }
        public void You_cannot_log_a_failure_without_a_started_operation()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);

                Assert.Throws<InvalidOperationException>(() => sut.OperationFailed(new FakeOperation(), new Exception()));
            }
        }
        public void Failures_are_correctly_indented_after_a_sibling_operation()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);

                sut.OperationStarted(new FakeOperation());
                sut.OperationStarted(new FakeOperation());
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);
                sut.OperationFailed(new FakeOperation(), new InvalidOperationException("MESSAGE"));
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);

                Assert.Equal($"FakeOperation {{{NL}  FakeOperation [duration: 0ms]{NL}{NL}  Error [InvalidOperationException]: MESSAGE{NL}}} [duration: 0ms]", sw.ToString());
            }
        }
        public void Failures_are_logged_nested_between_braces()
        {
            using (var sw = new StringWriter())
            {
                var sut = new TextWriterWorkflowLogger(sw);

                sut.OperationStarted(new FakeOperation());
                sut.OperationFailed(new FakeOperation(), new InvalidOperationException("MESSAGE"));
                sut.OperationFinished(new FakeOperation(), TimeSpan.Zero);

                Assert.Equal($"FakeOperation {{{NL}  Error [InvalidOperationException]: MESSAGE{NL}}} [duration: 0ms]", sw.ToString());
            }
        }