public async Task ValidateAsync_WhenCalculationNameAlreadyExistsButItsTheSameCalc_EnsuresValidIsTrue() { //Arrange CalculationEditModel model = CreateModel(); Calculation calculationWithSameName = new Calculation { Id = model.CalculationId }; ICalculationsRepository calculationsRepository = CreateCalculationRepository(); calculationsRepository .GetCalculationsBySpecificationIdAndCalculationName(Arg.Is(model.SpecificationId), Arg.Is(model.Name)) .Returns(calculationWithSameName); CalculationEditModelValidator validator = CreateValidator(calculationRepository: calculationsRepository); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeTrue(); }
public void Validate_GivenValidModelWithBaselineCalculationHasSpecificationThatDoesNotExist_ValidIsFalse() { //Arrange CalculationEditModel model = CreateModel(); model.CalculationType = CalculationType.Baseline; ISpecificationsRepository specsRepo = CreateSpecificationsRepository(false); Specification specification = null; specsRepo .GetSpecificationById(specificationId) .Returns(specification); CalculationEditModelValidator validator = CreateValidator(specsRepo); //Act ValidationResult result = validator.Validate(model); //Assert result .IsValid .Should() .BeFalse(); IEnumerable <string> expectedErrors = new[] { "Specification not found", "Unable to find Allocation Line with provided ID" }; result.Errors.Count().Should().Be(expectedErrors.Count()); foreach (string error in expectedErrors) { result.Errors.Count(e => e.ErrorMessage == error).Should().Be(1); } }
public async Task ValidateAsync_WhenSourceCodeDoesNotCompile_ValidIsFalse() { //Arrange CalculationEditModel model = CreateModel(); PreviewResponse previewResponse = new PreviewResponse { CompilerOutput = new Build { CompilerMessages = new List <CompilerMessage> { new CompilerMessage { Message = "Failed" } } } }; IPreviewService previewService = CreatePreviewService(previewResponse); CalculationEditModelValidator validator = CreateValidator(previewService: previewService); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); }
public async Task EditCalculation_WhenInvalidModelProvided_ThenValidationErrorReturned() { // Arrange ValidationResult validationResult = new ValidationResult(); validationResult.Errors.Add(new ValidationFailure("error", "error")); IValidator <CalculationEditModel> validator = CreateEditCalculationValidator(validationResult); CalculationEditModel calculationEditModel = new CalculationEditModel(); string json = JsonConvert.SerializeObject(calculationEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); SpecificationsService specificationsService = CreateService(calculationEditModelValidator: validator); // Act IActionResult result = await specificationsService.EditCalculation(request); // Assert result .Should() .BeOfType <BadRequestObjectResult>() .Which .Value .Should() .BeOfType <SerializableError>() .Which .Should() .HaveCount(1); }
public async Task EditCalculationWithSkipInstruct() { string specificationId = NewRandomString(); string calculationId = NewRandomString(); CalculationEditModel calculationEditModel = new CalculationEditModel(); await AssertPutRequest($"specifications/{specificationId}/calculations/{calculationId}/true", calculationEditModel, new Calculation(), () => _client.EditCalculationWithSkipInstruct(specificationId, calculationId, calculationEditModel)); }
public async Task EditCalculation_WhenValidModelButCalculationCouldNotBeFound_ThenReturnsNotFoundResult() { // Arrange CalculationEditModel policyEditModel = new CalculationEditModel(); string json = JsonConvert.SerializeObject(policyEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); Specification specification = CreateSpecification(); ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); SpecificationsService specificationsService = CreateService(specificationsRepository: specificationsRepository); // Act IActionResult result = await specificationsService.EditCalculation(request); // Assert result .Should() .BeOfType <NotFoundObjectResult>() .Which .Value .Should() .Be($"Calculation not found for calculation id '{CalculationId}'"); }
public async Task <IActionResult> SaveCalculation(string specificationId, string calculationId, [FromBody] CalculationUpdateViewModel vm) { Guard.ArgumentNotNull(specificationId, nameof(specificationId)); Guard.ArgumentNotNull(calculationId, nameof(calculationId)); Guard.ArgumentNotNull(vm, nameof(vm)); if (!await _authorizationHelper.DoesUserHavePermission(User, specificationId, SpecificationActionTypes.CanEditCalculations)) { return(new ForbidResult()); } if (!ModelState.IsValid) { return(BadRequest(ModelState)); } ApiResponse <Calculation> existingCalculationResponse = await _calcClient.GetCalculationById(calculationId); IActionResult errorResult = existingCalculationResponse.IsSuccessOrReturnFailureResult("Calculation"); if (errorResult != null) { return(errorResult); } Calculation existingCalculation = existingCalculationResponse.Content; CalculationEditModel update = new CalculationEditModel() { CalculationId = calculationId, Description = existingCalculation.Description, Name = existingCalculation.Name, SpecificationId = specificationId, ValueType = existingCalculation.ValueType, SourceCode = vm.SourceCode, }; ValidatedApiResponse <Calculation> response = await _calcClient.EditCalculation(specificationId, calculationId, update); if (response.IsBadRequest(out BadRequestObjectResult badRequest)) { return(badRequest); } if (response.StatusCode == HttpStatusCode.OK) { return(Ok(response.Content)); } else { throw new InvalidOperationException($"An error occurred while saving calculation. Status code={response.StatusCode}"); } }
public Task <IActionResult> EditCalculation([FromRoute] string specificationId, [FromRoute] string calculationId, [FromBody] CalculationEditModel model) { HttpRequest httpRequest = ControllerContext.HttpContext.Request; return(_calcsService.EditCalculation( specificationId, calculationId, model, httpRequest.GetUser(), httpRequest.GetCorrelationId(), calculationEditMode: CalculationEditMode.User)); }
public void Validate_GivenNameAlreadyExists_ValidIsFalse() { //Arrange CalculationEditModel model = CreateModel(); ISpecificationsRepository repository = CreateSpecificationsRepository(true); Specification specification = new Specification() { Current = new SpecificationVersion() }; repository .GetSpecificationById(specificationId) .Returns(specification); ICalculationsRepository calculationsRepository = Substitute.For <ICalculationsRepository>(); calculationsRepository .IsCalculationNameValid(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>()) .Returns(false); CalculationEditModelValidator validator = CreateValidator(repository, calculationsRepository); //Act ValidationResult result = validator.Validate(model); //Assert result .IsValid .Should() .BeFalse(); result .Errors .Count .Should() .Be(1); result .Errors .Single() .ErrorMessage .Should() .Be("Calculation with the same generated source code name already exists in this specification"); calculationsRepository .Received(1) .IsCalculationNameValid(specificationId, name, calculationId); }
public async Task ValidateAsync_WhenCalculationIdEmpty_ValidIsFalse() { //Arrange CalculationEditModel model = CreateModel(); model.CalculationId = string.Empty; CalculationEditModelValidator validator = CreateValidator(); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); }
public async Task ValidateAsync_WhenValueTypeIsMissing_ValidIsFalse() { //Arrange CalculationEditModel model = CreateModel(); model.ValueType = null; CalculationEditModelValidator validator = CreateValidator(); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); }
public void ValidateWithSpecificationAndFundingStream_ValidatesAsExpected(CalculationEditModel calculationEditModel, Specification specification, IEnumerable <FundingStream> fundingStreams, bool expectedResult, IEnumerable <string> expectedErrors) { //Arrange ISpecificationsRepository specsRepo = CreateSpecificationsRepository(false); specsRepo .GetSpecificationById(specificationId) .Returns(specification); specsRepo .GetFundingStreams() .Returns(fundingStreams); CalculationEditModelValidator validator = CreateValidator(specsRepo); // Act ValidationResult result = validator.Validate(calculationEditModel); // Assert result .IsValid .Should() .Be(expectedResult); result .Errors .Count .Should() .Be(expectedErrors.Count()); foreach (string error in expectedErrors) { result .Errors .Count(e => e.ErrorMessage == error) .Should() .Be(1, $"Error message collection should have included '{error}'"); } }
public async Task <IActionResult> EditAdditionalCalculation(string specificationId, string calculationId, [FromBody] EditAdditionalCalculationViewModel vm) { Guard.ArgumentNotNull(specificationId, nameof(specificationId)); Guard.ArgumentNotNull(vm, nameof(vm)); if (!await _authorizationHelper.DoesUserHavePermission(User, specificationId, SpecificationActionTypes.CanEditCalculations)) { return(new ForbidResult()); } if (!ModelState.IsValid) { return(BadRequest(ModelState)); } CalculationEditModel editCalculation = _mapper.Map <CalculationEditModel>(vm); editCalculation.SpecificationId = specificationId; editCalculation.CalculationId = calculationId; editCalculation.Name = vm.CalculationName; editCalculation.ValueType = vm.ValueType; editCalculation.DataType = vm.DataType; ValidatedApiResponse <Calculation> response = await _calcClient.EditCalculation(specificationId, calculationId, editCalculation); if (response.IsBadRequest(out BadRequestObjectResult badRequest)) { return(badRequest); } if (response.StatusCode == HttpStatusCode.OK) { return(Ok(response.Content)); } else { throw new InvalidOperationException($"An error occurred while saving calculation. Status code={response.StatusCode}"); } }
public async Task ValidateAsync_WhenValidModel_ValidIsTrue() { //Arrange CalculationEditModel model = CreateModel(); ICalculationsRepository calculationsRepository = CreateCalculationRepository(); calculationsRepository .GetCalculationsBySpecificationIdAndCalculationName(Arg.Is(model.SpecificationId), Arg.Is(model.Name)) .Returns((Calculation)null); CalculationEditModelValidator validator = CreateValidator(calculationsRepository); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeTrue(); }
public async Task <ValidatedApiResponse <Calculation> > EditCalculationWithSkipInstruct(string specificationId, string calculationId, CalculationEditModel calculationEditModel) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); Guard.ArgumentNotNull(calculationEditModel, nameof(calculationEditModel)); string url = $"{UrlRoot}/specifications/{specificationId}/calculations/{calculationId}/true"; return(await ValidatedPutAsync <Calculation, CalculationEditModel>(url, calculationEditModel)); }
public async Task EditCalculation_WhenValidModelButUpdateCosmosReturnsBadRequest_ReturnsBadRequest() { // Arrange CalculationEditModel policyEditModel = new CalculationEditModel { Name = "new calc name", CalculationType = CalculationType.Funding, Description = "test description", PolicyId = "policy-id-2" }; string json = JsonConvert.SerializeObject(policyEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); Specification specification = CreateSpecification(); specification .Current .Policies = new[] { new Policy { Id = PolicyId, Name = PolicyName, Calculations = new[] { new Calculation { Id = CalculationId, Name = "Old name" } } }, new Policy { Id = "policy-id-2", Name = PolicyName } }; ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); specificationsRepository .UpdateSpecification(Arg.Is(specification)) .Returns(HttpStatusCode.BadRequest); SpecificationsService specificationsService = CreateService(specificationsRepository: specificationsRepository); // Act IActionResult result = await specificationsService.EditCalculation(request); // Assert result .Should() .BeOfType <StatusCodeResult>() .Which .StatusCode .Should() .Be(400); }
public async Task EditCalculation_WhenCalcInSubPolicyButNotTopLevelPolicyUpdatesCosmos_SendsMessageReturnsOk() { // Arrange CalculationEditModel policyEditModel = new CalculationEditModel { Name = "new calc name", CalculationType = CalculationType.Funding, Description = "test description", PolicyId = "policy-id-2" }; string json = JsonConvert.SerializeObject(policyEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); Specification specification = CreateSpecification(); specification .Current .Policies = new[] { new Policy { Id = PolicyId, Name = PolicyName, SubPolicies = new[] { new Policy { Id = "policy-id-2", Name = "sub-policy", Calculations = new[] { new Calculation { Id = CalculationId, Name = "Old name" } } } } } }; ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); specificationsRepository .UpdateSpecification(Arg.Is(specification)) .Returns(HttpStatusCode.OK); ICacheProvider cacheProvider = CreateCacheProvider(); IMessengerService messengerService = CreateMessengerService(); SpecificationVersion newSpecVersion = specification.Current.Clone() as SpecificationVersion; newSpecVersion.Policies.First().SubPolicies.First().Calculations = new[] { new Calculation { Id = CalculationId, Name = "new calc name" } }; IVersionRepository <SpecificationVersion> versionRepository = CreateVersionRepository(); versionRepository .CreateVersion(Arg.Any <SpecificationVersion>(), Arg.Any <SpecificationVersion>()) .Returns(newSpecVersion); SpecificationsService specificationsService = CreateService(specificationsRepository: specificationsRepository, cacheProvider: cacheProvider, messengerService: messengerService, specificationVersionRepository: versionRepository); // Act IActionResult result = await specificationsService.EditCalculation(request); // Assert result .Should() .BeOfType <OkObjectResult>(); specification .Current .Policies .First() .SubPolicies .First() .Calculations .First() .Name .Should() .Be("new calc name"); await messengerService .Received(1) .SendToTopic(Arg.Is(ServiceBusConstants.TopicNames.EditCalculation), Arg.Is <CalculationVersionComparisonModel>( m => m.CalculationId == CalculationId && m.SpecificationId == SpecificationId ), Arg.Any <IDictionary <string, string> >()); await versionRepository .Received(1) .SaveVersion(Arg.Is(newSpecVersion)); }
public void EditCalculation_WhenSomethingGoesWrongDuringIndexing_ShouldThrowException() { // Arrange const string errorMessage = "Encountered error 802"; CalculationEditModel policyEditModel = new CalculationEditModel { Name = "new calc name", CalculationType = CalculationType.Funding, Description = "test description", PolicyId = "policy-id-2" }; string json = JsonConvert.SerializeObject(policyEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); Specification specification = CreateSpecification(); specification .Current .Policies = new[] { new Policy { Id = PolicyId, Name = PolicyName, Calculations = new[] { new Calculation { Id = CalculationId, Name = "Old name" } } }, new Policy { Id = "policy-id-2", Name = PolicyName } }; ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); specificationsRepository .UpdateSpecification(Arg.Is(specification)) .Returns(HttpStatusCode.OK); ICacheProvider cacheProvider = CreateCacheProvider(); IMessengerService messengerService = CreateMessengerService(); SpecificationVersion newSpecVersion = specification.Current.Clone() as SpecificationVersion; newSpecVersion.Policies.ElementAt(1).Calculations = new[] { new Calculation { Id = CalculationId, Name = "new calc name" } }; IVersionRepository <SpecificationVersion> versionRepository = CreateVersionRepository(); versionRepository .CreateVersion(Arg.Any <SpecificationVersion>(), Arg.Any <SpecificationVersion>()) .Returns(newSpecVersion); ISearchRepository <SpecificationIndex> mockSearchRepository = CreateSearchRepository(); mockSearchRepository .Index(Arg.Any <IEnumerable <SpecificationIndex> >()) .Returns(new List <IndexError>() { new IndexError() { ErrorMessage = errorMessage } }); SpecificationsService specificationsService = CreateService(specificationsRepository: specificationsRepository, cacheProvider: cacheProvider, messengerService: messengerService, specificationVersionRepository: versionRepository, searchRepository: mockSearchRepository); //Act Func <Task <IActionResult> > editSpecification = async() => await specificationsService.EditCalculation(request); //Assert editSpecification .Should() .Throw <ApplicationException>() .Which .Message .Should() .Be($"Could not index specification {specification.Current.Id} because: {errorMessage}"); }
public async Task EditCalculation_WhenRenameCalculationToBrandNew_ReturnsOk() { // Arrange CalculationEditModel policyEditModel = new CalculationEditModel { Name = "new calc name", CalculationType = CalculationType.Funding, Description = "test description", PolicyId = "policy-id-2" }; string json = JsonConvert.SerializeObject(policyEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); Specification specification = CreateSpecification(); specification .Current .Policies = new[] { new Policy { Id = PolicyId, Name = PolicyName, SubPolicies = new[] { new Policy { Id = "policy-id-2", Name = "sub-policy", Calculations = new[] { new Calculation { Id = CalculationId, Name = "Old name" } } } } } }; ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); specificationsRepository .UpdateSpecification(Arg.Is(specification)) .Returns(HttpStatusCode.OK); SpecificationVersion newSpecVersion = specification.Current.Clone() as SpecificationVersion; newSpecVersion.Policies.First().SubPolicies.First().Calculations = new[] { new Calculation { Id = CalculationId, Name = "new calc name" } }; IVersionRepository <SpecificationVersion> versionRepository = CreateVersionRepository(); versionRepository .CreateVersion(Arg.Any <SpecificationVersion>(), Arg.Any <SpecificationVersion>()) .Returns(newSpecVersion); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .IsCalculationNameValid(Arg.Is(SpecificationId), Arg.Is("new calc name"), Arg.Is(CalculationId)) .Returns(true); SpecificationsService specificationsService = CreateService(specificationsRepository: specificationsRepository, specificationVersionRepository: versionRepository); // Act IActionResult result = await specificationsService.EditCalculation(request); // Assert result .Should() .BeOfType <OkObjectResult>(); await versionRepository .Received(1) .SaveVersion(Arg.Is(newSpecVersion)); }
public async Task EditCalculation_WhenRenameCalcToSameAsExisting_ReturnsBadRequest() { // Arrange CalculationEditModel policyEditModel = new CalculationEditModel { Name = "Another name", CalculationType = CalculationType.Funding, Description = "test description", PolicyId = "policy-id-2" }; string json = JsonConvert.SerializeObject(policyEditModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpContext context = Substitute.For <HttpContext>(); HttpRequest request = Substitute.For <HttpRequest>(); IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues> { { "specificationId", new StringValues(SpecificationId) }, { "calculationId", new StringValues(CalculationId) }, }); request .Query .Returns(queryStringValues); request .Body .Returns(stream); request .HttpContext .Returns(context); Specification specification = CreateSpecification(); specification .Current .Policies = new[] { new Policy { Id = PolicyId, Name = PolicyName, Calculations = new[] { new Calculation { Id = CalculationId, Name = "Old name" }, new Calculation { Id = "calc2", Name = "Another name" } } } }; ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .IsCalculationNameValid(Arg.Is(specification.Id), Arg.Is("Another name"), Arg.Is(CalculationId)) .Returns(false); IValidator <CalculationEditModel> validator = CreateRealEditCalculationValidator(specificationsRepository, calculationsRepository); SpecificationsService specificationsService = CreateService(specificationsRepository: specificationsRepository, calculationEditModelValidator: validator); // Act IActionResult result = await specificationsService.EditCalculation(request); // Assert result .Should() .BeOfType <BadRequestObjectResult>(); }