public async Task <HttpStatusCode> UpdatePublishedRefreshedDate(string specificationId, DateTimeOffset publishedRefreshDate)
        {
            Guard.ArgumentNotNull(specificationId, nameof(specificationId));

            string url = $"{updatePublishedRefreshedDateUrl}{specificationId}";

            UpdatePublishedRefreshedDateModel model = new UpdatePublishedRefreshedDateModel
            {
                PublishedResultsRefreshedAt = publishedRefreshDate
            };

            return(await _apiClient.PostAsync(url, model));
        }
        public async Task UpdatePublishedRefreshedDate_WhenUpdateIsUnsuccessful_ThenInternalServerErrorReturned()
        {
            // Arrange
            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "specificationId", new StringValues(SpecificationId) }
            });

            Specification specification = new Specification
            {
                Id   = SpecificationId,
                Name = "spec1"
            };

            UpdatePublishedRefreshedDateModel updateModel = new UpdatePublishedRefreshedDateModel
            {
                PublishedResultsRefreshedAt = DateTimeOffset.Now.AddHours(-1)
            };
            string json = JsonConvert.SerializeObject(updateModel);

            byte[]       byteArray = Encoding.UTF8.GetBytes(json);
            MemoryStream stream    = new MemoryStream(byteArray);

            HttpContext context = Substitute.For <HttpContext>();

            ISpecificationsRepository specsRepo = CreateSpecificationsRepository();

            specsRepo.GetSpecificationById(Arg.Is(SpecificationId)).Returns(specification);
            specsRepo.UpdateSpecification(Arg.Is(specification)).Returns(HttpStatusCode.InternalServerError);

            SpecificationsService specsService = CreateService(specificationsRepository: specsRepo);

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

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

            // Act
            IActionResult result = await specsService.UpdatePublishedRefreshedDate(request);

            // Assert
            result.Should().BeOfType <InternalServerErrorResult>().Which.Value.Should().Be($"Failed to set PublishedResultsRefreshedAt on specification for id: {SpecificationId} to value: {updateModel.PublishedResultsRefreshedAt.ToString()}");
        }
        public async Task UpdatePublishedRefreshedDate_WhenUnknownSpecificationIdProvided_ThenNotFoundResultReturned()
        {
            // Arrange
            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "specificationId", new StringValues("-1") }
            });

            UpdatePublishedRefreshedDateModel updateModel = new UpdatePublishedRefreshedDateModel
            {
                PublishedResultsRefreshedAt = DateTimeOffset.Now.AddHours(-1)
            };
            string json = JsonConvert.SerializeObject(updateModel);

            byte[]       byteArray = Encoding.UTF8.GetBytes(json);
            MemoryStream stream    = new MemoryStream(byteArray);

            HttpContext context = Substitute.For <HttpContext>();

            ISpecificationsRepository specsRepo = CreateSpecificationsRepository();

            specsRepo.GetSpecificationById(Arg.Is("-1")).Returns((Specification)null);

            SpecificationsService specsService = CreateService(specificationsRepository: specsRepo);

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

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

            // Act
            IActionResult result = await specsService.UpdatePublishedRefreshedDate(request);

            // Assert
            result.Should().BeOfType <NotFoundObjectResult>().Which.Value.Should().Be("Specification not found");
        }
        public async Task UpdatePublishedRefreshedDate_WhenUpdateIsSuccessful_ThenOkResultReturned()
        {
            // Arrange
            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "specificationId", new StringValues(SpecificationId) }
            });

            Specification specification = new Specification
            {
                Id      = SpecificationId,
                Name    = "spec1",
                Current = new SpecificationVersion
                {
                    Description   = "test",
                    FundingPeriod = new Reference {
                        Id = "fp1", Name = "funding period 1"
                    },
                    FundingStreams = new List <FundingStream>
                    {
                        new FundingStream {
                            Id = "fs1", Name = "funding stream 1"
                        }
                    },
                    PublishStatus = Models.Versioning.PublishStatus.Draft
                }
            };

            UpdatePublishedRefreshedDateModel updateModel = new UpdatePublishedRefreshedDateModel
            {
                PublishedResultsRefreshedAt = DateTimeOffset.Now.AddHours(-1)
            };
            string json = JsonConvert.SerializeObject(updateModel);

            byte[]       byteArray = Encoding.UTF8.GetBytes(json);
            MemoryStream stream    = new MemoryStream(byteArray);

            HttpContext context = Substitute.For <HttpContext>();

            ISpecificationsRepository specsRepo = CreateSpecificationsRepository();

            specsRepo.GetSpecificationById(Arg.Is(SpecificationId)).Returns(specification);
            specsRepo.UpdateSpecification(Arg.Is(specification)).Returns(HttpStatusCode.OK);

            ISearchRepository <SpecificationIndex> searchRepo = CreateSearchRepository();

            searchRepo.Index(Arg.Any <IEnumerable <SpecificationIndex> >()).Returns(Enumerable.Empty <IndexError>());

            ICacheProvider cacheProvider = CreateCacheProvider();

            SpecificationsService specsService = CreateService(specificationsRepository: specsRepo, searchRepository: searchRepo, cacheProvider: cacheProvider);

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

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

            // Act
            IActionResult result = await specsService.UpdatePublishedRefreshedDate(request);

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

            await specsRepo.Received(1).UpdateSpecification(Arg.Is <Specification>(s => s.PublishedResultsRefreshedAt == updateModel.PublishedResultsRefreshedAt));

            await searchRepo.Received(1).Index(Arg.Is <IEnumerable <SpecificationIndex> >(l => l.Count() == 1 && l.First().PublishedResultsRefreshedAt == updateModel.PublishedResultsRefreshedAt));

            await cacheProvider
            .Received(1)
            .RemoveAsync <SpecificationSummary>($"{CacheKeys.SpecificationSummaryById}{specification.Id}");

            await cacheProvider
            .Received(1)
            .RemoveAsync <SpecificationCurrentVersion>($"{CacheKeys.SpecificationCurrentVersionById}{specification.Id}");
        }
        public async Task UpdatePublishedRefreshedDate_WhenUpdateIndexIsUnsuccessful_ThenInternalServerErrorReturned()
        {
            // Arrange
            IQueryCollection queryStringValues = new QueryCollection(new Dictionary <string, StringValues>
            {
                { "specificationId", new StringValues(SpecificationId) }
            });

            Specification specification = new Specification
            {
                Id      = SpecificationId,
                Name    = "spec1",
                Current = new SpecificationVersion
                {
                    Description   = "test",
                    FundingPeriod = new Reference {
                        Id = "fp1", Name = "funding period 1"
                    },
                    FundingStreams = new List <FundingStream>
                    {
                        new FundingStream {
                            Id = "fs1", Name = "funding stream 1"
                        }
                    },
                    PublishStatus = Models.Versioning.PublishStatus.Draft
                }
            };

            UpdatePublishedRefreshedDateModel updateModel = new UpdatePublishedRefreshedDateModel
            {
                PublishedResultsRefreshedAt = DateTimeOffset.Now.AddHours(-1)
            };
            string json = JsonConvert.SerializeObject(updateModel);

            byte[]       byteArray = Encoding.UTF8.GetBytes(json);
            MemoryStream stream    = new MemoryStream(byteArray);

            HttpContext context = Substitute.For <HttpContext>();

            ISpecificationsRepository specsRepo = CreateSpecificationsRepository();

            specsRepo.GetSpecificationById(Arg.Is(SpecificationId)).Returns(specification);
            specsRepo.UpdateSpecification(Arg.Is(specification)).Returns(HttpStatusCode.OK);

            ISearchRepository <SpecificationIndex> searchRepo = CreateSearchRepository();

            searchRepo.Index(Arg.Any <IEnumerable <SpecificationIndex> >()).Returns(new List <IndexError> {
                new IndexError {
                    ErrorMessage = "an error", Key = SpecificationId
                }
            });

            SpecificationsService specsService = CreateService(specificationsRepository: specsRepo, searchRepository: searchRepo);

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

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

            // Act
            IActionResult result = await specsService.UpdatePublishedRefreshedDate(request);

            // Assert
            result.Should().BeOfType <InternalServerErrorResult>().Which.Value.Should().Be($"Failed to index search for specification {SpecificationId} with the following errors: an error");
        }