Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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"));
        }
Ejemplo n.º 3
0
        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}'");
        }
Ejemplo n.º 4
0
        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'");
        }
Ejemplo n.º 5
0
        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();
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 8
0
        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);
                    }
                }));
            }
        }
Ejemplo n.º 10
0
        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);
        }