public void SpecificationSearchModelToSpecificationIndexMapping() { SpecificationSearchModel specificationSearchModel = NewSpecificationSearchModel(_ => _.WithFundingPeriod(NewFundingPeriod()) .WithDataDefinitionRelationshipIds(NewRandomString(), NewRandomString()) .WithFundingStreams(NewFundingStream(), NewFundingStream())); SpecificationIndex searchIndex = WhenTheSourceItemsAreMapped(specificationSearchModel).Single(); searchIndex .Should() .BeEquivalentTo(new SpecificationIndex { Id = specificationSearchModel.Id, Name = specificationSearchModel.Name, FundingPeriodId = specificationSearchModel.FundingPeriod.Id, FundingPeriodName = specificationSearchModel.FundingPeriod.Name, FundingStreamIds = specificationSearchModel.FundingStreams.Select(_ => _.Id).ToArray(), FundingStreamNames = specificationSearchModel.FundingStreams.Select(_ => _.Name).ToArray(), Description = specificationSearchModel.Description, LastUpdatedDate = specificationSearchModel.UpdatedAt, DataDefinitionRelationshipIds = specificationSearchModel.DataDefinitionRelationshipIds.ToArray(), Status = specificationSearchModel.PublishStatus, IsSelectedForFunding = specificationSearchModel.IsSelectedForFunding }, opt => opt.ComparingByMembers <Reference>()); }
public void SpecificationToSpecificationIndexMapping() { Specification specification = NewSpecification(_ => _.WithCurrent(NewSpecificationVersion(curr => curr.WithFundingStreamsIds(NewRandomString(), NewRandomString()) .WithDataDefinitionRelationshipIds(NewRandomString(), NewRandomString(), NewRandomString())))); SpecificationIndex searchIndex = WhenTheSourceItemsAreMapped(specification).Single(); searchIndex .Should() .BeEquivalentTo(new SpecificationIndex { Id = specification.Id, Name = specification.Name, FundingPeriodId = specification.Current.FundingPeriod.Id, FundingPeriodName = specification.Current.FundingPeriod.Name, FundingStreamIds = specification.Current.FundingStreams.Select(_ => _.Id).ToArray(), FundingStreamNames = specification.Current.FundingStreams.Select(_ => _.Name).ToArray(), Description = specification.Current.Description, LastUpdatedDate = specification.Current.Date, IsSelectedForFunding = specification.IsSelectedForFunding, DataDefinitionRelationshipIds = specification.Current.DataDefinitionRelationshipIds.ToArray(), Status = specification.Current.PublishStatus.ToString() }, opt => opt.ComparingByMembers <Reference>()); }
public async Task SearchById_GivenIdDoesNotReturnSearchResult_ReturnsNull() { SearchRepositorySettings searchRepositorySettings = new SearchRepositorySettings { SearchKey = string.Empty, SearchServiceName = string.Empty }; ISearchInitializer searchInitializer = Substitute.For <ISearchInitializer>(); ISearchIndexClient searchIndexClient = Substitute.For <ISearchIndexClient>(); AzureOperationResponse <DocumentSearchResult <SpecificationIndex> > documentSearchResult = new AzureOperationResponse <DocumentSearchResult <SpecificationIndex> > { Body = new DocumentSearchResult <SpecificationIndex>(null, null, null, null, null) }; IDocumentsOperations documentsOperations = Substitute.For <IDocumentsOperations>(); documentsOperations.SearchWithHttpMessagesAsync <SpecificationIndex>(Arg.Any <string>(), Arg.Any <SearchParameters>()).Returns(Task.FromResult(documentSearchResult)); ISearchServiceClient searchServiceClient = Substitute.For <ISearchServiceClient>(); searchIndexClient.Documents.Returns(documentsOperations); SearchRepository <SpecificationIndex> searchRepository = new SearchRepository <SpecificationIndex>(searchRepositorySettings, searchInitializer, searchServiceClient, searchIndexClient); string notFoundId = "notFound"; SpecificationIndex specificationIndex = await searchRepository.SearchById(notFoundId); specificationIndex.Should().BeNull(); }
private void AssertSearchResults(SpecificationIndex expectedSpecificationIndex, SpecificationSearchResult specificationSearchResult) { specificationSearchResult.Id.Should().Be(expectedSpecificationIndex.Id); specificationSearchResult.Name.Should().Be(expectedSpecificationIndex.Name); specificationSearchResult.FundingPeriodName.Should().Be(expectedSpecificationIndex.FundingPeriodName); specificationSearchResult.FundingStreamNames.Should().BeEquivalentTo(expectedSpecificationIndex.FundingStreamNames); specificationSearchResult.Status.Should().Be(expectedSpecificationIndex.Status); specificationSearchResult.Description.Should().Be(expectedSpecificationIndex.Description); specificationSearchResult.LastUpdatedDate.Should().Be(expectedSpecificationIndex.LastUpdatedDate); specificationSearchResult.IsSelectedForFunding.Should().Be(expectedSpecificationIndex.IsSelectedForFunding); }
private void AndTheSpecificationIndexHasTheDatasetsSummaryInformation(SpecificationIndex specificationIndex, int expectedTotalMappedCount, DateTimeOffset?expectedLastDatasetUpdatedDate) { specificationIndex.TotalMappedDataSets .Should() .Be(expectedTotalMappedCount); specificationIndex.MapDatasetLastUpdated .Should() .Be(expectedLastDatasetUpdatedDate); }
public async Task SearchById_GivenIdReturnsSearchResult_ReturnsResults() { string existingId = "existingId"; SearchRepositorySettings searchRepositorySettings = new SearchRepositorySettings { SearchKey = string.Empty, SearchServiceName = string.Empty }; ISearchInitializer searchInitializer = Substitute.For <ISearchInitializer>(); ISearchIndexClient searchIndexClient = Substitute.For <ISearchIndexClient>(); Microsoft.Azure.Search.Models.SearchResult <SpecificationIndex> specificationIndexSearchResult = new Microsoft.Azure.Search.Models.SearchResult <SpecificationIndex>(new SpecificationIndex { Id = existingId }); AzureOperationResponse <DocumentSearchResult <SpecificationIndex> > documentSearchResult = new AzureOperationResponse <DocumentSearchResult <SpecificationIndex> > { Body = new DocumentSearchResult <SpecificationIndex>(new[] { specificationIndexSearchResult }, null, null, null, null) }; IDocumentsOperations documentsOperations = Substitute.For <IDocumentsOperations>(); documentsOperations .SearchWithHttpMessagesAsync <SpecificationIndex>(Arg.Is <string>(_ => _ == $"\"{existingId}\""), Arg.Is <SearchParameters>(_ => _.SearchFields.SequenceEqual(new[] { "id" }))) .Returns(Task.FromResult(documentSearchResult)); ISearchServiceClient searchServiceClient = Substitute.For <ISearchServiceClient>(); searchIndexClient.Documents.Returns(documentsOperations); SearchRepository <SpecificationIndex> searchRepository = new SearchRepository <SpecificationIndex>(searchRepositorySettings, searchInitializer, searchServiceClient, searchIndexClient); SpecificationIndex specificationIndex = await searchRepository.SearchById(existingId); specificationIndex.Should().NotBeNull(); specificationIndex.Id.Should().Be(existingId); }
public async Task MapsSuppliedSpecificationIntoIndexAddsDatasetSummaryInformationAndThenAndThenIndexesIt() { DateTimeOffset lastUpdateOne = NewRandomDate(); DateTimeOffset lastUpdateTwo = lastUpdateOne.AddDays(1); Specification specification = NewSpecification(); SpecificationIndex specificationIndex = NewSpecificationIndex(); DatasetSpecificationRelationshipViewModel[] relationships = AsArray(NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateTwo)), NewDatasetSpecificationRelationshipViewModel(), NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateOne))); GivenTheSpecificationIndexMappings(AsArray(specification), specificationIndex); AndTheDatasetRelationshipsForSpecificationId(specificationIndex.Id, relationships); await WhenTheSpecificationIsIndexed(specification); ThenTheIndicesWereIndexed(specificationIndex); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndex, 2, lastUpdateTwo); }
public async Task SearchSpecifications_GivenValidModelWithOneFilter_ThenSearchIsPerformed() { //Arrange SearchModel model = new SearchModel { PageNumber = 1, Top = 50, IncludeFacets = true, Filters = new Dictionary <string, string[]>() { { "status", new string [] { "test" } } }, SearchTerm = "testTerm", }; SpecificationIndex expectedSpecificationIndex = new SpecificationIndex() { Id = "test-sp1", Name = "test-sp1-name", FundingPeriodName = "fp", FundingStreamNames = new[] { "fs" }, Status = "test-status", Description = "des", IsSelectedForFunding = true, LastUpdatedDate = new DateTimeOffset(new DateTime(2020, 09, 08, 10, 40, 15)) }; SearchResults <SpecificationIndex> searchResults = new SearchResults <SpecificationIndex>() { Results = new List <Repositories.Common.Search.SearchResult <SpecificationIndex> >() { new Repositories.Common.Search.SearchResult <SpecificationIndex>() { Result = expectedSpecificationIndex } } }; ILogger logger = CreateLogger(); ISearchRepository <SpecificationIndex> searchRepository = CreateSearchRepository(); searchRepository .Search(Arg.Any <string>(), Arg.Any <SearchParameters>()) .Returns(searchResults); SpecificationsSearchService service = CreateSearchService(logger: logger, searchRepository: searchRepository); //Act IActionResult result = await service.SearchSpecifications(model); //Assert SpecificationSearchResults searchResult = result .Should() .BeOfType <OkObjectResult>() .Which .Value .As <SpecificationSearchResults>(); searchResult.Results.Count().Should().Be(1); AssertSearchResults(expectedSpecificationIndex, searchResult.Results.First()); await searchRepository .Received(3) .Search(model.SearchTerm, Arg.Is <SearchParameters>(c => model.Filters.Keys.All(f => c.Filter.Contains(f)) && !string.IsNullOrWhiteSpace(c.Filter) )); }
public async Task MapsSuppliedSearchModelsIntoIndicesAddsDatasetSummaryInformationAndThenIndexesThem() { DateTimeOffset lastUpdateFour = NewRandomDate(); DateTimeOffset lastUpdateTwo = lastUpdateFour.AddDays(1); DateTimeOffset lastUpdateOne = lastUpdateFour.AddDays(10); SpecificationSearchModel[] specifications = AsArray( NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel(), NewSpecificationSearchModel() ); SpecificationIndex specificationIndexOne = NewSpecificationIndex(); SpecificationIndex specificationIndexTwo = NewSpecificationIndex(); SpecificationIndex specificationIndexThree = NewSpecificationIndex(); SpecificationIndex specificationIndexFour = NewSpecificationIndex(); SpecificationIndex specificationIndexFive = NewSpecificationIndex(); SpecificationIndex specificationIndexSix = NewSpecificationIndex(); SpecificationIndex specificationIndexSeven = NewSpecificationIndex(); GivenTheSpecificationIndexMappings(specifications, specificationIndexOne, specificationIndexTwo, specificationIndexThree, specificationIndexFour, specificationIndexFive, specificationIndexSix, specificationIndexSeven); AndTheDatasetRelationshipsForSpecificationId(specificationIndexFour.Id, NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateFour)), NewDatasetSpecificationRelationshipViewModel()); AndTheDatasetRelationshipsForSpecificationId(specificationIndexSix.Id, NewDatasetSpecificationRelationshipViewModel()); AndTheDatasetRelationshipsForSpecificationId(specificationIndexSeven.Id, NewDatasetSpecificationRelationshipViewModel()); AndTheDatasetRelationshipsForSpecificationId(specificationIndexFive.Id, NewDatasetSpecificationRelationshipViewModel()); AndTheDatasetRelationshipsForSpecificationId(specificationIndexTwo.Id, NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString())), NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateTwo)), NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateTwo.AddDays(-1))), NewDatasetSpecificationRelationshipViewModel()); AndTheDatasetRelationshipsForSpecificationId(specificationIndexOne.Id, NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateOne)), NewDatasetSpecificationRelationshipViewModel(_ => _.WithDatasetId(NewRandomString()) .WithLastUpdatedDate(lastUpdateOne.AddDays(-1))), NewDatasetSpecificationRelationshipViewModel()); await WhenTheSpecificationsAreIndexed(specifications); ThenTheIndicesWereIndexed(specificationIndexOne, specificationIndexTwo, specificationIndexThree, specificationIndexFour, specificationIndexFive); AndTheIndicesWereIndexed(specificationIndexSix, specificationIndexSeven); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexOne, 2, lastUpdateOne); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexTwo, 3, lastUpdateTwo); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexThree, 0, null); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexFour, 1, lastUpdateFour); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexFive, 0, null); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexSix, 0, null); AndTheSpecificationIndexHasTheDatasetsSummaryInformation(specificationIndexSeven, 0, null); }
public void SearchIndexTest_GivenSearchSchemasAndModels_EnsureFieldsMatch() { // Arrange IList <string> ErrorLog = new List <string>(); DatasetDefinitionIndex datasetDefinitionIndex = new DatasetDefinitionIndex(); ProvidersIndex providersIndex = new ProvidersIndex(); PublishedFundingIndex publishedfundingindex = new PublishedFundingIndex(); PublishedProviderIndex publishedProviderIndex = new PublishedProviderIndex(); SpecificationIndex specificationindex = new SpecificationIndex(); TemplateIndex templateIndex = new TemplateIndex(); IEnumerable <Type> searchIndexTypes = GetTypesWithSearchIndexAttribute(); IEnumerable <string> indexNames = Directory .GetDirectories(searchIndexDirectoryPath, "*index", SearchOption.TopDirectoryOnly) .Select(m => new DirectoryInfo(m).Name); //Act foreach (string indexName in indexNames) { try { string jsonFilePath = $@"{searchIndexDirectoryPath}\{indexName}\{indexName}.json"; string jsonText = File.ReadAllText(jsonFilePath, Encoding.UTF8); SearchIndexSchema searchIndexSchema = JsonConvert.DeserializeObject <SearchIndexSchema>(jsonText); if (searchIndexSchema?.Name == null) { ErrorLog.Add(string.IsNullOrWhiteSpace(jsonText) ? $"{indexName} json is blank" : $"{indexName} json name is not available"); } else if (searchIndexSchema.Name != indexName) { ErrorLog.Add($"Expected to find index { indexName }, but found { searchIndexSchema.Name }"); } else { Type searchIndexType = searchIndexTypes .FirstOrDefault(m => m.CustomAttributes .FirstOrDefault(p => p.NamedArguments .Any(n => n.TypedValue.Value.ToString() == searchIndexSchema.Name)) != null); IEnumerable <string> searchIndexProperties = searchIndexType.GetProperties() .Select(m => m.CustomAttributes .FirstOrDefault(a => a.AttributeType.Name == "JsonPropertyAttribute") ?.ConstructorArguments[0].Value.ToString().ToLower()) .Where(p => p != null); IEnumerable <string> searchIndexJsonProperties = searchIndexSchema.Fields .Select(m => m.Name.ToLower()) .Where(p => p != null); if (!searchIndexProperties.Any()) { ErrorLog.Add($"Index {indexName}: The model contains no properties"); } else if (!searchIndexJsonProperties.Any()) { ErrorLog.Add($"Index {indexName}: The json contains no properties"); } else { IEnumerable <string> notInJson = searchIndexProperties.Except(searchIndexJsonProperties); if (notInJson.Any()) { string properties = string.Join(",", notInJson); ErrorLog.Add($"Index {indexName}: The model contains the following properties not found in the json schema ({properties})"); } IEnumerable <string> notInModel = searchIndexJsonProperties.Except(searchIndexProperties); if (notInModel.Any()) { string properties = string.Join(",", notInModel); ErrorLog.Add($"Index {indexName}: The json schema contains the following properties not found in the model ({properties})"); } } } } catch (Exception e) { ErrorLog.Add($"Unexpected error checking '{indexName}': {e.Message}{Environment.NewLine}{ e.StackTrace }"); } } //Assert if (ErrorLog.Any()) { Assert.Fail(string.Join(Environment.NewLine, ErrorLog)); } }
public void SearchIndexTest_GivenSearchSchemasAndModels_EnsuresAttributesMatch() { //Arrange IList <string> ErrorLog = new List <string>(); DatasetDefinitionIndex datasetDefinitionIndex = new DatasetDefinitionIndex(); ProvidersIndex providersIndex = new ProvidersIndex(); PublishedFundingIndex publishedfundingindex = new PublishedFundingIndex(); PublishedProviderIndex publishedProviderIndex = new PublishedProviderIndex(); SpecificationIndex specificationindex = new SpecificationIndex(); TemplateIndex templateIndex = new TemplateIndex(); IEnumerable <Type> searchIndexTypes = GetTypesWithSearchIndexAttribute(); IEnumerable <string> indexNames = Directory .GetDirectories(searchIndexDirectoryPath, "*index", SearchOption.TopDirectoryOnly) .Select(m => new DirectoryInfo(m).Name); //Act foreach (string indexName in indexNames) { try { string jsonFilePath = $@"{searchIndexDirectoryPath}\{indexName}\{indexName}.json"; string jsonText = File.ReadAllText(jsonFilePath, Encoding.UTF8); SearchIndexSchema searchIndexSchema = JsonConvert.DeserializeObject <SearchIndexSchema>(jsonText); if (searchIndexSchema?.Name == null) { ErrorLog.Add(string.IsNullOrWhiteSpace(jsonText) ? $"{indexName} json is blank" : $"{indexName} json name is not available"); } else if (searchIndexSchema.Name != indexName) { ErrorLog.Add($"Expected to find index {indexName}, but found {searchIndexSchema.Name}"); } else { Type searchIndexType = searchIndexTypes.FirstOrDefault(m => m.CustomAttributes.FirstOrDefault(p => p.NamedArguments.Any(n => n.TypedValue.Value.ToString() == searchIndexSchema.Name)) != null); IEnumerable <PropertyInfo> searchIndexProperties = searchIndexType.GetProperties(); foreach (SearchIndexField searchIndexField in searchIndexSchema.Fields) { PropertyInfo matchedProperty = searchIndexProperties.FirstOrDefault(m => string.Equals(m.CustomAttributes .SingleOrDefault(x => x.AttributeType.Name == "JsonPropertyAttribute") ?.ConstructorArguments[0].ToString().Replace("\"", "") ?? m.Name, searchIndexField.Name, StringComparison.InvariantCultureIgnoreCase)); if (matchedProperty == null) { ErrorLog.Add($"{indexName}: {searchIndexField.Name} did not match any properties"); } else { CheckIndexFieldTypes(matchedProperty, searchIndexField, ErrorLog, indexName); CheckIndexAttributes(matchedProperty, searchIndexField, ErrorLog, indexName); } } } } catch (Exception e) { ErrorLog.Add($"Unexpected error checking '{indexName}': {e.Message}{Environment.NewLine}{e.StackTrace}"); } } //Assert if (ErrorLog.Any()) { Assert.Fail(string.Join(Environment.NewLine, ErrorLog)); } }