async public Task GetCalculationCurrentVersion_GivencalculationWasFoundWithNoCurrent_ReturnsNotFound()
        {
            //Arrange
            Calculation calculation = new Calculation();

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository);

            //Act
            IActionResult result = await service.GetCalculationById(CalculationId);

            //Assert
            result
            .Should()
            .BeOfType <NotFoundResult>();

            logger
            .Received(1)
            .Information(Arg.Is($"A current calculation was not found for calculation id {CalculationId}"));
        }
        async public Task GetCalculationById_GivenCalculationIdWasProvidedButCalculationCouldNotBeFound_ReturnsNotFound()
        {
            //Arrange
            IQueryCollection queryStringValues = new QueryCollection(new Dictionary<string, StringValues>
            {
                { "calculationId", new StringValues(CalculationId) }

            });

            HttpRequest request = Substitute.For<HttpRequest>();
            request
                .Query
                .Returns(queryStringValues);

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();
            calculationsRepository
                .GetCalculationById(Arg.Is(CalculationId))
                .Returns((Calculation)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository);

            //Act
            IActionResult result = await service.GetCalculationById(request);

            //Assert
            result
                .Should()
                .BeOfType<NotFoundResult>();

            logger
                .Received(1)
                .Information(Arg.Is($"A calculation was not found for calculation id {CalculationId}"));
        }
        public async Task EditCalculationStatus_GivenCalculationWasNotFound_ReturnsNotFoundResult()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            ILogger logger = CreateLogger();

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns((Calculation)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: CalculationsRepository);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(CalculationId, CalculationEditStatusModel);

            //Arrange
            result
            .Should()
            .BeOfType <NotFoundObjectResult>()
            .Which
            .Value
            .Should()
            .Be("Calculation not found");

            logger
            .Received(1)
            .Warning(Arg.Is($"A calculation was not found for calculation id {CalculationId}"));
        }
        public async Task EditCalculationStatus_GivenCalculationWasNotFound_ReturnsNotFoundResult()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            string json = JsonConvert.SerializeObject(CalculationEditStatusModel);

            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>
            {
                { "calculationId", new StringValues(CalculationId) },
            });

            request
            .Query
            .Returns(queryStringValues);
            request
            .Body
            .Returns(stream);

            request
            .HttpContext
            .Returns(context);

            ILogger logger = CreateLogger();

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns((Calculation)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: CalculationsRepository);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(request);

            //Arrange
            result
            .Should()
            .BeOfType <NotFoundObjectResult>()
            .Which
            .Value
            .Should()
            .Be("Calculation not found");

            logger
            .Received(1)
            .Warning(Arg.Is($"A calculation was not found for calculation id {CalculationId}"));
        }
        public async Task EditCalculationStatus_GivenNewStatusButUpdatingDbReturnsBadRequest_ReturnsStatusCode400()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.BadRequest);

            SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary();

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary));


            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, specificationsApiClient: specificationsApiClient);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(CalculationId, CalculationEditStatusModel);

            //Arrange
            result
            .Should()
            .BeAssignableTo <StatusCodeResult>()
            .Which
            .StatusCode
            .Should()
            .Be(400);
        }
        public async Task EditCalculationStatus_GivenNewStatusButNoSpecSummaryFound_ReturnsPreConditionFailed()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, null));

            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, specificationsApiClient: specificationsApiClient);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(CalculationId, CalculationEditStatusModel);

            //Arrange
            result
            .Should()
            .BeAssignableTo <PreconditionFailedResult>()
            .Which
            .Value
            .Should()
            .Be("Specification not found");
        }
        public async Task EditCalculationStatus_GivenStatusHasNoChanges_DoesNotUpdateReturnsOkResult()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            calculation.Current.PublishStatus = PublishStatus.Approved;

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: CalculationsRepository);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(CalculationId, CalculationEditStatusModel);

            //Arrange
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .Be(calculation.Current);

            await
            CalculationsRepository
            .DidNotReceive()
            .UpdateCalculation(Arg.Any <Calculation>());
        }
        public async Task EditCalculationStatus_GivenNewStatusOfUpdated_UpdatesSearchReturnsOK()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Updated
            };

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            calculation.Current.PublishStatus = PublishStatus.Approved;

            CalculationVersion calculationVersion = calculation.Current.Clone() as CalculationVersion;

            calculationVersion.PublishStatus = PublishStatus.Updated;

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);


            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary()
            {
                Id             = calculation.SpecificationId,
                Name           = "spec name",
                FundingStreams = new[]
                {
                    new Reference(calculation.FundingStreamId, "funding stream name")
                }
            };

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary));

            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();

            versionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            Build build = new Build
            {
                SourceFiles = new List <SourceFile> {
                    new SourceFile()
                }
            };

            BuildProject buildProject = new BuildProject();

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(calculation.SpecificationId))
            .Returns(buildProject);

            ISourceCodeService sourceCodeService = CreateSourceCodeService();

            sourceCodeService
            .Compile(Arg.Any <BuildProject>(), Arg.Any <IEnumerable <Models.Calcs.Calculation> >(), Arg.Any <CompilerOptions>())
            .Returns(build);

            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, searchRepository: searchRepository,
                specificationsApiClient: specificationsApiClient, calculationVersionRepository: versionRepository,
                sourceCodeService: sourceCodeService, buildProjectsService: buildProjectsService);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(CalculationId, CalculationEditStatusModel);

            //Arrange
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeOfType <PublishStatusResultModel>()
            .Which
            .PublishStatus
            .Should()
            .Be(PublishStatus.Updated);

            calculation
            .Current
            .PublishStatus
            .Should()
            .Be(PublishStatus.Updated);
        }
        async public Task GetCalculationCurrentVersion_GivenCalculationExistsAndWasWasNotFoundInCache_ReturnsOK()
        {
            //Arrange
            const string   specificationId  = "specId";
            DateTimeOffset lastModifiedDate = DateTimeOffset.Now;

            Calculation calculation = new Calculation
            {
                SpecificationId = specificationId,
                Current         = new CalculationVersion
                {
                    Author        = new Reference(UserId, Username),
                    Date          = lastModifiedDate,
                    PublishStatus = PublishStatus.Draft,
                    SourceCode    = "source code",
                    Version       = 1
                },
                Name = "any name",
                Id   = CalculationId,
                CalculationSpecification = new Reference("any name", "any-id"),
                FundingPeriod            = new Reference("18/19", "2018/2019"),
                CalculationType          = CalculationType.Number
            };

            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "calculationId", new StringValues(CalculationId) }
            });

            HttpRequest request = Substitute.For <HttpRequest>();

            request
            .Query
            .Returns(queryStringValues);

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            ICacheProvider cacheProvider = CreateCacheProvider();

            cacheProvider
            .GetAsync <CalculationCurrentVersion>(Arg.Is($"{CacheKeys.CurrentCalculation}{CalculationId}"))
            .Returns((CalculationCurrentVersion)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository, cacheProvider: cacheProvider);

            //Act
            IActionResult result = await service.GetCalculationCurrentVersion(request);

            //Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should().BeEquivalentTo(new CalculationCurrentVersion
            {
                Author     = new Reference(UserId, Username),
                Date       = lastModifiedDate,
                SourceCode = "source code",
                Version    = 1,
                Name       = "any name",
                Id         = CalculationId,
                CalculationSpecification = new Reference("any name", "any-id"),
                FundingPeriodName        = "2018/2019",
                FundingPeriodId          = "18/19",
                CalculationType          = "Number",
                SpecificationId          = specificationId,
                PublishStatus            = PublishStatus.Draft,
            });

            await calculationsRepository
            .Received(1)
            .GetCalculationById(Arg.Is <string>(CalculationId));

            await cacheProvider
            .Received(1)
            .GetAsync <CalculationCurrentVersion>(Arg.Is($"{CacheKeys.CurrentCalculation}{CalculationId}"));
        }
예제 #10
0
 private async Task <Calculation> GetCalculation(string calculationId)
 => await _calculationsResilience.ExecuteAsync(() => _calculations.GetCalculationById(calculationId));
 private void AndMissingCalculation(string calculationId, Calculation calculation)
 {
     _calculationsRepository.GetCalculationById(calculationId)
     .Returns(calculation);
 }
예제 #12
0
        public async Task UpdateCalculationCodeOnCalculationChange_WhenNoCalculationsFoundReferencingCalculationToBeUpdated_ThenNoCalculationsUpdated()
        {
            // Arrange
            ICalculationsRepository  calculationsRepository           = CreateCalculationsRepository();
            ISpecificationsApiClient specificationsApiClient          = CreateSpecificationsApiClient();
            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();

            CalculationService service = CreateCalculationService(calculationsRepository: calculationsRepository,
                                                                  specificationsApiClient: specificationsApiClient,
                                                                  calculationVersionRepository: versionRepository);

            const string specificationId = "specId";
            const string calculationId   = "updatedCalc";

            CalculationVersionComparisonModel comparison = new CalculationVersionComparisonModel()
            {
                CalculationId   = calculationId,
                CurrentName     = "Calculation To Update",
                PreviousName    = "Original Name",
                SpecificationId = specificationId,
            };

            Reference user = new Reference("userId", "User Name");

            List <Calculation> calculations = new List <Calculation>()
            {
                new Calculation
                {
                    Id = calculationId,
                    SpecificationId = specificationId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = "Return 10",
                        Name            = "Calculation to Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description"
                    }
                },
                new Calculation
                {
                    Id = "referenceCalc",
                    SpecificationId = specificationId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = "Return 50",
                        Name            = "Calling Calculation To Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description",
                    }
                }
            };

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            calculationsRepository
            .GetCalculationById(Arg.Is(calculations[0].Id))
            .Returns(calculations[0]);

            SpecModel.SpecificationSummary specification = new SpecModel.SpecificationSummary()
            {
                Id   = specificationId,
                Name = "Specification Name",
            };

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specification));

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = "Return CalculationToUpdate()",
                Version    = 2
            };

            versionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            // Act
            IEnumerable <Calculation> updatedCalculations = await service.UpdateCalculationCodeOnCalculationChange(comparison, user);

            // Assert
            updatedCalculations
            .Should()
            .HaveCount(0);
        }
예제 #13
0
        public async Task UpdateCalculationCodeOnCalculationChange_WhenCalculationsFoundReferencingCalculationToBeUpdated_ThenSourceCodeUpdated()
        {
            // Arrange
            ICalculationsRepository  calculationsRepository           = CreateCalculationsRepository();
            ISpecificationsApiClient specificationsApiClient          = CreateSpecificationsApiClient();
            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();
            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();
            ISourceCodeService    sourceCodeService    = CreateSourceCodeService();

            CalculationService service = CreateCalculationService(calculationsRepository: calculationsRepository,
                                                                  specificationsApiClient: specificationsApiClient,
                                                                  calculationVersionRepository: versionRepository,
                                                                  buildProjectsService: buildProjectsService,
                                                                  sourceCodeService: sourceCodeService);

            const string specificationId    = "specId";
            const string calculationId      = "updatedCalc";
            const string originalCodeUpdate = @"Dim test as OriginalNameOptions? 
                                                OriginalNameOptions.enumName 
                                                Return Calculations.OriginalName()";
            const string newCodeUpdated     = @"Dim test as CalculationToUpdateOptions? 
                                                CalculationToUpdateOptions.enumName 
                                                Return Calculations.CalculationToUpdate()";
            const string originalCodeIgnore = "Return 10";
            const string fundingStreamId    = "fundingstreamid";

            CalculationVersionComparisonModel comparison = new CalculationVersionComparisonModel()
            {
                CalculationId       = calculationId,
                CurrentName         = "Calculation To Update",
                PreviousName        = "Original Name",
                SpecificationId     = specificationId,
                CalculationDataType = CalculationDataType.Enum,
                Namespace           = "Calculations"
            };

            Reference user = new Reference("userId", "User Name");

            List <Calculation> calculations = new List <Calculation>
            {
                new Calculation
                {
                    Id = calculationId,
                    SpecificationId = specificationId,
                    FundingStreamId = fundingStreamId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = originalCodeIgnore,
                        Name            = "Calculation to Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description",
                        DataType        = CalculationDataType.Enum
                    }
                },
                new Calculation
                {
                    Id = "referenceCalc",
                    SpecificationId = specificationId,
                    FundingStreamId = fundingStreamId,
                    Current         = new CalculationVersion
                    {
                        SourceCode      = originalCodeUpdate,
                        Name            = "Calling Calculation To Update",
                        CalculationType = CalculationType.Template,
                        Description     = "Calculation Description"
                    }
                }
            };

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            calculationsRepository
            .GetCalculationById(Arg.Is(calculations[0].Id))
            .Returns(calculations[0]);

            SpecModel.SpecificationSummary specification = new SpecModel.SpecificationSummary()
            {
                Id             = specificationId,
                Name           = "Specification Name",
                FundingStreams = new [] { new Reference(fundingStreamId, "fundingStreamName"), }
            };

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specification));

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = newCodeUpdated,
                Version    = 2
            };

            versionRepository
            .CreateVersion(Arg.Is <CalculationVersion>(_ => _.SourceCode == newCodeUpdated), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            buildProjectsService
            .GetBuildProjectForSpecificationId(specificationId)
            .Returns(new BuildProject());

            sourceCodeService
            .Compile(Arg.Any <BuildProject>(), Arg.Any <IEnumerable <Calculation> >(), Arg.Any <CompilerOptions>())
            .Returns(new Build());

            // Act
            IEnumerable <Calculation> updatedCalculations = await service.UpdateCalculationCodeOnCalculationChange(comparison, user);

            // Assert
            updatedCalculations
            .Should()
            .HaveCount(1);

            Calculation calculation = updatedCalculations.Single();

            calculation.Current.SourceCode
            .Should()
            .Be(newCodeUpdated);


            calculation.Current.Version
            .Should()
            .Be(2);

            calculation.Id
            .Should()
            .Be("referenceCalc");
        }
예제 #14
0
        public async Task UpdateCalculationCodeOnCalculationSpecificationChange_WhenNoCalculationsFoundReferencingCalculationToBeUpdated_ThenNoCalculationsUpdated()
        {
            // Arrange
            ICalculationsRepository  calculationsRepository           = CreateCalculationsRepository();
            ISpecificationRepository specificationRepository          = CreateSpecificationRepository();
            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();
            ICalculationCodeReferenceUpdate         calculationCodeReferenceUpdate = FakeCalculationCodeReferenceUpdate();

            CalculationService service = CreateCalculationService(calculationsRepository: calculationsRepository,
                                                                  specificationRepository: specificationRepository,
                                                                  calculationVersionRepository: versionRepository,
                                                                  calculationCodeReferenceUpdate: calculationCodeReferenceUpdate);

            const string specificationId = "specId";
            const string calculationId   = "updatedCalc";

            Models.Specs.CalculationVersionComparisonModel comparison = new Models.Specs.CalculationVersionComparisonModel()
            {
                CalculationId = calculationId,
                Current       = new Models.Specs.Calculation
                {
                    Id              = "calcSpec1",
                    Name            = "Calculation to update",
                    CalculationType = Models.Specs.CalculationType.Funding,
                },
                Previous = new Models.Specs.Calculation
                {
                    Id              = "calcSpec1",
                    Name            = "Original Name",
                    CalculationType = Models.Specs.CalculationType.Funding,
                },
                SpecificationId = specificationId,
            };

            Reference user = new Reference("userId", "User Name");

            List <Calculation> calculations = new List <Calculation>()
            {
                new Calculation
                {
                    Id                       = calculationId,
                    Name                     = "Calculation to Update",
                    SpecificationId          = specificationId,
                    FundingPeriod            = new Reference("fp1", "Funding Period"),
                    CalculationSpecification = new Reference("calcSpec1", "Calculation to Update"),
                    CalculationType          = CalculationType.Funding,
                    Description              = "Calculation Description",
                    BuildProjectId           = "bpC1",
                    Policies                 = new List <Reference>(),
                    Current                  = new CalculationVersion
                    {
                        SourceCode    = "Return 10",
                        DecimalPlaces = 6,
                    }
                },
                new Calculation
                {
                    Id                       = "referenceCalc",
                    Name                     = "Calling Calculation To Update",
                    SpecificationId          = specificationId,
                    FundingPeriod            = new Reference("fp1", "Funding Period"),
                    CalculationSpecification = new Reference("calcSpec1", "Calculation to Update"),
                    CalculationType          = CalculationType.Funding,
                    Description              = "Calculation Description",
                    BuildProjectId           = "bpC1",
                    Policies                 = new List <Reference>(),
                    Current                  = new CalculationVersion
                    {
                        SourceCode    = "Return 50",
                        DecimalPlaces = 6,
                    }
                }
            };

            calculationsRepository
            .GetCalculationsBySpecificationId(Arg.Is(specificationId))
            .Returns(calculations);

            calculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);

            calculationsRepository
            .GetCalculationById(Arg.Is(calculations[0].Id))
            .Returns(calculations[0]);

            Models.Specs.SpecificationSummary specification = new Models.Specs.SpecificationSummary()
            {
                Id   = specificationId,
                Name = "Specification Name",
            };

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(specificationId))
            .Returns(specification);

            CalculationVersion calculationVersion = new CalculationVersion
            {
                SourceCode = "Return CalculationToUpdate()",
                Version    = 2
            };

            versionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            // Act
            IEnumerable <Calculation> updatedCalculations = await service.UpdateCalculationCodeOnCalculationSpecificationChange(comparison, user);

            // Assert
            updatedCalculations
            .Should()
            .HaveCount(0);

            calculationCodeReferenceUpdate
            .Received(calculations.Count)
            .ReplaceSourceCodeReferences(Arg.Any <string>(),
                                         VisualBasicTypeGenerator.GenerateIdentifier(comparison.Previous.Name),
                                         VisualBasicTypeGenerator.GenerateIdentifier(comparison.Current.Name));

            foreach (Calculation calculation in calculations)
            {
                calculationCodeReferenceUpdate
                .Received(1)
                .ReplaceSourceCodeReferences(calculation.Current.SourceCode,
                                             VisualBasicTypeGenerator.GenerateIdentifier(comparison.Previous.Name),
                                             VisualBasicTypeGenerator.GenerateIdentifier(comparison.Current.Name));
            }
        }
        public async Task EditCalculationStatus_GivenCalculationIsApprovedButNewStatusIsDraft_UpdatesSearchReturnsOK()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Draft
            };

            string json = JsonConvert.SerializeObject(CalculationEditStatusModel);

            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>
            {
                { "calculationId", new StringValues(CalculationId) },
            });

            request
            .Query
            .Returns(queryStringValues);
            request
            .Body
            .Returns(stream);

            request
            .HttpContext
            .Returns(context);

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            calculation.Current.PublishStatus = PublishStatus.Approved;

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);


            Models.Specs.SpecificationSummary specificationSummary = new Models.Specs.SpecificationSummary();

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(specificationSummary);

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, searchRepository: searchRepository, specificationRepository: specificationRepository);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(request);

            //Arrange
            result
            .Should()
            .BeOfType <BadRequestObjectResult>()
            .Which
            .Value
            .Should()
            .Be("Publish status can't be changed to Draft from Updated or Approved");

            calculation
            .Current
            .PublishStatus
            .Should()
            .Be(PublishStatus.Approved);

            await
            searchRepository
            .Received(0)
            .Index(Arg.Any <IEnumerable <CalculationIndex> >());
        }
        public async Task EditCalculationStatus_GivenStatusHasntChanges_DoesNotUpdateReturnsOkResult()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            string json = JsonConvert.SerializeObject(CalculationEditStatusModel);

            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>
            {
                { "calculationId", new StringValues(CalculationId) },
            });

            request
            .Query
            .Returns(queryStringValues);
            request
            .Body
            .Returns(stream);

            request
            .HttpContext
            .Returns(context);

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            calculation.Current.PublishStatus = PublishStatus.Approved;

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: CalculationsRepository);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(request);

            //Arrange
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .Be(calculation.Current);

            await
            CalculationsRepository
            .DidNotReceive()
            .UpdateCalculation(Arg.Any <Calculation>());
        }
        public async Task EditCalculationStatus_GivenCalculationIsApprovedButNewStatusIsDraft_UpdatesSearchReturnsOK()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Draft
            };

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            calculation.Current.PublishStatus = PublishStatus.Approved;

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);


            SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary();

            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(new Common.ApiClient.Models.ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary));

            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, searchRepository: searchRepository, specificationsApiClient: specificationsApiClient);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(CalculationId, CalculationEditStatusModel);

            //Arrange
            result
            .Should()
            .BeOfType <BadRequestObjectResult>()
            .Which
            .Value
            .Should()
            .Be("Publish status can't be changed to Draft from Updated or Approved");

            calculation
            .Current
            .PublishStatus
            .Should()
            .Be(PublishStatus.Approved);

            await
            searchRepository
            .Received(0)
            .Index(Arg.Any <IEnumerable <CalculationIndex> >());
        }
        public async Task EditCalculationStatus_GivenNewStatusButUpdatingDbReturnsBadRequest_ReturnsStatusCode400()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Approved
            };

            string json = JsonConvert.SerializeObject(CalculationEditStatusModel);

            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>
            {
                { "calculationId", new StringValues(CalculationId) },
            });

            request
            .Query
            .Returns(queryStringValues);
            request
            .Body
            .Returns(stream);

            request
            .HttpContext
            .Returns(context);

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.BadRequest);

            Models.Specs.SpecificationSummary specificationSummary = new Models.Specs.SpecificationSummary();

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(specificationSummary);

            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, specificationRepository: specificationRepository);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(request);

            //Arrange
            result
            .Should()
            .BeAssignableTo <StatusCodeResult>()
            .Which
            .StatusCode
            .Should()
            .Be(400);
        }
        public async Task <IActionResult> HasCalculationResults(string calculationId)
        {
            Guard.IsNullOrWhiteSpace(calculationId, nameof(calculationId));

            Common.ApiClient.Calcs.Models.Calculation calculation = await _calculationsRepositoryPolicy.ExecuteAsync(() => _calculationRepository.GetCalculationById(calculationId));

            if (calculation == null)
            {
                _logger.Error($"Calculation could not be found for calculation id '{calculationId}'");

                return(new NotFoundObjectResult($"Calculation could not be found for calculation id '{calculationId}'"));
            }

            ProviderResult providerResult = await _resultsRepositoryPolicy.ExecuteAsync(() => _resultsRepository.GetSingleProviderResultBySpecificationId(calculation.SpecificationId));

            CalculationResult calculationResult = providerResult?
                                                  .CalculationResults?
                                                  .FirstOrDefault(m =>
                                                                  string.Equals(m.Calculation.Id,
                                                                                calculationId,
                                                                                StringComparison.InvariantCultureIgnoreCase));

            if (calculationResult != null)
            {
                return(new OkObjectResult(true));
            }

            return(new OkObjectResult(false));
        }
        public async Task EditCalculationStatus_GivenNewStatusOfUpdated_UpdatesSearchReturnsOK()
        {
            //Arrange
            EditStatusModel CalculationEditStatusModel = new EditStatusModel
            {
                PublishStatus = PublishStatus.Updated
            };

            string json = JsonConvert.SerializeObject(CalculationEditStatusModel);

            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>
            {
                { "calculationId", new StringValues(CalculationId) },
            });

            request
            .Query
            .Returns(queryStringValues);
            request
            .Body
            .Returns(stream);

            request
            .HttpContext
            .Returns(context);

            ILogger logger = CreateLogger();

            Calculation calculation = CreateCalculation();

            calculation.Current.PublishStatus = PublishStatus.Approved;

            CalculationVersion calculationVersion = calculation.Current.Clone() as CalculationVersion;

            calculationVersion.PublishStatus = PublishStatus.Updated;

            ICalculationsRepository CalculationsRepository = CreateCalculationsRepository();

            CalculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            CalculationsRepository
            .UpdateCalculation(Arg.Any <Calculation>())
            .Returns(HttpStatusCode.OK);


            ISearchRepository <CalculationIndex> searchRepository = CreateSearchRepository();

            Models.Specs.SpecificationSummary specificationSummary = new Models.Specs.SpecificationSummary();

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(calculation.SpecificationId))
            .Returns(specificationSummary);

            IVersionRepository <CalculationVersion> versionRepository = CreateCalculationVersionRepository();

            versionRepository
            .CreateVersion(Arg.Any <CalculationVersion>(), Arg.Any <CalculationVersion>())
            .Returns(calculationVersion);

            Build build = new Build
            {
                SourceFiles = new List <SourceFile> {
                    new SourceFile()
                }
            };

            BuildProject buildProject = new BuildProject();

            IBuildProjectsService buildProjectsService = CreateBuildProjectsService();

            buildProjectsService
            .GetBuildProjectForSpecificationId(Arg.Is(calculation.SpecificationId))
            .Returns(buildProject);

            ISourceCodeService sourceCodeService = CreateSourceCodeService();

            sourceCodeService
            .Compile(Arg.Any <BuildProject>(), Arg.Any <IEnumerable <Models.Calcs.Calculation> >(), Arg.Any <CompilerOptions>())
            .Returns(build);

            CalculationService service = CreateCalculationService(
                logger: logger, calculationsRepository: CalculationsRepository, searchRepository: searchRepository,
                specificationRepository: specificationRepository, calculationVersionRepository: versionRepository,
                sourceCodeService: sourceCodeService, buildProjectsService: buildProjectsService);

            //Act
            IActionResult result = await service.UpdateCalculationStatus(request);

            //Arrange
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeOfType <PublishStatusResultModel>()
            .Which
            .PublishStatus
            .Should()
            .Be(PublishStatus.Updated);

            calculation
            .Current
            .PublishStatus
            .Should()
            .Be(PublishStatus.Updated);

            await
            searchRepository
            .Received(1)
            .Index(Arg.Is <IEnumerable <CalculationIndex> >(m => m.First().Status == "Updated"));
        }
        async public Task GetCalculationCurrentVersion_GivenCalculationExistsAndWasWasNotFoundInCache_ReturnsOK()
        {
            //Arrange
            const string   specificationId  = "specId";
            DateTimeOffset lastModifiedDate = DateTimeOffset.Now;

            Calculation calculation = new Calculation
            {
                SpecificationId = specificationId,
                Current         = new CalculationVersion
                {
                    Author          = new Reference(UserId, Username),
                    Date            = lastModifiedDate,
                    PublishStatus   = PublishStatus.Draft,
                    SourceCode      = "source code",
                    Version         = 1,
                    Name            = "any name",
                    CalculationType = CalculationType.Template
                },

                Id = CalculationId
            };

            ILogger logger = CreateLogger();

            ICalculationsRepository calculationsRepository = CreateCalculationsRepository();

            calculationsRepository
            .GetCalculationById(Arg.Is(CalculationId))
            .Returns(calculation);

            ICacheProvider cacheProvider = CreateCacheProvider();

            cacheProvider
            .GetAsync <CalculationResponseModel>(Arg.Is($"{CacheKeys.CurrentCalculation}{CalculationId}"))
            .Returns((CalculationResponseModel)null);

            CalculationService service = CreateCalculationService(logger: logger, calculationsRepository: calculationsRepository, cacheProvider: cacheProvider);

            //Act
            IActionResult result = await service.GetCalculationById(CalculationId);

            //Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should().BeEquivalentTo(new CalculationResponseModel
            {
                Author          = new Reference(UserId, Username),
                LastUpdated     = lastModifiedDate,
                SourceCode      = "source code",
                Version         = 1,
                Name            = "any name",
                Id              = CalculationId,
                CalculationType = CalculationType.Template,
                SpecificationId = specificationId,
                PublishStatus   = PublishStatus.Draft,
            });

            await calculationsRepository
            .Received(1)
            .GetCalculationById(Arg.Is <string>(CalculationId));

            await cacheProvider
            .Received(1)
            .GetAsync <CalculationResponseModel>(Arg.Is($"{CacheKeys.CurrentCalculation}{CalculationId}"));
        }