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();
        }
Пример #2
0
        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);
        }
Пример #5
0
        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}'");
        }
Пример #7
0
        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}");
            }
        }
Пример #8
0
        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));
        }
Пример #9
0
        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();
        }
Пример #12
0
        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}'");
            }
        }
Пример #13
0
        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();
        }
Пример #15
0
        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>();
        }