public void Validate_ValidatesAsExpected(CalculationCreateModel model, bool expectedResult, IEnumerable <string> expectedErrors) { //Arrange ISpecificationsRepository specsRepo = CreateSpecificationsRepository(false); Specification specification = new Specification { Current = new SpecificationVersion() }; specsRepo .GetSpecificationById(specificationId) .Returns(specification); CalculationCreateModelValidator validator = CreateValidator(specsRepo); //Act ValidationResult result = validator.Validate(model); //Assert result .IsValid .Should() .Be(expectedResult); foreach (var error in expectedErrors) { result.Errors.Count(e => e.ErrorMessage == error).Should().Be(1, $"Expected to find error message '{error}'"); } result .Errors .Count .Should() .Be(expectedErrors.Count()); }
public async Task CreateAdditionalCalculation_GivenCreateJobReturnsNull_ReturnsInternalServerError() { //Arrange CalculationCreateModel model = CreateCalculationCreateModel(); Reference author = CreateAuthor(); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .CreateDraftCalculation(Arg.Any <Calculation>()) .Returns(HttpStatusCode.OK); IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository(); ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository(); IJobManagement jobManagement = CreateJobManagement(); jobManagement .QueueJob(Arg.Any <JobCreateModel>()) .Returns((Job)null); ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(SpecificationId)) .Returns(new ApiResponse <SpecificationSummary>( HttpStatusCode.OK, new SpecificationSummary { Id = SpecificationId } )); ILogger logger = CreateLogger(); CalculationService calculationService = CreateCalculationService( calculationsRepository: calculationsRepository, calculationVersionRepository: versionRepository, searchRepository: searchRepository, jobManagement: jobManagement, logger: logger, specificationsApiClient: specificationsApiClient); //Act IActionResult result = await calculationService.CreateAdditionalCalculation(SpecificationId, model, author, CorrelationId); //Assert result .Should() .BeOfType <InternalServerErrorResult>() .Which .Value .Should() .Be($"Failed to create job of type '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' on specification '{SpecificationId}'"); logger .Received(1) .Error(Arg.Is($"Failed to create job of type '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' on specification '{SpecificationId}'")); }
public async Task CreateAdditionalCalculation_GivenValidationFails_ReturnsBadRequest() { //Arrange string correlationId = "any-id"; CalculationCreateModel model = new CalculationCreateModel(); Reference author = new Reference(); ValidationResult validationResult = new ValidationResult(new[] { new ValidationFailure("prop1", "oh no an error!!!") }); IValidator <CalculationCreateModel> validator = CreateCalculationCreateModelValidator(validationResult); ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(SpecificationId)) .Returns(new ApiResponse <SpecificationSummary>( HttpStatusCode.OK, new SpecificationSummary { Id = SpecificationId } )); CalculationService calculationService = CreateCalculationService(calculationCreateModelValidator: validator, specificationsApiClient: specificationsApiClient); //Act IActionResult result = await calculationService.CreateAdditionalCalculation(SpecificationId, model, author, correlationId); //Assert result .Should() .BeAssignableTo <BadRequestObjectResult>(); }
public async Task ValidateAsync_WhenCalculationNameAlreadyExists_ValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); Calculation calculationWithSameName = new Calculation(); ICalculationsRepository calculationsRepository = CreateCalculationRepository(); calculationsRepository .GetCalculationsBySpecificationIdAndCalculationName(Arg.Is(model.SpecificationId), Arg.Is(model.Name)) .Returns(calculationWithSameName); CalculationCreateModelValidator validator = CreateValidator(calculationRepository: calculationsRepository); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "A calculation already exists with the name: 'test calc' for this specification"); }
public async Task <IActionResult> CreateAdditionalCalculation([FromRoute] string specificationId, [FromBody] CalculationCreateModel model) { HttpRequest httpRequest = ControllerContext.HttpContext.Request; return(await _calcsService.CreateAdditionalCalculation(specificationId, model, httpRequest.GetUserOrDefault(), httpRequest.GetCorrelationId())); }
public async Task <IActionResult> CreateCalculation(string specificationId, string calculationId, [FromBody] CreateAdditionalCalculationViewModel vm) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } if (!await _authorizationHelper.DoesUserHavePermission(User, specificationId, SpecificationActionTypes.CanEditCalculations)) { return(new ForbidResult()); } CalculationCreateModel createCalculation = _mapper.Map <CalculationCreateModel>(vm); createCalculation.SpecificationId = specificationId; createCalculation.Id = calculationId; createCalculation.Name = vm.CalculationName; createCalculation.ValueType = vm.CalculationType; ValidatedApiResponse <Calculation> response = await _calcClient.CreateCalculation(specificationId, createCalculation); if (response.IsBadRequest(out BadRequestObjectResult badRequest)) { return(badRequest); } if (response.StatusCode == HttpStatusCode.OK) { return(Ok(response.Content)); } return(BadRequest($"An error occurred while saving calculation. Please check and try again.")); }
public async Task ValidateAsync_WhenSpecificationCanNotBeFound_ValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(model.SpecificationId)) .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, null)); CalculationCreateModelValidator validator = CreateValidator(specificationsApiClient: specificationsApiClient); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "Failed to find specification for provided specification id."); }
public async Task ValidateAsync_WhenSpecificationDoesNotContainFundingStreamValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary { FundingStreams = new[] { new Reference() } }; ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(model.SpecificationId)) .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary)); CalculationCreateModelValidator validator = CreateValidator(specificationsApiClient: specificationsApiClient); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "The funding stream id provided is not associated with the provided specification."); }
public async Task CreateCalculation_GivenDuplicateCalculationName_ReturnsBadRequest() { // Arrange Specification specification = CreateSpecification(); CalculationCreateModel model = new CalculationCreateModel { SpecificationId = SpecificationId, PolicyId = PolicyId, Name = "calc1", CalculationType = CalculationType.Number }; string json = JsonConvert.SerializeObject(model); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); ClaimsPrincipal principal = new ClaimsPrincipal(new[] { new ClaimsIdentity(new [] { new Claim(ClaimTypes.Sid, UserId), new Claim(ClaimTypes.Name, Username) }) }); HttpContext context = Substitute.For <HttpContext>(); context .User .Returns(principal); HttpRequest request = Substitute.For <HttpRequest>(); request .Body .Returns(stream); request .HttpContext .Returns(context); ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); IValidator <CalculationCreateModel> validator = CreateCalculationValidator(new ValidationResult(new[] { new ValidationFailure("prop1", "any error") })); SpecificationsService service = CreateService(specificationsRepository: specificationsRepository, calculationCreateModelValidator: validator); // Act IActionResult result = await service.CreateCalculation(request); // Assert result .Should() .BeOfType <BadRequestObjectResult>(); }
public async Task CreateCalculation_GivenValidModelButNoPolicyFound_ReturnsPreconditionFailed() { //Arrange Specification specification = new Specification() { Current = new SpecificationVersion(), }; CalculationCreateModel model = new CalculationCreateModel { SpecificationId = SpecificationId, PolicyId = PolicyId }; string json = JsonConvert.SerializeObject(model); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpRequest request = Substitute.For <HttpRequest>(); request .Body .Returns(stream); ILogger logger = CreateLogger(); ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns(specification); Calculation calculation = new Calculation(); IMapper mapper = CreateMapper(); mapper .Map <Calculation>(model) .Returns(calculation); SpecificationsService service = CreateService(logs: logger, specificationsRepository: specificationsRepository, mapper: mapper); //Act IActionResult result = await service.CreateCalculation(request); //Assert result .Should() .BeOfType <PreconditionFailedResult>() .Which .Value .Should() .Be("Policy not found for policy id 'dda8ccb3-eb8e-4658-8b3f-f1e4c3a8f322'"); logger .Received(1) .Warning($"Policy not found for policy id '{PolicyId}'"); }
public async Task ValidateAsync_WhenSourceCodeDoesNotCompile__ValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); model.CalculationType = CalculationType.Additional; ICalculationsRepository calculationsRepository = CreateCalculationRepository(); calculationsRepository .GetCalculationsBySpecificationIdAndCalculationName(Arg.Is(model.SpecificationId), Arg.Is(model.Name)) .Returns((Calculation)null); SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary { Name = "spec name", FundingStreams = new[] { new Reference(model.FundingStreamId, "funding stream name") } }; ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(model.SpecificationId)) .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary)); PreviewResponse previewResponse = new PreviewResponse { CompilerOutput = new Build { CompilerMessages = new List <CompilerMessage> { new CompilerMessage { Message = "Failed" } } } }; IPreviewService previewService = CreatePreviewService(previewResponse); CalculationCreateModelValidator validator = CreateValidator( calculationsRepository, previewService: previewService, specificationsApiClient: specificationsApiClient); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "There are errors in the source code provided"); }
public async Task CreateCalculation() { string id = NewRandomString(); CalculationCreateModel calculationCreateModel = new CalculationCreateModel(); await AssertPostRequest($"specifications/{id}/calculations", calculationCreateModel, new Calculation(), () => _client.CreateCalculation(id, calculationCreateModel)); }
public async Task <ValidatedApiResponse <Calculation> > CreateCalculation( string specificationId, CalculationCreateModel calculationCreateModel, bool skipCalcRun, bool skipQueueCodeContextCacheUpdate, bool overrideCreateModelAuthor, bool updateBuildProject) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); Guard.ArgumentNotNull(calculationCreateModel, nameof(calculationCreateModel)); string url = $"{UrlRoot}/specifications/{specificationId}/calculations/{skipCalcRun}/{skipQueueCodeContextCacheUpdate}/{overrideCreateModelAuthor}/{updateBuildProject}"; return(await ValidatedPostAsync <Calculation, CalculationCreateModel>(url, calculationCreateModel)); }
public async Task CreateAdditionalCalculation_GivenSavingDraftCalcFails_ReturnsInternalServerErrorResult() { //Arrange string correlationId = "any-id"; CalculationCreateModel model = CreateCalculationCreateModel(); Reference author = CreateAuthor(); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .CreateDraftCalculation(Arg.Any <Calculation>()) .Returns(HttpStatusCode.BadRequest); ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(SpecificationId)) .Returns(new ApiResponse <SpecificationSummary>( HttpStatusCode.OK, new SpecificationSummary { Id = SpecificationId } )); ILogger logger = CreateLogger(); CalculationService calculationService = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository, specificationsApiClient: specificationsApiClient); string errorMessage = $"There was problem creating a new calculation with name {CalculationName} in Cosmos Db with status code 400"; //Act IActionResult result = await calculationService.CreateAdditionalCalculation(SpecificationId, model, author, correlationId); //Assert result .Should() .BeAssignableTo <InternalServerErrorResult>() .Which .Value .Should() .Be(errorMessage); logger .Received(1) .Error(Arg.Is(errorMessage)); }
public async Task CreateCalculationWithSkipParameters() { string id = NewRandomString(); CalculationCreateModel calculationCreateModel = new CalculationCreateModel(); bool skipCalcRun = NewRandomBoolean(); bool skipQueueCodeContextCacheUpdate = NewRandomBoolean(); bool overrideCreateModelAuthor = NewRandomBoolean(); bool updateBuildProject = NewRandomBoolean(); await AssertPostRequest($"specifications/{id}/calculations/{skipCalcRun}/{skipQueueCodeContextCacheUpdate}/{overrideCreateModelAuthor}/{updateBuildProject}", calculationCreateModel, new Calculation(), () => _client.CreateCalculation(id, calculationCreateModel, skipCalcRun, skipQueueCodeContextCacheUpdate, overrideCreateModelAuthor, updateBuildProject)); }
private async Task GenerateCalculations(SpecGeneratorConfiguration configuration, Specification specification) { int totalCalculations = 0; if (configuration.NumberOfCalculations > 0) { totalCalculations = configuration.NumberOfCalculations; } List <Policy> policies = new List <Policy>(specification.Policies); List <AllocationLine> allocationLines = new List <AllocationLine>(); _logger.Information("Generating {totalCalculations} calculations across {Count} policies", totalCalculations, policies.Count); foreach (FundingStream fundingStream in specification.FundingStreams) { foreach (AllocationLine allocationLine in fundingStream.AllocationLines) { allocationLines.Add(allocationLine); } } IEnumerable <string> allocationLineNames = allocationLines.Select(a => a.Name); _logger.Information("Creating calculations in the following Allocation Lines {allocationLineNames}", allocationLineNames); for (int i = 0; i < totalCalculations; i++) { Policy policy = policies[i % policies.Count]; AllocationLine allocationLine = allocationLines[i % allocationLines.Count]; CalculationCreateModel calculationCreateModel = new CalculationCreateModel() { SpecificationId = specification.Id, PolicyId = policy.Id, AllocationLineId = allocationLine.Id, CalculationType = CalculationSpecificationType.Funding, Description = "SpecGenerator", Name = $"{specification.Name} - Calculation {i + 1}", IsPublic = false, }; await _specsClient.CreateCalculation(calculationCreateModel); } }
public void ValidateWithSpecificationAndFundingStreams_ValidatesAsExpected(CalculationCreateModel model, Specification specification, IEnumerable <FundingStream> fundingStreams, bool expectedResult, IEnumerable <string> expectedErrors) { //Arrange ISpecificationsRepository specsRepo = CreateSpecificationsRepository(false); specsRepo .GetSpecificationById(specificationId) .Returns(specification); specsRepo .GetFundingStreams() .Returns(fundingStreams); CalculationCreateModelValidator validator = CreateValidator(specsRepo); //Act ValidationResult result = validator.Validate(model); //Assert result .IsValid .Should() .Be(expectedResult); foreach (var error in expectedErrors) { result .Errors .Select(e => e.ErrorMessage) .Distinct() .Count(e => e == error) .Should() .Be(1, $"Expected to find error message '{error}'"); } result .Errors .Count .Should() .Be(expectedErrors.Count()); }
public void Validate_GivenNameAlreadyExists_ValidIsFalse() { //Arrange CalculationCreateModel 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); CalculationCreateModelValidator 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); }
public async Task ValidateAsync_WhenValidModel_ValidIsTrue() { //Arrange CalculationCreateModel model = CreateModel(); ICalculationsRepository calculationsRepository = CreateCalculationRepository(); calculationsRepository .GetCalculationsBySpecificationIdAndCalculationName(Arg.Is(model.SpecificationId), Arg.Is(model.Name)) .Returns((Calculation)null); SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary { Name = "spec name", FundingStreams = new[] { new Reference(model.FundingStreamId, "funding stream name") } }; ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(model.SpecificationId)) .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary)); CalculationCreateModelValidator validator = CreateValidator( calculationsRepository, specificationsApiClient: specificationsApiClient); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeTrue(); model.SpecificationName .Should() .Be("spec name"); model.FundingStreamName .Should() .Be("funding stream name"); }
public async Task CreateCalculation_GivenValidModelButSpecificationcannotBeFoundd_ReturnsPreconditionFailed() { //Arrange CalculationCreateModel model = new CalculationCreateModel { SpecificationId = SpecificationId }; string json = JsonConvert.SerializeObject(model); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpRequest request = Substitute.For <HttpRequest>(); request .Body .Returns(stream); ILogger logger = CreateLogger(); ISpecificationsRepository specificationsRepository = CreateSpecificationsRepository(); specificationsRepository .GetSpecificationById(Arg.Is(SpecificationId)) .Returns((Specification)null); SpecificationsService service = CreateService(logs: logger, specificationsRepository: specificationsRepository); //Act IActionResult result = await service.CreateCalculation(request); //Assert result .Should() .BeOfType <PreconditionFailedResult>(); logger .Received(1) .Warning($"Specification not found for specification id {SpecificationId}"); }
public async Task ValidateAsync_WhenSpecificationIsEmpty_ValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); model.SpecificationId = string.Empty; CalculationCreateModelValidator validator = CreateValidator(); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "'Specification Id' must not be empty."); }
public async Task ValidateAsync_WhenNameIsEmpty_ValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); model.Name = string.Empty; CalculationCreateModelValidator validator = CreateValidator(); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "Null or empty calculation name provided."); }
public async Task ValidateAsync_WhenValueTypeIsMissing_ValidIsFalse() { //Arrange CalculationCreateModel model = CreateModel(); model.ValueType = null; CalculationCreateModelValidator validator = CreateValidator(); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeFalse(); result.Errors .Should() .Contain(_ => _.ErrorMessage == "Null value type was provided."); }
public async Task CreateCalculation_GivenModelButModelIsNotValid_ReturnsBadRequest() { //Arrange CalculationCreateModel model = new CalculationCreateModel(); string json = JsonConvert.SerializeObject(model); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpRequest request = Substitute.For <HttpRequest>(); request .Body .Returns(stream); ValidationResult validationResult = new ValidationResult(new[] { new ValidationFailure("prop1", "any error") }); IValidator <CalculationCreateModel> validator = CreateCalculationValidator(validationResult); ILogger logger = CreateLogger(); SpecificationsService service = CreateService(logs: logger, calculationCreateModelValidator: validator); //Act IActionResult result = await service.CreateCalculation(request); //Assert result .Should() .BeOfType <BadRequestObjectResult>(); logger .Received(1) .Error("Invalid data was provided for CreateCalculation"); }
public async Task ValidateAsync_WhenFundingStreamIdEmptyForAdditionalCalcs_ValidIsTrue() { //Arrange CalculationCreateModel model = CreateModel(CalculationType.Additional); model.FundingStreamId = string.Empty; ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(model.SpecificationId)) .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, new SpecModel.SpecificationSummary())); CalculationCreateModelValidator validator = CreateValidator(specificationsApiClient: specificationsApiClient); //Act ValidationResult result = await validator.ValidateAsync(model); //Assert result .IsValid .Should() .BeTrue(); }
public void OnPostAsync_GivenCalculationDoesNotAlreadyExistButSavingIsNotOK_InvalidOperationException() { //Arrange CreateCalculationViewModel viewModel = new CreateCalculationViewModel { Name = "any name" }; Specification specification = CreateSpecification(); IEnumerable <Reference> allocationLines = new[] { new Reference { Id = "alloc-id", Name = "alloc-name" } }; CalculationCreateModel createModel = new CalculationCreateModel { SpecificationId = specificationId }; IMapper mapper = CreateMapper(); mapper .Map <CalculationCreateModel>(Arg.Is(viewModel)) .Returns(createModel); ApiResponse <Calculation> calcApiRespnse = new ApiResponse <Calculation>(HttpStatusCode.NotFound); ValidatedApiResponse <Calculation> newCalcApiResponse = new ValidatedApiResponse <Calculation>(HttpStatusCode.InternalServerError, new Calculation { Id = "new-calc-id", }); newCalcApiResponse.ModelState = new Dictionary <string, IEnumerable <string> >(); ISpecsApiClient specsClient = CreateSpecsApiClient(); specsClient .GetCalculationBySpecificationIdAndCalculationName(Arg.Is(specificationId), Arg.Is(viewModel.Name)) .Returns(calcApiRespnse); specsClient .CreateCalculation(Arg.Is(createModel)) .Returns(newCalcApiResponse); List <FundingStream> fundingStreams = new List <FundingStream>(); fundingStreams.Add(new FundingStream { Id = fundingStreamId, AllocationLines = new List <AllocationLine>() { new AllocationLine() { Id = "al1", Name = "Allocation Line 1", } } }); ApiResponse <IEnumerable <FundingStream> > fundingStreamResponse = new ApiResponse <IEnumerable <FundingStream> >(HttpStatusCode.OK, fundingStreams); specsClient .GetFundingStreamsForSpecification(Arg.Is(specification.Id)) .Returns(fundingStreamResponse); specsClient .GetBaselineCalculationsBySpecificationId(Arg.Is(specificationId)) .Returns(new ApiResponse <IEnumerable <CalculationCurrentVersion> >(HttpStatusCode.OK, Enumerable.Empty <CalculationCurrentVersion>())); specsClient.GetSpecification(Arg.Is(specificationId)) .Returns(new ApiResponse <Specification>(HttpStatusCode.OK, specification)); CreateCalculationPageModel pageModel = CreatePageModel(specsClient, mapper); pageModel.PageContext = new PageContext(); pageModel.CreateCalculationViewModel = viewModel; //Act Func <Task> test = async() => await pageModel.OnPostAsync(specificationId); //Assert test .Should() .ThrowExactly <InvalidOperationException>(); }
public async Task <ValidatedApiResponse <Calculation> > CreateCalculation(string specificationId, CalculationCreateModel calculationCreateModel) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); Guard.ArgumentNotNull(calculationCreateModel, nameof(calculationCreateModel)); string url = $"{UrlRoot}/specifications/{specificationId}/calculations"; return(await ValidatedPostAsync <Calculation, CalculationCreateModel>(url, calculationCreateModel)); }
public Task <ApiResponse <Calculation> > CreateCalculation(CalculationCreateModel calculation) { Guard.ArgumentNotNull(calculation, nameof(calculation)); return(PostAsync <Calculation, CalculationCreateModel>("calculations", calculation)); }
public async Task <IActionResult> OnPostAsync(string specificationId) { Guard.IsNullOrWhiteSpace(specificationId, nameof(specificationId)); Specification specification = await GetSpecification(specificationId); if (!await _authorizationHelper.DoesUserHavePermission(User, specification, SpecificationActionTypes.CanEditSpecification)) { return(new ForbidResult()); } if (!string.IsNullOrWhiteSpace(CreateCalculationViewModel.Name)) { ApiResponse <Calculation> existingCalculationResponse = await _specsClient .GetCalculationBySpecificationIdAndCalculationName(specificationId, CreateCalculationViewModel.Name); if (existingCalculationResponse.StatusCode != HttpStatusCode.NotFound) { this.ModelState.AddModelError($"{nameof(CreateCalculationViewModel)}.{nameof(CreateCalculationViewModel.Name)}", ValidationMessages.CalculationNameAlreadyExists); } } if (CreateCalculationViewModel.CalculationType == "Funding" && string.IsNullOrWhiteSpace(CreateCalculationViewModel.AllocationLineId)) { this.ModelState.AddModelError($"{nameof(CreateCalculationViewModel)}.{nameof(CreateCalculationViewModel.AllocationLineId)}", ValidationMessages.CalculationAllocationLineRequired); } if (!ModelState.IsValid) { SpecificationName = specification.Name; SpecificationId = specificationId; FundingPeriodName = specification.FundingPeriod.Name; FundingPeriodId = specification.FundingPeriod.Id; return(await PopulateForm(specification)); } CalculationCreateModel calculation = _mapper.Map <CalculationCreateModel>(CreateCalculationViewModel); calculation.SpecificationId = specificationId; ValidatedApiResponse <Calculation> newCalculationResponse = await _specsClient.CreateCalculation(calculation); if (newCalculationResponse.StatusCode == HttpStatusCode.OK) { Calculation newCalculation = newCalculationResponse.Content; return(Redirect($"/specs/policies/{specificationId}?operationType=CalculationCreated&operationId={newCalculation.Id}")); } else if (newCalculationResponse.StatusCode == HttpStatusCode.BadRequest) { newCalculationResponse.AddValidationResultErrors(ModelState); SpecificationName = specification.Name; SpecificationId = specificationId; FundingPeriodName = specification.FundingPeriod.Name; FundingPeriodId = specification.FundingPeriod.Id; return(await PopulateForm(specification)); } else { throw new InvalidOperationException($"Unable to create calculation specifications. Status Code = {newCalculationResponse.StatusCode}"); } }
public async Task CreateAdditionalCalculation_GivenCalcSaves_ReturnsOKObjectResult() { //Arrange string cacheKey = $"{CacheKeys.CalculationsMetadataForSpecification}{SpecificationId}"; CalculationCreateModel model = CreateCalculationCreateModel(); Reference author = CreateAuthor(); ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .CreateDraftCalculation(Arg.Any <Calculation>()) .Returns(HttpStatusCode.OK); IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository(); ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository(); IJobManagement jobManagement = CreateJobManagement(); jobManagement .QueueJob(Arg.Any <JobCreateModel>()) .Returns(new Job { Id = "job-id-1" }); ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaryById(Arg.Is(SpecificationId)) .Returns(new ApiResponse <SpecificationSummary>( HttpStatusCode.OK, new SpecificationSummary { Id = SpecificationId, FundingPeriod = new FundingPeriod { Id = FundingPeriodId } } )); ILogger logger = CreateLogger(); ICacheProvider cacheProvider = CreateCacheProvider(); ICodeContextCache codeContextCache = Substitute.For <ICodeContextCache>(); IResultsApiClient resultsApiClient = CreateResultsApiClient(); CalculationService calculationService = CreateCalculationService( calculationsRepository: calculationsRepository, calculationVersionRepository: versionRepository, searchRepository: searchRepository, jobManagement: jobManagement, logger: logger, cacheProvider: cacheProvider, specificationsApiClient: specificationsApiClient, codeContextCache: codeContextCache, resultsApiClient: resultsApiClient); IEnumerable <CalculationIndex> indexedCalculations = null; await searchRepository .Index(Arg.Do <IEnumerable <CalculationIndex> >(m => indexedCalculations = m )); CalculationVersion savedCalculationVersion = null; await versionRepository .SaveVersion(Arg.Do <CalculationVersion>(m => savedCalculationVersion = m)); //Act IActionResult result = await calculationService.CreateAdditionalCalculation(SpecificationId, model, author, CorrelationId); //Assert result .Should() .BeAssignableTo <OkObjectResult>(); Calculation calculation = (result as OkObjectResult).Value as Calculation; await jobManagement .Received(1) .QueueJob(Arg.Is <JobCreateModel>( m => m.InvokerUserDisplayName == Username && m.InvokerUserId == UserId && m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructAllocationJob && m.Properties["specification-id"] == SpecificationId )); logger .Received(1) .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.CreateInstructAllocationJob}' created with id: 'job-id-1'")); await versionRepository .Received(1) .SaveVersion(Arg.Is <CalculationVersion>(m => m.PublishStatus == Models.Versioning.PublishStatus.Draft && m.Author.Id == UserId && m.Author.Name == Username && m.Date.Date == DateTimeOffset.Now.Date && m.Version == 1 && m.SourceCode == model.SourceCode && m.Description == model.Description && m.ValueType == model.ValueType && m.CalculationType == CalculationType.Additional && m.WasTemplateCalculation == false && m.Namespace == CalculationNamespace.Additional && m.Name == model.Name && m.SourceCodeName == new VisualBasicTypeIdentifierGenerator().GenerateIdentifier(model.Name) && m.DataType == CalculationDataType.Decimal )); await searchRepository .Received(1) .Index(Arg.Any <IEnumerable <CalculationIndex> >()); indexedCalculations .Should() .BeEquivalentTo(new List <CalculationIndex>() { new CalculationIndex() { CalculationType = "Additional", Description = "test description", FundingStreamId = "fs-1", FundingStreamName = model.FundingStreamName, Id = model.Id, Name = model.Name, Namespace = "Additional", SpecificationId = "spec-id-1", SpecificationName = "spec-id-1_specificationName", Status = "Draft", ValueType = "Currency", WasTemplateCalculation = false, LastUpdatedDate = savedCalculationVersion.Date, } }); //!string.IsNullOrWhiteSpace(m.First().Id) && //m.First().Name == model.Name && //m.First().SpecificationId == SpecificationId && //m.First().SpecificationName == model.SpecificationName && //m.First().ValueType == model.ValueType.ToString() && //m.First().CalculationType == CalculationType.Additional.ToString() && //m.First().Namespace == CalculationNamespace.Additional.ToString() && //m.First().FundingStreamId == model.FundingStreamId && //m.First().FundingStreamName == model.FundingStreamName && //m.First().WasTemplateCalculation == false && //m.First().Description == model.Description && //m.First().Status == calculation.Current.PublishStatus.ToString() await cacheProvider .Received(1) .RemoveAsync <List <CalculationMetadata> >(Arg.Is(cacheKey)); await codeContextCache .Received(1) .QueueCodeContextCacheUpdate(SpecificationId); }