public async Task MemberPathIsTransformedForMultipleObjects() { var firstParameterName = "one"; var firstParameterValue = new object(); var secondParameterName = "two"; var secondParameterValue = new OrderFulfillmentMessage(); var mockValidator = new Mock <IValidator>(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var mockDependencyScope = new Mock <IDependencyScope>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = "generic" }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); var messageValidator = new ValidateMessageAttribute(); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); mockDependencyScope.Setup(scope => scope.GetService(It.IsAny <Type>())) .Returns(mockValidator.Object) .Verifiable("Tthe validator should have been requested."); mockValidator.Setup(validator => validator.Validate(It.Is <object>(param => param == firstParameterValue))) .Returns(new [] { new Error(ErrorCode.LengthIsInvalid, "someThing.Path", "Dummy description") }) .Verifiable("The validator should have been used to validate the parameter."); mockValidator.Setup(validator => validator.Validate(It.Is <object>(param => param == secondParameterValue))) .Returns(new [] { new Error(ErrorCode.LengthIsInvalid, "order.OrderId", "Dummy description") }) .Verifiable("The validator should have been used to validate the parameter."); actionContext.ActionArguments.Add(firstParameterName, firstParameterValue); actionContext.ActionArguments.Add(secondParameterName, secondParameterValue); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); request.Properties.Add(HttpPropertyKeys.DependencyScope, mockDependencyScope.Object); await messageValidator.OnActionExecutingAsync(actionContext, new CancellationToken()); actionContext.Response.Should().NotBeNull("because an invalid response should contain response"); actionContext.Response.StatusCode.Should().Be(HttpStatusCode.BadRequest, "because a validation failure is a Bad Request"); var errorSet = await actionContext.Response.Content.ReadAsAsync <ErrorSet>(); errorSet.Should().NotBeNull("because an error set should be present for a failed validation"); errorSet.Errors.Count().Should().Be(2, "because two failures were returned by validation"); errorSet.Errors.Count(error => error.MemberPath.StartsWith($"{ firstParameterName }::")).Should().Be(1, "because a single error should have been mapped to the firstParameter"); errorSet.Errors.Count(error => error.MemberPath.StartsWith($"{ secondParameterName }::")).Should().Be(1, "because a single error should have been mapped to the secondParameter"); }
public async Task FulfillOrderWebHookWithNonPriviledgedUserLogsWhenSupplyingTestData() { var mockLogger = new Mock <ILogger>(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); var unpriviledgedIdentity = new ClaimsIdentity(new Claim[] { new Claim(CustomClaimTypes.IdentityType, "UnitTest") }); mockLogger.Setup(log => log.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); actionContext.RequestContext.Principal = new ClaimsPrincipal(unpriviledgedIdentity); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), Mock.Of <ICommandPublisher <ProcessOrder> >(), Mock.Of <IEventPublisher <EventBase> >(), mockLogger.Object, new OrderSubmissionControllerConfiguration()) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem>(), Emulation = new DependencyEmulation() }; var partner = "SQUIRE"; var actionResult = await controller.FulfillOrderWebHook(partner, order); var result = await actionResult.ExecuteAsync(CancellationToken.None); mockLogger.Verify(logger => logger.Warning(It.IsAny <string>(), It.Is <HttpStatusCode>(code => code == HttpStatusCode.Forbidden), It.Is <string>(name => name == nameof(OrderSubmissionController)), It.Is <string>(method => method == nameof(OrderSubmissionController.FulfillOrderWebHook)), It.Is <string>(partnerName => partnerName == partner), It.IsAny <HttpRequestHeaders>()), Times.Once, "The failure should be logged"); }
public async Task FulfillOrderWebHookWithFailedCommandFails() { var mockLogger = new Mock <ILogger>(); var mockCommandPublisher = new Mock <ICommandPublisher <ProcessOrder> >(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); mockLogger.Setup(log => log.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); mockCommandPublisher.Setup(publisher => publisher.TryPublishAsync(It.IsAny <ProcessOrder>(), It.IsAny <Instant?>())) .ReturnsAsync(false); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), mockCommandPublisher.Object, Mock.Of <IEventPublisher <EventBase> >(), mockLogger.Object, new OrderSubmissionControllerConfiguration { ServiceUnavailableeRetryAfterInSeconds = 5 }) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem>() }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); result.StatusCode.Should().Be(HttpStatusCode.ServiceUnavailable, "because the request should have been rejected"); result.Headers.RetryAfter.Should().NotBeNull("because a RETRY-AFTER header should be specified for an Service Unavailable result"); }
public async Task FulfillOrderWebHookPublishesTheCommandToTiriggerProcessingForAnAcceptedOrder() { var mockLogger = new Mock <ILogger>(); var mockCommandPublisher = new Mock <ICommandPublisher <ProcessOrder> >(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); mockLogger.Setup(log => log.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), mockCommandPublisher.Object, Mock.Of <IEventPublisher <EventBase> >(), mockLogger.Object, new OrderSubmissionControllerConfiguration { OrderAcceptedRetryAfterInSeconds = 5 }) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem>() }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); mockCommandPublisher.Verify(publisher => publisher.TryPublishAsync(It.Is <ProcessOrder>(command => command.OrderId == order.OrderRequestHeader.OrderId), It.Is <Instant?>(time => time == null)), Times.Once, "An accepted order should emit an Order Received event"); }
public async Task FulfillOrderWebHookAcceptsAnOrder() { var mockCommandPublisher = new Mock <ICommandPublisher <ProcessOrder> >(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); mockCommandPublisher.Setup(publisher => publisher.TryPublishAsync(It.IsAny <ProcessOrder>(), It.IsAny <Instant?>())) .ReturnsAsync(true); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), mockCommandPublisher.Object, Mock.Of <IEventPublisher <EventBase> >(), Mock.Of <ILogger>(), new OrderSubmissionControllerConfiguration { OrderAcceptedRetryAfterInSeconds = 5 }) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem>() }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); result.StatusCode.Should().Be(HttpStatusCode.Accepted, "because the request was valid"); result.Headers.RetryAfter.Should().NotBeNull("because a RETRY-AFTER header should be specified for an Accepted result"); result.TryGetContentValue <OrderFulfillmentAccepted>(out var response).Should().BeTrue("because the response should have been set"); response.FulfillerData.OrderId.Should().Be(order.OrderRequestHeader.OrderId, "because the correct order should have been acknoledged"); }
public async Task FulfillOrderWebHookWithAPriviledgedUserAcceptsTestData() { var mockCommandPublisher = new Mock <ICommandPublisher <ProcessOrder> >(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); var priviledgedIdentity = new ClaimsIdentity(new Claim[] { new Claim(CustomClaimTypes.MayAccessPriviledgedOperations, "true") }); mockCommandPublisher.Setup(publisher => publisher.TryPublishAsync(It.IsAny <ProcessOrder>(), It.IsAny <Instant?>())) .ReturnsAsync(true); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); actionContext.RequestContext.Principal = new ClaimsPrincipal(priviledgedIdentity); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), mockCommandPublisher.Object, Mock.Of <IEventPublisher <EventBase> >(), Mock.Of <ILogger>(), new OrderSubmissionControllerConfiguration()) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem>(), Emulation = new DependencyEmulation() }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); result.StatusCode.Should().Be(HttpStatusCode.Accepted, "because the request was valid"); }
public async Task FulfillOrderWebHookWithNonPriviledgedUserIsRejectedWhenSupplyingTestData() { var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); var unpriviledgedIdentity = new ClaimsIdentity(new Claim[] { new Claim(CustomClaimTypes.IdentityType, "UnitTest") }); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); actionContext.RequestContext.Principal = new ClaimsPrincipal(unpriviledgedIdentity); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), Mock.Of <ICommandPublisher <ProcessOrder> >(), Mock.Of <IEventPublisher <EventBase> >(), Mock.Of <ILogger>(), new OrderSubmissionControllerConfiguration()) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem>(), Emulation = new DependencyEmulation() }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); result.StatusCode.Should().Be(HttpStatusCode.Forbidden, "because the request should have been rejected"); var errorSet = await result.Content.ReadAsAsync <ErrorSet>(); errorSet.Should().BeNull("because no errors should be returned when the caller is unpriviledged"); }
public async Task RequestHeaderIsRequired() { var currentInstant = Instant.FromUtc(2017, 08, 17, 12, 0, 0); var fakeClock = new FakeClock(currentInstant); var headerValidator = new OrderHeaderValidator(fakeClock) as IMessageValidator <OrderHeader>; var itemValidator = new itemItemValidator() as IMessageValidator <ItemAsset>; var itemOutValidator = new ItemOutValidator(itemValidator) as IMessageValidator <LineItem>; var validator = new OrderFulfillmentMessageValidator(headerValidator, itemOutValidator); var target = new OrderFulfillmentMessage { OrderRequestHeader = null, LineItems = new List <LineItem>() }; var result = await validator.ValidateAsync(target); result.Should().NotBeNull("because a validation result should have been returned"); result.Should().ContainSingle(error => ((error.MemberPath == nameof(OrderFulfillmentMessage.OrderRequestHeader)) && (error.Code == ErrorCode.ValueIsRequired.ToString())), "because the order header was not provided"); }
public async Task RequestHeaderIsValidated() { var currentInstant = Instant.FromUtc(2017, 08, 17, 12, 0, 0); var fakeClock = new FakeClock(currentInstant); var headerValidator = new OrderHeaderValidator(fakeClock) as IMessageValidator <OrderHeader>; var itemValidator = new itemItemValidator() as IMessageValidator <ItemAsset>; var itemOutValidator = new ItemOutValidator(itemValidator) as IMessageValidator <LineItem>; var validator = new OrderFulfillmentMessageValidator(headerValidator, itemOutValidator); var header = new OrderHeader { OrderId = null, OrderDate = currentInstant.ToDateTimeUtc() }; var target = new OrderFulfillmentMessage { OrderRequestHeader = header, LineItems = new List <LineItem>() }; var result = await validator.ValidateAsync(target); result.Should().NotBeNull("because a validation result should have been returned"); result.Should().ContainSingle(error => (error.MemberPath == $"{ nameof(OrderFulfillmentMessage.OrderRequestHeader) }.{ nameof(OrderHeader.OrderId) }"), "because the order id was not provided in the header"); }
public async Task EmptyItemOutIsValid() { var currentInstant = Instant.FromUtc(2017, 08, 17, 12, 0, 0); var fakeClock = new FakeClock(currentInstant); var headerValidator = new OrderHeaderValidator(fakeClock) as IMessageValidator <OrderHeader>; var itemValidator = new itemItemValidator() as IMessageValidator <ItemAsset>; var itemOutValidator = new ItemOutValidator(itemValidator) as IMessageValidator <LineItem>; var validator = new OrderFulfillmentMessageValidator(headerValidator, itemOutValidator); var header = new OrderHeader { OrderId = "ABC123", OrderDate = currentInstant.ToDateTimeUtc() }; var target = new OrderFulfillmentMessage { OrderRequestHeader = header, LineItems = new List <LineItem>() }; var result = await validator.ValidateAsync(target); result.Should().NotBeNull("because a validation result should have been returned"); result.Should().BeEmpty("because an empty itemout set is allowed"); }
public async Task ItemOutsAreValidated() { var currentInstant = Instant.FromUtc(2017, 08, 17, 12, 0, 0); var fakeClock = new FakeClock(currentInstant); var headerValidator = new OrderHeaderValidator(fakeClock) as IMessageValidator <OrderHeader>; var itemValidator = new itemItemValidator() as IMessageValidator <ItemAsset>; var itemOutValidator = new ItemOutValidator(itemValidator) as IMessageValidator <LineItem>; var validator = new OrderFulfillmentMessageValidator(headerValidator, itemOutValidator); var header = new OrderHeader { OrderId = "ABC123", OrderDate = currentInstant.ToDateTimeUtc() }; var itemOuts = new List <LineItem> { new LineItem { Assets = new List <ItemAsset> { new ItemAsset(), new ItemAsset() } } }; var target = new OrderFulfillmentMessage { OrderRequestHeader = header, LineItems = itemOuts }; var result = await validator.ValidateAsync(target); var failurePath = $"{ nameof(OrderFulfillmentMessage.LineItems) }[0].{ nameof(LineItem.Assets) }"; result.Should().NotBeNull("because a validation result should have been returned"); result.Should().ContainSingle(error => error.MemberPath == failurePath, "because the itemout violated a rule"); }
public async Task <IHttpActionResult> FulfillOrderWebHook(string partner, [FromBody] OrderFulfillmentMessage order) { // Verify that the order was sent as the request body. if (order == null) { var errorSet = new ErrorSet(ErrorCode.ValueIsRequired, nameof(order), "The order body is required."); try { var body = await this.Request.SafeReadContentAsStringAsync(); this.Log .WithCorrelationId(this.Request.GetOrderFulfillmentCorrelationId()) .Information($"Response: {{Response}} { Environment.NewLine } Missing order detected for {{Controller}}::{{ActionMethod}}({{Partner}}) with Headers: [{{Headers}}] { Environment.NewLine } Body: {{RequestBody}} { Environment.NewLine } The following errors were observed: { Environment.NewLine }{{ErrorSet}}", HttpStatusCode.BadRequest, nameof(OrderSubmissionController), nameof(FulfillOrderWebHook), partner, this.Request.Headers, body, errorSet); } catch { // Do nothing; logging is a non-critical operation that should not cause // cascading failures. } return(this.BadRequest(errorSet)); } // If the emulation data was provided and the caller is not priviledged, then reject the request. var principal = this.User as ClaimsPrincipal; if ((order.Emulation != null) && ((principal == null) || (!principal.HasClaim(claim => claim.Type == CustomClaimTypes.MayAccessPriviledgedOperations)))) { try { this.Log .WithCorrelationId(this.Request.GetOrderFulfillmentCorrelationId()) .Warning($"Response: {{Response}} { Environment.NewLine } Unauthorized request detected for {{Controller}}::{{ActionMethod}}({{Partner}}) with Headers: [{{Headers}}] { Environment.NewLine } The caller does not have permission to perform a priviledged operation.", HttpStatusCode.Forbidden, nameof(OrderSubmissionController), nameof(FulfillOrderWebHook), partner, this.Request.Headers); } catch { // Do nothing; logging is a non-critical operation that should not cause // cascading failures. } return(this.Content <object>(HttpStatusCode.Forbidden, null)); } var assets = order.LineItems .SelectMany(item => item.Assets) .Where(asset => asset != null) .ToDictionary(asset => asset.Name, asset => this.ParseAssetLocationToUrl(asset.Location)); // Create the command to trigger order processing and place it on the command queue var command = new ProcessOrder { OrderId = order.OrderRequestHeader.OrderId, PartnerCode = partner, Assets = assets, Emulation = order.Emulation, Id = Guid.NewGuid(), CorrelationId = this.Request.GetOrderFulfillmentCorrelationId(), OccurredTimeUtc = this.clock.GetCurrentInstant().ToDateTimeUtc(), CurrentUser = principal?.Identity?.Name, Sequence = 0 }; if (!(await this.processOrderCommandPublisher.TryPublishAsync(command))) { this.Log .WithCorrelationId(this.Request.GetOrderFulfillmentCorrelationId()) .Error("Unable to publish the {CommandName} for {Partner}//{Order}", nameof(ProcessOrder), partner, command.OrderId); return(this.ServiceUnavailable(this.CaclulateRetryAfter(this.config.ServiceUnavailableeRetryAfterInSeconds))); } // This can't be fire-and-forget, as completing the handler with the outstanding request causes an exception. try { await this.eventPublisher.TryPublishAsync(command.CreateNewOrderEvent <OrderReceived>()); } catch (Exception ex) { this.Log .WithCorrelationId(this.Request.GetOrderFulfillmentCorrelationId()) .Error(ex, "The event {EventName} for {Partner}//{Order} could not be published. This is non-critical for fulfillment processing.", nameof(OrderReceived), partner, command.OrderId); } return(this.Accepted(new OrderFulfillmentAccepted(command.OrderId), this.CaclulateRetryAfter(this.config.OrderAcceptedRetryAfterInSeconds))); }
public async Task FulfillOrderWebHookAllowsNonUrlAssetsForAnAcceptedOrder() { var mockLogger = new Mock <ILogger>(); var mockCommandPublisher = new Mock <ICommandPublisher <ProcessOrder> >(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); var publishedCommand = default(ProcessOrder); mockLogger.Setup(log => log.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); mockCommandPublisher .Setup(publisher => publisher.TryPublishAsync(It.IsAny <ProcessOrder>(), It.IsAny <Instant?>())) .ReturnsAsync(true) .Callback <ProcessOrder, Instant?>((command, publishTime) => publishedCommand = command); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), mockCommandPublisher.Object, Mock.Of <IEventPublisher <EventBase> >(), mockLogger.Object, new OrderSubmissionControllerConfiguration { OrderAcceptedRetryAfterInSeconds = 5 }) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem> { { new LineItem { Assets = new List <ItemAsset> { { new ItemAsset { Name = "one", Location = "Not a url" } } } } } } }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); publishedCommand.Should().NotBeNull("because the command should have been published"); foreach (var item in order.LineItems) { var asset = item.Assets.Single(); var commandAsset = publishedCommand.Assets[asset.Name]; commandAsset.Should().NotBeNull("because an asset for asset {0} should be present", asset.Name); commandAsset.Should().Be(asset.Location, "because the asset value should be unchanged for asset {0}", asset.Name); } }
public async Task FulfillOrderWebHookForcesAssetUrlsToHttpsForAnAcceptedOrder() { var mockLogger = new Mock <ILogger>(); var mockCommandPublisher = new Mock <ICommandPublisher <ProcessOrder> >(); var mockActionDescriptor = new Mock <HttpActionDescriptor>(); var httpConfiguration = new HttpConfiguration(); var routeData = new HttpRouteData(new HttpRoute()); var request = new HttpRequestMessage(); var controllerDescriptor = new HttpControllerDescriptor { Configuration = httpConfiguration, ControllerName = nameof(OrderSubmissionController) }; var controllerContext = new HttpControllerContext(httpConfiguration, routeData, request) { ControllerDescriptor = controllerDescriptor }; var actionContext = new HttpActionContext(controllerContext, mockActionDescriptor.Object); var publishedCommand = default(ProcessOrder); mockLogger.Setup(log => log.ForContext(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <bool>())) .Returns(mockLogger.Object); mockCommandPublisher .Setup(publisher => publisher.TryPublishAsync(It.IsAny <ProcessOrder>(), It.IsAny <Instant?>())) .ReturnsAsync(true) .Callback <ProcessOrder, Instant?>((command, publishTime) => publishedCommand = command); mockActionDescriptor.SetupGet(descriptor => descriptor.ActionName).Returns("someAction"); request.SetConfiguration(httpConfiguration); request.SetRouteData(routeData); var controller = new OrderSubmissionController(Mock.Of <IClock>(), mockCommandPublisher.Object, Mock.Of <IEventPublisher <EventBase> >(), mockLogger.Object, new OrderSubmissionControllerConfiguration { OrderAcceptedRetryAfterInSeconds = 5 }) { ControllerContext = controllerContext }; var order = new OrderFulfillmentMessage { OrderRequestHeader = new OrderHeader { OrderId = "ABC123", OrderDate = new DateTime(2017, 12, 09, 09, 00, 00, DateTimeKind.Utc) }, LineItems = new List <LineItem> { { new LineItem { Assets = new List <ItemAsset> { { new ItemAsset { Name = "one", Location = "https://www.bob.com/path" } } } } }, { new LineItem { Assets = new List <ItemAsset> { { new ItemAsset { Name = "two", Location = "https://www.john.com:443/path/?name=john" } } } } }, { new LineItem { Assets = new List <ItemAsset> { { new ItemAsset { Name = "three", Location = "gopher://www.frank.com:8086/path" } } } } } } }; var actionResult = await controller.FulfillOrderWebHook("SQUIRE", order); var result = await actionResult.ExecuteAsync(CancellationToken.None); result.Should().NotBeNull("because a result should have been returned"); publishedCommand.Should().NotBeNull("because the command should have been published"); foreach (var item in order.LineItems) { var asset = item.Assets.Single(); var commandAsset = publishedCommand.Assets[asset.Name]; asset.Should().NotBeNull("because an asset for asset {0} should be present", asset.Name); var assetUri = new Uri(asset.Location); var commandAssetUri = new Uri(commandAsset); commandAssetUri.Scheme.Should().Be(Uri.UriSchemeHttps, "because the uri scheme should have been forced to HTTPS for asset {0}", asset.Name); commandAssetUri.Host.Should().Be(assetUri.Host, "because the authorities should match for asset {0}", asset.Name); commandAssetUri.PathAndQuery.Should().Be(assetUri.PathAndQuery, "because the path and querystring should match for asset {0}", asset.Name); if (assetUri.IsDefaultPort) { commandAssetUri.Port.Should().Be(443, "because the default port was used for asset {0}", asset.Name); } else { commandAssetUri.Port.Should().Be(assetUri.Port, "because a non-default port was used for asset {0}", asset.Name); } } }