public void CheckPrerequisitesForApproveSpecificationToBeApproved_WhenPreReqsValidationErrors_ThrowsException() { string specificationId = NewRandomString(); GivenTheMessageHasTheSpecificationId(specificationId); AndTheMessageIsOtherwiseValid(); AndCalculationEngineApproveSpecificationRunning(specificationId); AndRetrieveJobAndCheckCanBeProcessedSuccessfully(_ => _.WithJobId(_jobId)); Func <Task> invocation = WhenAllProvidersResultsAreApproved; invocation .Should() .Throw <Exception>() .And .Message .Should() .Be($"Specification with id: '{specificationId} has prerequisites which aren't complete."); string[] prereqValidationErrors = new string[] { $"{JobConstants.DefinitionNames.RefreshFundingJob} is still running" }; _logger.Received(1) .Error($"{JobConstants.DefinitionNames.RefreshFundingJob} is still running"); _jobManagement .Received(1) .UpdateJobStatus(_jobId, 0, false, string.Join(", ", prereqValidationErrors)); }
public void CheckPrerequisitesForAllProvidersToBePublished_WhenPreReqsValidationErrors_ThrowsException() { GivenJobCanBeProcessed(); AndSpecification(); AndCalculationResultsBySpecificationId(); AndTemplateMetadataContents(); AndPublishedProviders(); AndCalculationEngineRunningForPublishAllProviders(); Func <Task> invocation = WhenPublishAllProvidersMessageReceivedWithJobId; invocation .Should() .Throw <Exception>() .And .Message .Should() .Be($"Specification with id: '{SpecificationId} has prerequisites which aren't complete."); string[] prereqValidationErrors = new string[] { $"{JobConstants.DefinitionNames.RefreshFundingJob} is still running" }; _jobManagement .Received(1) .UpdateJobStatus(JobId, 0, false, string.Join(", ", prereqValidationErrors)); }
public async Task QueueCsvGenerationMessages_GivenSpecificationSummariesFoundAndHasNewResults_CreatesNewMessage() { //Arrange IEnumerable <SpecModel.SpecificationSummary> specificationSummaries = new[] { new SpecModel.SpecificationSummary { Id = specificationId } }; ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecModel.SpecificationSummary> >(HttpStatusCode.OK, specificationSummaries)); ICalculationResultsRepository calculationResultsRepository = CreateResultsRepository(); calculationResultsRepository .CheckHasNewResultsForSpecificationIdAndTime( Arg.Is(specificationId), Arg.Any <DateTimeOffset>()) .Returns(true); ILogger logger = CreateLogger(); IJobManagement jobManagement = CreateJobManagement(); IBlobClient blobClient = CreateBlobClient(); blobClient .DoesBlobExistAsync($"{CalculationResultsReportFilePrefix}-{specificationId}", CalcsResultsContainerName) .Returns(true); ResultsService resultsService = CreateResultsService( logger, specificationsApiClient: specificationsApiClient, resultsRepository: calculationResultsRepository, jobManagement: jobManagement, blobClient: blobClient); //Act await resultsService.QueueCsvGenerationMessages(); //Assert await jobManagement .Received(1) .QueueJob( Arg.Is <JobCreateModel>(_ => _.JobDefinitionId == JobConstants.DefinitionNames.GenerateCalcCsvResultsJob && _.Properties["specification-id"] == specificationId)); logger .Received() .Information($"Found new calculation results for specification id '{specificationId}'"); }
public async Task ReIndexesAllPublishedProvidersIfJobCanBeProcessed() { Message message = new Message(); message.UserProperties.Add("jobId", JobId); _jobManagement.RetrieveJobAndCheckCanBeProcessed(JobId) .Returns(NewJobViewModel()); await _service.Run(message); await _jobManagement .Received(1) .UpdateJobStatus(JobId, 0, 0, null, null); await _publishedFundingRepository .Received(1) .AllPublishedProviderBatchProcessing(Arg.Any <Func <List <PublishedProvider>, Task> >(), Arg.Is(1000), null); await _jobManagement .Received(1) .UpdateJobStatus(JobId, 0, 0, true, null); }
public async Task RegenerateProviderSourceDatasets_GivenSpecificationId_ThenCallJobServiceToProcess() { // Arrange IDatasetRepository datasetRepository = CreateDatasetsRepository(); datasetRepository .GetDefinitionSpecificationRelationshipsByQuery(Arg.Any <Expression <Func <DocumentEntity <DefinitionSpecificationRelationship>, bool> > >()) .Returns(new List <DefinitionSpecificationRelationship> { new DefinitionSpecificationRelationship { DatasetVersion = new DatasetRelationshipVersion { Id = "DSRV1", Version = 1 }, Specification = new Common.Models.Reference { Id = SpecificationId, Name = "SpecAbc" } } }); datasetRepository .GetDatasetsByQuery(Arg.Any <Expression <Func <DocumentEntity <Dataset>, bool> > >()) .Returns(new List <Dataset> { new Dataset { Id = "DS1" } }); IJobManagement jobManagement = CreateJobManagement(); DatasetService service = CreateDatasetService(datasetRepository: datasetRepository, jobManagement: jobManagement); // Act await service.RegenerateProviderSourceDatasets(SpecificationId, null, null); // Assert await jobManagement .Received(1) .QueueJob(Arg.Is <JobCreateModel>(j => j.JobDefinitionId == "MapDatasetJob" && j.Properties.ContainsKey("session-id") && j.Properties["session-id"] == SpecificationId)); }
public async Task ReIndex_CreatesReIndexPublishedProviderJob() { Reference user = NewUser(_ => _.WithId(NewRandomString()) .WithName(NewRandomString())); string correlationId = NewRandomString(); IActionResult result = await WhenThePublishedProviderVersionsAreReIndexed(user, correlationId); result .Should() .BeOfType <NoContentResult>(); await _jobManagement .Received(1) .QueueJob(Arg.Is <JobCreateModel>(_ => _.CorrelationId == correlationId && _.InvokerUserId == user.Id && _.InvokerUserDisplayName == user.Name && _.JobDefinitionId == JobConstants.DefinitionNames.ReIndexPublishedProvidersJob)); }
public async Task SaveProviderResults_WhenExcludedResultsAndIsNewProviderCalculationResultsIndexEnabled_ThenResultsSavedToCosmosSavesNull() { // Arrange ICosmosRepository cosmosRepository = CreateCosmosRepository(); IJobManagement jobManagement = CreateJobManagement(); ProviderResultsRepository repo = CreateProviderResultsRepository( cosmosRepository, jobManagement: jobManagement); SpecificationSummary specificationSummary = new SpecificationSummary { Name = "Specification 1", FundingPeriod = new Reference() }; IEnumerable <ProviderResult> results = new List <ProviderResult> { new ProviderResult { CalculationResults = new List <CalculationResult> { new CalculationResult { Calculation = new Reference { Id = "calc1", Name = "calculation one" }, CalculationType = Models.Calcs.CalculationType.Template, Value = null } }, FundingLineResults = new List <FundingLineResult> { new FundingLineResult { FundingLine = new Reference { Id = "fl1", Name = "funding line one" }, FundingLineFundingStreamId = "FS1", Value = null } }, Id = Guid.NewGuid().ToString(), Provider = new ProviderSummary { Id = "prov1", Name = "Provider 1", ProviderType = "TYpe 1", ProviderSubType = "Sub type 1", Authority = "Authority", UKPRN = "ukprn123", URN = "urn123", EstablishmentNumber = "en123", UPIN = "upin123", DateOpened = DateTime.Now }, SpecificationId = "spec1" } }; // Act await repo.SaveProviderResults(results, specificationSummary, 1, 1, _user, _correlationId, _jobId); // Assert await cosmosRepository.Received(1).UpsertAsync <ProviderResult>( Arg.Any <ProviderResult>(), Arg.Any <string>(), Arg.Is <bool>(false), Arg.Is <bool>(false)); await jobManagement.Received(1).QueueJob(Arg.Is <JobCreateModel>(_ => _.JobDefinitionId == JobConstants.DefinitionNames.SearchIndexWriterJob && _.ParentJobId == _jobId && _.Properties["specification-id"] == specificationSummary.GetSpecificationId() && _.Properties["specification-name"] == specificationSummary.Name && _.Properties["index-writer-type"] == SearchIndexWriterTypes.ProviderCalculationResultsIndexWriter && _.MessageBody == JsonConvert.SerializeObject(results.Select(x => x.Provider.Id)))); }
public async Task SaveProviderResults_WhenResultsAndIsNewProviderCalculationResultsIndexEnabled_ThenQueueSearchIndexWriterJob() { // Arrange ICosmosRepository cosmosRepository = CreateCosmosRepository(); IJobManagement jobManagement = CreateJobManagement(); ProviderResultsRepository repo = CreateProviderResultsRepository( cosmosRepository, jobManagement: jobManagement); SpecificationSummary specificationSummary = new SpecificationSummary { Id = NewRandomString(), Name = NewRandomString(), FundingPeriod = new Reference { Id = NewRandomString() }, LastEditedDate = new RandomDateTime(), FundingStreams = new[] { new Reference { Id = NewRandomString() }, new Reference { Id = NewRandomString() }, new Reference { Id = NewRandomString() } } }; IEnumerable <ProviderResult> results = new List <ProviderResult> { new ProviderResult { CalculationResults = new List <CalculationResult> { new CalculationResult { Calculation = new Reference { Id = "calc1", Name = "calculation one" }, CalculationType = CalculationType.Template, Value = 1112.3M } }, FundingLineResults = new List <FundingLineResult> { new FundingLineResult { FundingLine = new Reference { Id = "fl1", Name = "funding line one" }, FundingLineFundingStreamId = "FS1", Value = 112.3M } }, Id = Guid.NewGuid().ToString(), Provider = new ProviderSummary { Id = "prov1", Name = "Provider 1", ProviderType = "TYpe 1", ProviderSubType = "Sub type 1", Authority = "Authority", UKPRN = "ukprn123", URN = "urn123", EstablishmentNumber = "en123", UPIN = "upin123", DateOpened = DateTime.Now }, SpecificationId = "spec1" } }; // Act await repo.SaveProviderResults(results, specificationSummary, 1, 1, _user, _correlationId, _jobId); // Assert await jobManagement.Received(1).QueueJob(Arg.Is <JobCreateModel>(_ => _.JobDefinitionId == JobConstants.DefinitionNames.SearchIndexWriterJob && _.Properties["specification-id"] == specificationSummary.GetSpecificationId() && _.Properties["specification-name"] == specificationSummary.Name && _.Properties["index-writer-type"] == SearchIndexWriterTypes.ProviderCalculationResultsIndexWriter && _.ParentJobId == _jobId && _.MessageBody == JsonConvert.SerializeObject(results.Select(x => x.Provider.Id)))); await _resultsApiClient.Received(1) .QueueMergeSpecificationInformationJob(Arg.Is <MergeSpecificationInformationRequest>(_ => _.SpecificationInformation.Id == specificationSummary.Id && _.SpecificationInformation.Name == specificationSummary.Name && _.SpecificationInformation.LastEditDate == specificationSummary.LastEditedDate && _.SpecificationInformation.FundingStreamIds.SequenceEqual(specificationSummary.FundingStreams.Select(fs => fs.Id).ToArray()) && _.SpecificationInformation.FundingPeriodId == specificationSummary.FundingPeriod.Id && _.ProviderIds.SequenceEqual(new[] { "prov1" }))); }
private async Task ThenTheDeleteSpecificationJobIsCreated(Expression <Predicate <JobCreateModel> > expectedJob) { await _jobs.Received(1).QueueJob( Arg.Is(expectedJob)); }
private async Task ThenProviderSnapshotDataLoadJobWasCreated(Expression <Predicate <JobCreateModel> > expectedJob) { await _jobManagement.Received(1).QueueJob( Arg.Is(expectedJob)); }
private async Task ThenTheAssignTemplateCalculationJobWasCreated(Expression <Predicate <JobCreateModel> > expectedJob) { await _jobs.Received(1).QueueJob( Arg.Is(expectedJob)); }
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); }
private async Task ThenTheApproveAllCalculationsJobIsCreated(Expression <Predicate <JobCreateModel> > expectedJob) { await _jobs.Received(1).QueueJob( Arg.Is(expectedJob)); }
private void AndTheJobWasAddedForTheJobId(Expression <Predicate <JobLogUpdateModel> > jobLogMatching, int times = 1) { _jobs .Received(times) .AddJobLog(_jobId, Arg.Is(jobLogMatching)); }
public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameButCreatingJobReturnsNull_LogsError() { // Arrange const string specificationId = "spec-id"; SpecificationVersionComparisonModel specificationVersionComparison = new SpecificationVersionComparisonModel() { Id = specificationId, Current = new SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Name = "any-name" }, Previous = new SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" } } }; string json = JsonConvert.SerializeObject(specificationVersionComparison); Message message = new Message(Encoding.UTF8.GetBytes(json)); message.UserProperties.Add("user-id", UserId); message.UserProperties.Add("user-name", Username); ILogger logger = CreateLogger(); IEnumerable <Calculation> calcs = new[] { new Calculation { SpecificationId = "spec-id", Id = "any-id", Current = new CalculationVersion { Author = new Reference(UserId, Username), Date = DateTimeOffset.Now, PublishStatus = PublishStatus.Draft, SourceCode = "source code", Version = 1, Name = "any name", CalculationType = CalculationType.Template } } }; BuildProject buildProject = new BuildProject { Id = "build-project-1", SpecificationId = specificationId }; ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .GetCalculationsBySpecificationId(Arg.Is(specificationId)) .Returns(calcs); IBuildProjectsService buildProjectsService = CreateBuildProjectsService(); buildProjectsService .GetBuildProjectForSpecificationId(Arg.Is(specificationId)) .Returns(buildProject); IJobManagement jobManagement = CreateJobManagement(); jobManagement .QueueJob(Arg.Any <JobCreateModel>()) .Returns((Job)null); CalculationService service = CreateCalculationService( calculationsRepository, logger, buildProjectsService: buildProjectsService, jobManagement: jobManagement); // Act Func <Task> test = async() => await service.Run(message); // Assert test .Should() .ThrowExactly <RetriableException>() .Which .Message .Should() .Be($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'"); 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 && m.Trigger.EntityId == specificationId && m.Trigger.EntityType == "Specification" && m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'" )); logger .Received(1) .Error(Arg.Is($"Failed to create job: '{JobConstants.DefinitionNames.CreateInstructAllocationJob} for specification id '{specificationId}'")); }
public async Task UpdateCalculationsForSpecification_GivenModelHasChangedPolicyNameAndSourceCodeContainsCalculationAggregate_SavesChangesEnsuresGenerateAggregationsJobCreated() { // Arrange const string specificationId = "spec-id"; SpecificationVersionComparisonModel specificationVersionComparison = new SpecificationVersionComparisonModel() { Id = specificationId, Current = new SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" }, Name = "any-name" }, Previous = new SpecificationVersion { FundingPeriod = new Reference { Id = "fp1" } } }; string json = JsonConvert.SerializeObject(specificationVersionComparison); Message message = new Message(Encoding.UTF8.GetBytes(json)); message.UserProperties.Add("user-id", UserId); message.UserProperties.Add("user-name", Username); ILogger logger = CreateLogger(); IEnumerable <Calculation> calcs = new[] { new Calculation { SpecificationId = "spec-id", Id = "any-id", Current = new CalculationVersion { Author = new Reference(UserId, Username), Date = DateTimeOffset.Now, PublishStatus = PublishStatus.Draft, SourceCode = "return Min(calc1)", Version = 1, Name = "any name", CalculationType = CalculationType.Template } } }; BuildProject buildProject = new BuildProject { Id = "build-project-1", SpecificationId = specificationId }; ICalculationsRepository calculationsRepository = CreateCalculationsRepository(); calculationsRepository .GetCalculationsBySpecificationId(Arg.Is(specificationId)) .Returns(calcs); IBuildProjectsService buildProjectsService = CreateBuildProjectsService(); buildProjectsService .GetBuildProjectForSpecificationId(Arg.Is(specificationId)) .Returns(buildProject); IJobManagement jobManagement = CreateJobManagement(); jobManagement .QueueJob(Arg.Any <JobCreateModel>()) .Returns(new Job { Id = "job-id-1", JobDefinitionId = JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob }); CalculationService service = CreateCalculationService( calculationsRepository, logger, buildProjectsService: buildProjectsService, jobManagement: jobManagement); // Act await service.Run(message); // Assert await jobManagement .Received(1) .QueueJob(Arg.Is <JobCreateModel>( m => m.InvokerUserDisplayName == Username && m.InvokerUserId == UserId && m.JobDefinitionId == JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob && m.Properties["specification-id"] == specificationId && m.Trigger.EntityId == specificationId && m.Trigger.EntityType == "Specification" && m.Trigger.Message == $"Updating calculations for specification: '{specificationId}'" )); logger .Received(1) .Information(Arg.Is($"New job of type '{JobConstants.DefinitionNames.CreateInstructGenerateAggregationsAllocationJob}' created with id: 'job-id-1'")); }
private void AndTheJobsStartWasLogged() { _jobManagement .Received(1) .UpdateJobStatus(_jobId, 0, 0, null, null); }