/// <summary>
        /// Creates a new configuration
        /// </summary>
        public JsonApiHttpConfiguration(JsonApiFormatter formatter,
            FallbackDocumentBuilderAttribute fallbackDocumentBuilderAttribute,
            JsonApiExceptionFilterAttribute jsonApiExceptionFilterAttribute)
        {
            if (formatter == null) throw new ArgumentNullException("formatter");
            if (fallbackDocumentBuilderAttribute == null) throw new ArgumentNullException("fallbackDocumentBuilderAttribute");
            if (jsonApiExceptionFilterAttribute == null) throw new ArgumentNullException("jsonApiExceptionFilterAttribute");

            _formatter = formatter;
            _fallbackDocumentBuilderAttribute = fallbackDocumentBuilderAttribute;
            _jsonApiExceptionFilterAttribute = jsonApiExceptionFilterAttribute;
        }
        public void OnActionExecutedAsync_leaves_IResourceCollectionDocument_alone()
        {
            // Arrange
            var mockDocument = new Mock<IResourceCollectionDocument>(MockBehavior.Strict);
            var actionExecutedContext = GetActionExecutedContext(mockDocument.Object);
            var cancellationTokenSource = new CancellationTokenSource();
            var mockFallbackDocumentBuilder = new Mock<IFallbackDocumentBuilder>(MockBehavior.Strict);
            var mockErrorDocumentBuilder = new Mock<IErrorDocumentBuilder>(MockBehavior.Strict);

            // Act
            var attribute = new FallbackDocumentBuilderAttribute(mockFallbackDocumentBuilder.Object, mockErrorDocumentBuilder.Object);
            var task = attribute.OnActionExecutedAsync(actionExecutedContext, cancellationTokenSource.Token);
            task.Wait();

            ((ObjectContent)actionExecutedContext.Response.Content).Value.Should().BeSameAs(mockDocument.Object);
            actionExecutedContext.Response.StatusCode.Should().Be(HttpStatusCode.OK);
        }
        public void OnActionExecutedAsync_does_nothing_if_there_is_an_exception()
        {
            // Arrange
            var objectContent = new object();
            var theException = new Exception("This is an error.");
            var actionExecutedContext = GetActionExecutedContext(objectContent, theException);
            var cancellationTokenSource = new CancellationTokenSource();
            var mockFallbackDocumentBuilder = new Mock<IFallbackDocumentBuilder>(MockBehavior.Strict);
            var mockErrorDocumentBuilder = new Mock<IErrorDocumentBuilder>(MockBehavior.Strict);

            // Act
            var attribute = new FallbackDocumentBuilderAttribute(mockFallbackDocumentBuilder.Object, mockErrorDocumentBuilder.Object);
            var task = attribute.OnActionExecutedAsync(actionExecutedContext, cancellationTokenSource.Token);
            task.Wait();

            var newObjectContent = ((ObjectContent) actionExecutedContext.Response.Content).Value;
            newObjectContent.Should().BeSameAs(objectContent);
            actionExecutedContext.Exception.Should().Be(theException);
        }
        public void OnActionExecutedAsync_leaves_IErrorDocument_alone_but_changes_request_status_to_match_error_status()
        {
            // Arrange
            var mockError = new Mock<IError>(MockBehavior.Strict);
            mockError.Setup(e => e.Status).Returns(HttpStatusCode.Conflict);
            var mockDocument = new Mock<IErrorDocument>(MockBehavior.Strict);
            mockDocument.Setup(p => p.Errors).Returns(new[] {mockError.Object});
            var actionExecutedContext = GetActionExecutedContext(mockDocument.Object);
            var cancellationTokenSource = new CancellationTokenSource();
            var mockFallbackDocumentBuilder = new Mock<IFallbackDocumentBuilder>(MockBehavior.Strict);
            var mockErrorDocumentBuilder = new Mock<IErrorDocumentBuilder>(MockBehavior.Strict);

            // Act
            var attribute = new FallbackDocumentBuilderAttribute(mockFallbackDocumentBuilder.Object, mockErrorDocumentBuilder.Object);
            var task = attribute.OnActionExecutedAsync(actionExecutedContext, cancellationTokenSource.Token);
            task.Wait();

            ((ObjectContent)actionExecutedContext.Response.Content).Value.Should().BeSameAs(mockDocument.Object);
            actionExecutedContext.Response.StatusCode.Should().Be(HttpStatusCode.Conflict);
        }
        public void OnActionExecutedAsync_creates_IErrorDocument_for_HttpError()
        {
            // Arrange
            var httpError = new HttpError("Some error");
            var actionExecutedContext = GetActionExecutedContext(httpError);
            var cancellationTokenSource = new CancellationTokenSource();
            var mockFallbackDocumentBuilder = new Mock<IFallbackDocumentBuilder>(MockBehavior.Strict);

            var mockError = new Mock<IError>(MockBehavior.Strict);
            mockError.Setup(e => e.Status).Returns(HttpStatusCode.OK);
            var mockResult = new Mock<IErrorDocument>(MockBehavior.Strict);
            mockResult.Setup(r => r.Errors).Returns(new[] { mockError.Object });

            var mockErrorDocumentBuilder = new Mock<IErrorDocumentBuilder>(MockBehavior.Strict);
            mockErrorDocumentBuilder.Setup(b => b.BuildFromHttpError(httpError, HttpStatusCode.OK)).Returns(mockResult.Object);
            
            // Act
            var attribute = new FallbackDocumentBuilderAttribute(mockFallbackDocumentBuilder.Object, mockErrorDocumentBuilder.Object);
            var task = attribute.OnActionExecutedAsync(actionExecutedContext, cancellationTokenSource.Token);
            task.Wait();

            // Assert
            ((ObjectContent)actionExecutedContext.Response.Content).Value.Should().BeSameAs(mockResult.Object);
            actionExecutedContext.Response.StatusCode.Should().Be(HttpStatusCode.OK);
        }
        public void OnActionExecutedAsync_delegates_to_fallback_document_builder_for_unknown_types()
        {
            // Arrange
            var resource = new Fruit();
            var actionExecutedContext = GetActionExecutedContext(resource);
            var cancellationTokenSource = new CancellationTokenSource();

            var mockResult = new Mock<IJsonApiDocument>(MockBehavior.Strict);
            var mockFallbackDocumentBuilder = new Mock<IFallbackDocumentBuilder>(MockBehavior.Strict);
            mockFallbackDocumentBuilder.Setup(b => b.BuildDocument(resource, It.IsAny<HttpRequestMessage>(), cancellationTokenSource.Token))
                .Returns(Task.FromResult(mockResult.Object));

            var mockErrorDocumentBuilder = new Mock<IErrorDocumentBuilder>(MockBehavior.Strict);

            // Act
            var attribute = new FallbackDocumentBuilderAttribute(mockFallbackDocumentBuilder.Object, mockErrorDocumentBuilder.Object);
            var task = attribute.OnActionExecutedAsync(actionExecutedContext, cancellationTokenSource.Token);
            task.Wait();

            // Assert
            ((ObjectContent)actionExecutedContext.Response.Content).Value.Should().BeSameAs(mockResult.Object);
            actionExecutedContext.Response.StatusCode.Should().Be(HttpStatusCode.OK);
        }