public void QueueCsvGenerationMessages_GivenNoSpecificationSummariesFound_ThrowsRetriableException() { //Arrange string errorMessage = "No specification summaries found to generate calculation results csv."; IEnumerable <SpecModel.SpecificationSummary> specificationSummaries = Enumerable.Empty <SpecModel.SpecificationSummary>(); ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecModel.SpecificationSummary> >(HttpStatusCode.OK, specificationSummaries)); ILogger logger = CreateLogger(); ResultsService resultsService = CreateResultsService(logger, specificationsApiClient: specificationsApiClient); //Act Func <Task> test = async() => await resultsService.QueueCsvGenerationMessages(); //Assert test .Should() .ThrowExactly <RetriableException>() .Which .Message .Should() .Be(errorMessage); logger .Received(1) .Error(errorMessage); }
public void TestScenarioResultsService_PerformSearch_WhenRowCountsApiCallContentIsNull_ThenExceptionThrown() { // Arrange IScenarioSearchService searchService = CreateScenarioSearchService(); ISpecificationsApiClient specsApiClient = CreateSpecsApiClient(); ITestEngineApiClient testEngineApiClient = CreateTestEngineApiClient(); ILogger logger = CreateLogger(); TestScenarioResultRequestViewModel resultRequestViewModel = new TestScenarioResultRequestViewModel() { SearchTerm = "", PageNumber = 1, FundingPeriodId = null, SpecificationId = null, }; TestScenarioResultsService testScenarioResultsService = CreateService(searchService, specsApiClient, testEngineApiClient, logger: logger); searchService.PerformSearch(Arg.Any <SearchRequestViewModel>()) .Returns(new ScenarioSearchResultViewModel() { Scenarios = new List <ScenarioSearchResultItemViewModel>() { new ScenarioSearchResultItemViewModel() { Id = "s1", Name = "S1", }, new ScenarioSearchResultItemViewModel() { Id = "s2", Name = "S2", }, } }); List <SpecificationSummary> specifications = CreateSpecifications(); specsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecificationSummary> >(HttpStatusCode.OK, specifications)); testEngineApiClient .GetTestResultCounts(Arg.Any <TestScenarioResultCountsRequestModel>()) .Returns(new ApiResponse <IEnumerable <TestScenarioResultCounts> >(HttpStatusCode.OK, null)); // Act Func <Task> action = async() => await testScenarioResultsService.PerformSearch(resultRequestViewModel); // Assert action. Should() .ThrowExactly <InvalidOperationException>() .WithMessage("Row counts api request failed with null content"); logger .Received(1) .Warning(Arg.Is("Row counts api request failed with null content")); }
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 QueueCsvGenerationMessages_GivenSpecificationSummariesFoundButNoResults_DoesNotCreateNewMessages() { //Arrange IEnumerable <SpecModel.SpecificationSummary> specificationSummaries = new[] { new SpecModel.SpecificationSummary { Id = "spec-1" } }; ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient(); specificationsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecModel.SpecificationSummary> >(HttpStatusCode.OK, specificationSummaries)); ICalculationResultsRepository calculationResultsRepository = CreateResultsRepository(); calculationResultsRepository .ProviderHasResultsBySpecificationId( Arg.Is("spec-1")) .Returns(false); IBlobClient blobClient = CreateBlobClient(); blobClient .DoesBlobExistAsync($"{CalculationResultsReportFilePrefix}-spec-1", CalcsResultsContainerName) .Returns(false); ILogger logger = CreateLogger(); IJobManagement jobManagement = CreateJobManagement(); ResultsService resultsService = CreateResultsService( logger, specificationsApiClient: specificationsApiClient, resultsRepository: calculationResultsRepository, jobManagement: jobManagement, blobClient: blobClient); //Act await resultsService.QueueCsvGenerationMessages(); //Assert await jobManagement .DidNotReceive() .QueueJob(Arg.Any <JobCreateModel>()); logger .DidNotReceive() .Information($"Found new calculation results for specification id 'spec-1'"); }
public async Task TestScenarioResultsService_PerformSearch_WhenGetAllSpecificationsLookupIsNull_ThenExceptionThrown() { // Arrange IScenarioSearchService searchService = CreateScenarioSearchService(); ISpecificationsApiClient specsApiClient = CreateSpecsApiClient(); ITestEngineApiClient testEngineApiClient = CreateTestEngineApiClient(); ILogger logger = CreateLogger(); TestScenarioResultRequestViewModel resultRequestViewModel = new TestScenarioResultRequestViewModel() { SearchTerm = "", PageNumber = 1, FundingPeriodId = null, SpecificationId = null, }; TestScenarioResultsService testScenarioResultsService = CreateService(searchService, specsApiClient, testEngineApiClient, logger: logger); searchService.PerformSearch(Arg.Any <SearchRequestViewModel>()) .Returns(new ScenarioSearchResultViewModel()); List <SpecificationSummary> specifications = CreateSpecifications(); specsApiClient .GetSpecificationSummaries() .Returns((ApiResponse <IEnumerable <SpecificationSummary> >)null); // Act Func <Task> action = async() => await testScenarioResultsService.PerformSearch(resultRequestViewModel); // Assert action. Should() .ThrowExactly <InvalidOperationException>() .WithMessage("Specifications API Response was null"); logger .Received(1) .Warning(Arg.Is("Specifications API Response was null")); await specsApiClient .Received(1) .GetSpecificationSummaries(); }
public void TestScenarioResultsService_PerformSearch_WhenTestScenariosSearchResultsIsNull_ThenExceptionThrown() { // Arrange IScenarioSearchService searchService = CreateScenarioSearchService(); ISpecificationsApiClient specsApiClient = CreateSpecsApiClient(); ITestEngineApiClient testEngineApiClient = CreateTestEngineApiClient(); ILogger logger = CreateLogger(); string specificationId = "spec1"; TestScenarioResultsService testScenarioResultsService = CreateService(searchService, specsApiClient, testEngineApiClient, logger: logger); TestScenarioResultRequestViewModel resultRequestViewModel = new TestScenarioResultRequestViewModel() { SearchTerm = "", PageNumber = 1, FundingPeriodId = null, SpecificationId = specificationId, }; ScenarioSearchResultViewModel scenarioSearchResultViewModel = null; searchService.PerformSearch(Arg.Is <SearchRequestViewModel>(s => s.SearchTerm == resultRequestViewModel.SearchTerm)) .Returns(scenarioSearchResultViewModel); List <SpecificationSummary> specifications = CreateSpecifications(); specsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecificationSummary> >(HttpStatusCode.OK, specifications.AsEnumerable())); // Act Func <Task> action = async() => await testScenarioResultsService.PerformSearch(resultRequestViewModel); // Assert action. Should() .ThrowExactly <InvalidOperationException>() .WithMessage("Scenario Search Results response was null"); logger .Received(1) .Warning(Arg.Is <string>("Scenario Search Results response was null")); }
public async Task QueueCsvGenerationMessages() { Common.ApiClient.Models.ApiResponse <IEnumerable <SpecModel.SpecificationSummary> > specificationApiResponse = await _specificationsApiClientPolicy.ExecuteAsync(() => _specificationsApiClient.GetSpecificationSummaries()); if (!specificationApiResponse.StatusCode.IsSuccess() || specificationApiResponse.Content.IsNullOrEmpty()) { string errorMessage = "No specification summaries found to generate calculation results csv."; _logger.Error(errorMessage); throw new RetriableException(errorMessage); } IEnumerable <SpecModel.SpecificationSummary> specificationSummaries = specificationApiResponse.Content; Task[] queueCsvJobTasks = specificationSummaries.Select(_ => QueueCsvGenerationMessageIfNewCalculationResults(_.Id, _.Name)) .ToArray(); await TaskHelper.WhenAllAndThrow(queueCsvJobTasks); }
public void TestScenarioResultsService_PerformSearch_WhenGetAllSpecificationsLookupResponseIsNotOk_ThenExceptionThrown() { // Arrange IScenarioSearchService searchService = CreateScenarioSearchService(); ISpecificationsApiClient specsApiClient = CreateSpecsApiClient(); ITestEngineApiClient testEngineApiClient = CreateTestEngineApiClient(); ILogger logger = CreateLogger(); TestScenarioResultRequestViewModel resultRequestViewModel = new TestScenarioResultRequestViewModel() { SearchTerm = "", PageNumber = 1, FundingPeriodId = null, SpecificationId = null, }; TestScenarioResultsService testScenarioResultsService = CreateService(searchService, specsApiClient, testEngineApiClient, logger: logger); searchService.PerformSearch(Arg.Any <SearchRequestViewModel>()) .Returns(new ScenarioSearchResultViewModel()); specsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecificationSummary> >(HttpStatusCode.InternalServerError, null)); // Act Func <Task> action = async() => await testScenarioResultsService.PerformSearch(resultRequestViewModel); // Assert action. Should() .ThrowExactly <InvalidOperationException>() .WithMessage("Specifications API Response content did not return OK, but instead 'InternalServerError'"); logger .Received(1) .Warning(Arg.Is("Specifications API Response content did not return OK, but instead {specificationsApiResponse.StatusCode}"), Arg.Is(HttpStatusCode.InternalServerError)); }
public override async Task Process(Message message) { Guard.ArgumentNotNull(message, nameof(message)); Reference user = message.GetUserDetails(); _logger.Information($"{nameof(ReIndexCalculationResults)} initiated by: '{user.Name}'"); ApiResponse <IEnumerable <SpecModel.SpecificationSummary> > specificationsApiResponse = await _specificationsApiClientPolicy.ExecuteAsync(() => _specificationsApiClient.GetSpecificationSummaries()); if (specificationsApiResponse == null || !specificationsApiResponse.StatusCode.IsSuccess() || specificationsApiResponse.Content == null) { return; } IEnumerable <SpecModel.SpecificationSummary> specifications = specificationsApiResponse.Content; foreach (SpecModel.SpecificationSummary specification in specifications) { await _resultsRepositoryPolicy.ExecuteAsync(() => _resultsRepository.ProviderResultsBatchProcessing(specification.Id, async(x) => { IList <ProviderCalculationResultsIndex> results = new List <ProviderCalculationResultsIndex>(); foreach (ProviderResult providerResult in x) { if (!providerResult.CalculationResults.IsNullOrEmpty()) { ProviderCalculationResultsIndex calculationResult = new ProviderCalculationResultsIndex { SpecificationId = providerResult.SpecificationId, SpecificationName = specification?.Name, ProviderId = providerResult.Provider?.Id, ProviderName = providerResult.Provider?.Name, ProviderType = providerResult.Provider?.ProviderType, ProviderSubType = providerResult.Provider?.ProviderSubType, LocalAuthority = providerResult.Provider?.Authority, LastUpdatedDate = providerResult.CreatedAt, UKPRN = providerResult.Provider?.UKPRN, URN = providerResult.Provider?.URN, UPIN = providerResult.Provider?.UPIN, EstablishmentNumber = providerResult.Provider?.EstablishmentNumber, OpenDate = providerResult.Provider?.DateOpened, CalculationId = providerResult.CalculationResults.Select(m => m.Calculation.Id).ToArraySafe(), CalculationName = providerResult.CalculationResults.Select(m => m.Calculation.Name).ToArraySafe(), CalculationResult = providerResult.CalculationResults.Select(m => !string.IsNullOrEmpty(m.Value?.ToString()) ? m.Value.ToString() : "null").ToArraySafe() }; if (providerResult.FundingLineResults != null) { calculationResult.FundingLineName = providerResult.FundingLineResults?.Select(m => m.FundingLine.Name).ToArraySafe(); calculationResult.FundingLineFundingStreamId = providerResult.FundingLineResults?.Select(m => m.FundingLineFundingStreamId).ToArraySafe(); calculationResult.FundingLineId = providerResult.FundingLineResults?.Select(m => m.FundingLine.Id).ToArraySafe(); calculationResult.FundingLineResult = providerResult.FundingLineResults?.Select(m => !string.IsNullOrEmpty(m.Value?.ToString()) ? m.Value.ToString() : "null").ToArraySafe(); } if (_featureToggle.IsExceptionMessagesEnabled()) { calculationResult.CalculationException = providerResult.CalculationResults .Where(m => !string.IsNullOrWhiteSpace(m.ExceptionType)) .Select(e => e.Calculation.Id) .ToArraySafe(); calculationResult.CalculationExceptionType = providerResult.CalculationResults .Select(m => m.ExceptionType ?? string.Empty) .ToArraySafe(); calculationResult.CalculationExceptionMessage = providerResult.CalculationResults .Select(m => m.ExceptionMessage ?? string.Empty) .ToArraySafe(); if (providerResult.FundingLineResults != null) { calculationResult.FundingLineException = providerResult.FundingLineResults .Where(m => !string.IsNullOrWhiteSpace(m.ExceptionType)) .Select(e => e.FundingLine.Id) .ToArraySafe(); calculationResult.FundingLineExceptionType = providerResult.FundingLineResults .Select(m => m.ExceptionType ?? string.Empty) .ToArraySafe(); calculationResult.FundingLineExceptionMessage = providerResult.FundingLineResults .Select(m => m.ExceptionMessage ?? string.Empty) .ToArraySafe(); } } results.Add(calculationResult); } } IEnumerable <IndexError> errors = await _resultsSearchRepositoryPolicy.ExecuteAsync(() => _providerCalculationResultsSearchRepository.Index(results)); if (errors.Any()) { string errorMessage = $"Failed to index calculation provider result documents with errors: { string.Join(";", errors.Select(m => m.ErrorMessage)) }"; _logger.Error(errorMessage); throw new RetriableException(errorMessage); } })); } }
public async Task TestScenarioResultsService_PerformSearch_WhenTestScenariosExist_ThenResultsAreReturned() { // Arrange IScenarioSearchService searchService = CreateScenarioSearchService(); ISpecificationsApiClient specsApiClient = CreateSpecsApiClient(); ITestEngineApiClient testEngineApiClient = CreateTestEngineApiClient(); TestScenarioResultsService testScenarioResultsService = CreateService(searchService, specsApiClient, testEngineApiClient); TestScenarioResultRequestViewModel resultRequestViewModel = new TestScenarioResultRequestViewModel() { SearchTerm = "", PageNumber = 1, FundingPeriodId = null, SpecificationId = null, }; ScenarioSearchResultViewModel scenarioSearchResultViewModel = new ScenarioSearchResultViewModel() { CurrentPage = 1, TotalResults = 1, StartItemNumber = 1, EndItemNumber = 1, Scenarios = new List <ScenarioSearchResultItemViewModel>() { new ScenarioSearchResultItemViewModel() { Id = "ts1", Name = "Test Scenario 1", FundingPeriodName = "2018/2019", Status = "Passed", SpecificationName = "Specifcation 1", LastUpdatedDate = new DateTime(2018, 1, 5, 7, 8, 9), } } }; searchService.PerformSearch(Arg.Is <SearchRequestViewModel>(s => s.SearchTerm == resultRequestViewModel.SearchTerm)) .Returns(scenarioSearchResultViewModel); List <SpecificationSummary> specifications = CreateSpecifications(); specsApiClient .GetSpecificationSummaries() .Returns(new ApiResponse <IEnumerable <SpecificationSummary> >(HttpStatusCode.OK, specifications.AsEnumerable())); List <TestScenarioResultCounts> testScenarioResultCounts = new List <TestScenarioResultCounts>(); testScenarioResultCounts.Add(new TestScenarioResultCounts() { Passed = 5, Failed = 10, Ignored = 50, LastUpdatedDate = new DateTime(2018, 10, 5, 7, 8, 9), TestScenarioId = "ts1", TestScenarioName = "Test Scenario 1", }); testEngineApiClient .GetTestResultCounts(Arg.Any <TestScenarioResultCountsRequestModel>()) .Returns(new ApiResponse <IEnumerable <TestScenarioResultCounts> >(HttpStatusCode.OK, testScenarioResultCounts)); // Act TestScenarioResultViewModel resultViewModel = await testScenarioResultsService.PerformSearch(resultRequestViewModel); // Assert resultViewModel.Should().NotBeNull(); TestScenarioResultViewModel expectedResult = new TestScenarioResultViewModel() { CurrentPage = 1, EndItemNumber = 1, Facets = new List <SearchFacetViewModel>(), FundingPeriodId = null, Specifications = new List <ReferenceViewModel>() { new ReferenceViewModel("spec1", "Specification 1"), new ReferenceViewModel("spec2", "Specification 2"), new ReferenceViewModel("spec3", "Specification for 2018/2019"), }, StartItemNumber = 1, TotalResults = 1, TestResults = new List <TestScenarioResultItemViewModel>() { new TestScenarioResultItemViewModel() { Id = "ts1", Name = "Test Scenario 1", Passes = 5, Failures = 10, Ignored = 50, LastUpdatedDate = new DateTime(2018, 1, 5, 7, 8, 9), } } }; resultViewModel.Should().BeEquivalentTo(expectedResult); await specsApiClient .Received(1) .GetSpecificationSummaries(); }
public async Task <TestScenarioResultViewModel> PerformSearch(TestScenarioResultRequestViewModel request) { Guard.ArgumentNotNull(request, nameof(request)); SearchRequestViewModel searchRequest = new SearchRequestViewModel() { IncludeFacets = false, SearchTerm = request.SearchTerm, Filters = request.Filters, PageNumber = request.PageNumber, PageSize = 20, SearchMode = SearchMode.All }; if (searchRequest.Filters == null) { searchRequest.Filters = new Dictionary <string, string[]>(); } SetFilterValue(searchRequest, "specificationId", request.SpecificationId); SetFilterValue(searchRequest, "fundingPeriodId", request.FundingPeriodId); Task <ScenarioSearchResultViewModel> scenarioSearchResultsTask = _scenariosSearchService.PerformSearch(searchRequest); Task <ApiResponse <IEnumerable <SpecificationSummary> > > specificationsLookupTask; if (string.IsNullOrWhiteSpace(request.FundingPeriodId)) { specificationsLookupTask = _specsClient.GetSpecificationSummaries(); } else { specificationsLookupTask = _specsClient.GetSpecifications(request.FundingPeriodId); } await TaskHelper.WhenAllAndThrow(scenarioSearchResultsTask, specificationsLookupTask); ScenarioSearchResultViewModel scenarioSearchResults = scenarioSearchResultsTask.Result; if (scenarioSearchResults == null) { _logger.Warning("Scenario Search Results response was null"); throw new InvalidOperationException("Scenario Search Results response was null"); } ApiResponse <IEnumerable <SpecificationSummary> > specificationsApiResponse = specificationsLookupTask.Result; if (specificationsApiResponse == null) { _logger.Warning("Specifications API Response was null"); throw new InvalidOperationException("Specifications API Response was null"); } if (specificationsApiResponse.StatusCode != HttpStatusCode.OK) { _logger.Warning("Specifications API Response content did not return OK, but instead {specificationsApiResponse.StatusCode}", specificationsApiResponse.StatusCode); throw new InvalidOperationException($"Specifications API Response content did not return OK, but instead '{specificationsApiResponse.StatusCode}'"); } if (specificationsApiResponse.Content == null) { _logger.Warning("Specifications API Response content was null"); throw new InvalidOperationException("Specifications API Response content was null"); } IEnumerable <string> testScenarioIds = scenarioSearchResults.Scenarios.Select(s => s.Id); TestScenarioResultViewModel result = _mapper.Map <TestScenarioResultViewModel>(scenarioSearchResults); List <ReferenceViewModel> specifications = new List <ReferenceViewModel>(); foreach (SpecificationSummary specification in specificationsApiResponse.Content.OrderBy(s => s.Name)) { specifications.Add(new ReferenceViewModel(specification.Id, specification.Name)); } result.Specifications = specifications; if (testScenarioIds.Any()) { ApiResponse <IEnumerable <TestScenarioResultCounts> > rowCounts = await _testEngineClient.GetTestResultCounts(new TestScenarioResultCountsRequestModel() { TestScenarioIds = testScenarioIds, }); if (rowCounts == null) { _logger.Warning("Row counts api request failed with null response"); throw new InvalidOperationException($"Row counts api request failed with null response"); } if (rowCounts.StatusCode != HttpStatusCode.OK) { _logger.Warning("Row counts api request failed with status code: {rowCounts.StatusCode}", rowCounts.StatusCode); throw new InvalidOperationException($"Row counts api request failed with status code: {rowCounts.StatusCode}"); } if (rowCounts.Content == null) { _logger.Warning("Row counts api request failed with null content"); throw new InvalidOperationException($"Row counts api request failed with null content"); } foreach (TestScenarioResultItemViewModel vm in result.TestResults) { TestScenarioResultCounts counts = rowCounts.Content.Where(r => r.TestScenarioId == vm.Id).FirstOrDefault(); if (counts != null) { vm.Failures = counts.Failed; vm.Passes = counts.Passed; vm.Ignored = counts.Ignored; } } } return(result); }