public async Task SearchOrganisationBySearchParamsReturnsOrganisationsInTheSortOrderSpecified() { var session = EntityHelpers.CreateSession("Admin"); DatabaseContext.Sessions.Add(session); Client.DefaultRequestHeaders.Add("Cookie", $"access_token={session.Payload}"); var rand = new Random(); var organisations = EntityHelpers.CreateOrganisations(10).ToList(); var searchParam = Randomm.Word(); var first = rand.Next(10, 20); var second = rand.Next(20, 30); organisations[5].Name = searchParam + first; organisations[3].Name = searchParam + second; DatabaseContext.Organisations.AddRange(organisations); DatabaseContext.SaveChanges(); var requestUri = new Uri($"api/v1/organisations?search={searchParam}&sort=name&direction=asc", UriKind.Relative); var response = await Client.GetAsync(requestUri).ConfigureAwait(true); response.StatusCode.Should().Be(200); var content = response.Content; var stringResponse = await content.ReadAsStringAsync().ConfigureAwait(true); var deserializedBody = JsonConvert.DeserializeObject <OrganisationResponseList>(stringResponse); deserializedBody.Should().NotBeNull(); deserializedBody.Organisations[0].Name.Should().BeEquivalentTo(organisations[5].Name); deserializedBody.Organisations[1].Name.Should().BeEquivalentTo(organisations[3].Name); }
public void CreateOrganisationUseCaseCallsGatewayCreateOrganisation() { var requestParams = Randomm.Create <OrganisationRequest>(); var accessToken = Randomm.Word(); _classUnderTest.ExecuteCreate(accessToken, requestParams); _mockOrganisationsGateway.Verify(u => u.CreateOrganisation(It.IsAny <Organisation>()), Times.Once); }
public async Task SearchServicesReturnServicesAccordingToRankIfMatched() { var searchWord1 = Randomm.Word(); var searchWord2 = Randomm.Word(); var irrelevantWord = Randomm.Word(); var bridgeSyn1Word = Utility.SuperSetOfString(searchWord1); var bridgeSyn2Word = Utility.SuperSetOfString(searchWord2); var synWord1 = Randomm.Word(); var synWord2 = Randomm.Word(); var synWord3 = Randomm.Word(); var synonymGroup1 = EntityHelpers.CreateSynonymGroupWithWords(); var synonymGroup2 = EntityHelpers.CreateSynonymGroupWithWords(); var dummySynGroup = EntityHelpers.CreateSynonymGroupWithWords(); var bridgeSynonym1 = EntityHelpers.SynWord(synonymGroup1, bridgeSyn1Word); var bridgeSynonym2 = EntityHelpers.SynWord(synonymGroup2, bridgeSyn2Word); var matchSynonym1 = EntityHelpers.SynWord(synonymGroup1, synWord1); var matchSynonym2 = EntityHelpers.SynWord(synonymGroup1, synWord2); var matchSynonym3 = EntityHelpers.SynWord(synonymGroup2, synWord3); synonymGroup1.SynonymWords.Add(bridgeSynonym1); synonymGroup2.SynonymWords.Add(bridgeSynonym2); synonymGroup1.SynonymWords.Add(matchSynonym1); synonymGroup1.SynonymWords.Add(matchSynonym2); synonymGroup2.SynonymWords.Add(matchSynonym3); var services = EntityHelpers.CreateServices(5); var matchService1 = EntityHelpers.CreateService(); var matchService2 = EntityHelpers.CreateService(); var matchService3 = EntityHelpers.CreateService(); var matchService4 = EntityHelpers.CreateService(); matchService1.Name += searchWord2; //matchService2.Description += synWord2; matchService2.Description += " " + synWord2; //15 Feb 2021 - Change made so we only search for whole words in the service description! - So we add a space. matchService3.Organization.Name += synWord3; matchService4.Organization.Name += searchWord1; services.AddMany(matchService1, matchService2, matchService3, matchService4); DatabaseContext.SynonymGroups.AddRange(synonymGroup1); DatabaseContext.SynonymGroups.AddRange(synonymGroup2); DatabaseContext.SynonymGroups.AddRange(dummySynGroup); DatabaseContext.Services.AddRange(services); DatabaseContext.SaveChanges(); var requestUri = new Uri($"api/v1/services?search={searchWord1} {searchWord2} {irrelevantWord}", UriKind.Relative); var response = Client.GetAsync(requestUri).Result; response.StatusCode.Should().Be(200); var content = response.Content; var stringContent = await content.ReadAsStringAsync().ConfigureAwait(false); var deserializedBody = JsonConvert.DeserializeObject <GetServiceResponseList>(stringContent); deserializedBody.Services.Count.Should().Be(4); deserializedBody.Services[0].Name.Should().Be(matchService4.Name); deserializedBody.Services[1].Name.Should().Be(matchService1.Name); deserializedBody.Services[2].Name.Should().Be(matchService3.Name); deserializedBody.Services[3].Name.Should().Be(matchService2.Name); }
[TestCase(TestName = "Given Addresses API context's GetAddressesRequest method is called, When an unexpected exception is thrown during its execution, Then the AddressesGateway rethrows that exception so it could be handled elsewhere.")] // it should be handled where all the other exceptions are handled. Gateway can't be the one handling it because as requested it only has to return the coordinates. TODO: improve on this. public void GivenAnUnexpectedExceptionIsThrownInTheGatewayThenItShouldRethrowThatException() // Like WebException (Timeout, Connect failure) { // arrange var expectedException = new WebException(Randomm.Word(), WebExceptionStatus.Timeout); _mockAddressesApiContext.Setup(c => c.GetAddressesRequest(It.IsAny <string>())) .Throws(expectedException); // act Action gatewayCall = () => _classUnderTest.GetPostcodeCoordinates(It.IsAny <string>()); // assert gatewayCall.Should().Throw <WebException>(); }
[TestCase(TestName = "Given user provided search term consisting of multiple words, When services get filtered in SearchService method, Then the returned services are categorized into Full user input match Or Split match.")] // done so to ensure the less relevant services are in the separate collection public void SearchServiceGatewaySeparatesOutFullMatchResultsFromSplitMatch() { // arrange var word1 = Randomm.Word(); var word2 = Randomm.Word(); var userSearchInput = $"{word1} {word2}"; var request = new SearchServicesRequest() { Search = userSearchInput }; var services = new List <Service>(); var serviceToFind1 = EntityHelpers.CreateService(); // full match serviceToFind1.Name += userSearchInput; var serviceToFind2 = EntityHelpers.CreateService(); // split match 1 serviceToFind2.Name += word1; var serviceToFind3 = EntityHelpers.CreateService(); // split match 2 serviceToFind3.Name += word2; services.Add(serviceToFind1); services.Add(serviceToFind2); services.Add(serviceToFind3); DatabaseContext.Services.AddRange(services); DatabaseContext.SaveChanges(); // act var gatewayResult = _classUnderTest.SearchServices(request); var fullMatches = gatewayResult.FullMatchServices; var splitMatches = gatewayResult.SplitMatchServices; // assert gatewayResult.Should().NotBeNull(); fullMatches.Should().NotBeNull(); splitMatches.Should().NotBeNull(); fullMatches.Should().Contain(s => s.Name.Contains(userSearchInput, StringComparison.OrdinalIgnoreCase)); fullMatches.Should().HaveCount(1); splitMatches.Should().Contain(s => s.Name.Contains(word1, StringComparison.OrdinalIgnoreCase)); splitMatches.Should().Contain(s => s.Name.Contains(word2, StringComparison.OrdinalIgnoreCase)); splitMatches.Should().NotContain(s => s.Name.Contains(userSearchInput, StringComparison.OrdinalIgnoreCase)); splitMatches.Should().HaveCount(2); }
public void WhenDoingPartialTextSearchMatchesWordsOf3orLessCharactersLongGetIgnored() //it's too short - these will be searched and found inside other words in DB { // arrange var shortWordList = new List <string> { "and", "a", "an", "the", "bfg", "42" }; var shortWord = shortWordList.RandomItem(); var word = Randomm.Word().Replace(shortWord, "test");// have to ensure the shortword is not contained in the actual word for the sake of test var userSearchInput = $"{shortWord} {word}"; var request = new SearchServicesRequest() { Search = userSearchInput }; var services = EntityHelpers.CreateServices(5).ToList(); //dummy services services.ForEach(s => s.Name = s.Name.Replace(word, "ssj")); //make sure they don't match the search word //assuming there's no full match. due to full match containing a shortword, the assertion at the bottom wouldn't be able to test what's needed. var serviceToFind = EntityHelpers.CreateService(); // word 1 match serviceToFind.Name = serviceToFind.Name.Replace(shortWord, "test"); //ensuring random hash does not contain shortword. for the assertion bellow to work as intended, the service name's hash part should not contain shortword. serviceToFind.Name += word; var serviceToNotFind = EntityHelpers.CreateService(); // shortword no match. this ensures that the test can fail if the implementation is wrong or not present. serviceToNotFind.Name = serviceToNotFind.Name.Replace(word, "1234"); // make sure the mismatching service does not contain a desired search term serviceToNotFind.Name += shortWord; services.Add(serviceToFind); services.Add(serviceToNotFind); DatabaseContext.Services.AddRange(services); DatabaseContext.SaveChanges(); // act var gatewayResult = _classUnderTest.SearchServices(request); var splitMatches = gatewayResult.SplitMatchServices; // assert gatewayResult.Should().NotBeNull(); splitMatches.Should().NotBeNull(); splitMatches.Should().NotContain(s => s.Name.Contains(shortWord, StringComparison.OrdinalIgnoreCase)); splitMatches.Should().HaveCount(1); }
//[TestCase(TestName = "Given an organisation domain object is provided the created organisation is returned")] public void ReturnsCreatedOrganisation() { var requestParams = Randomm.Create <OrganisationRequest>(); var domainData = requestParams.ToDomain(); var accessToken = Randomm.Word(); var users = new List <UserDomain> { Randomm.Create <UserDomain>() }; _mockOrganisationsGateway.Setup(g => g.CreateOrganisation(It.IsAny <Organisation>())).Returns(domainData); _mockUsersGateway.Setup(ug => ug.GetAllUsers(It.IsAny <UserQueryParam>())).ReturnsAsync(users); var expectedResponse = domainData.ToResponse(); var response = _classUnderTest.ExecuteCreate(accessToken, requestParams); response.Should().NotBeNull(); response.Should().BeEquivalentTo(expectedResponse); }
public void UponFilteringServicesByAMultiWordInputTheReturnedResultsIncludePartialMatches() { // arrange var word1 = Randomm.Word(); var word2 = Randomm.Word(); var userSearchInput = $"{word1} {word2}"; var request = new SearchServicesRequest() { Search = userSearchInput }; var services = EntityHelpers.CreateServices(5).ToList(); // dummy services var serviceToFind1 = EntityHelpers.CreateService(); // full match serviceToFind1.Name += userSearchInput; var serviceToFind2 = EntityHelpers.CreateService(); // word 1 match serviceToFind2.Name += word1; var serviceToFind3 = EntityHelpers.CreateService(); // word 2 match serviceToFind3.Name += word2; services.Add(serviceToFind1); services.Add(serviceToFind2); services.Add(serviceToFind3); DatabaseContext.Services.AddRange(services); DatabaseContext.SaveChanges(); // act var gatewayResult = _classUnderTest.SearchServices(request); var fullMatches = gatewayResult.FullMatchServices; var splitMatches = gatewayResult.SplitMatchServices; var returnedServices = fullMatches.Concat(splitMatches).ToList(); // assert gatewayResult.Should().NotBeNull(); fullMatches.Should().NotBeNull(); splitMatches.Should().NotBeNull(); returnedServices.Should().Contain(s => s.Name.Contains(userSearchInput, StringComparison.OrdinalIgnoreCase)); returnedServices.Should().Contain(s => s.Name.Contains(word1, StringComparison.OrdinalIgnoreCase)); returnedServices.Should().Contain(s => s.Name.Contains(word2, StringComparison.OrdinalIgnoreCase)); returnedServices.Should().HaveCount(3); }
public async Task CreateServiceUseCaseCallsGatewayCreateService() { var requestParams = Randomm.Create <ServiceRequest>(); var locationRequest = Randomm.Create <ServiceLocationRequest>(); requestParams.Locations = new List <ServiceLocationRequest>() { locationRequest }; var domainData = requestParams.ToDomain(); domainData.Organisation = Randomm.Create <OrganisationDomain>(); var accessToken = Randomm.Word(); _mockServicesGateway.Setup(g => g.CreateService(It.IsAny <ServiceRequest>())).ReturnsAsync(domainData); var myResult = await _classUnderTest.Execute(requestParams).ConfigureAwait(false); _mockServicesGateway.Verify(u => u.CreateService(It.IsAny <ServiceRequest>()), Times.Once); }
public void AddressesGatewayShouldThrowAnErrorWhenAPICallReturnsUnexpectedSchema(int statusCode) // if anything about the Addresses API changes, ResponseSchemaNotRecognisedException //TODO: should contain api name { // arrange var contextResponse = Randomm.AddressesAPIContextResponse(statusCode == 9000 ? 400 : statusCode); switch (statusCode) { case 200: contextResponse.JsonContent = contextResponse.JsonContent.Replace("Data", Randomm.Word() , StringComparison.OrdinalIgnoreCase); break; case 400: contextResponse.JsonContent = contextResponse.JsonContent.Replace("validationErrors", Randomm.Word() , StringComparison.OrdinalIgnoreCase); break; case 500: contextResponse.JsonContent = contextResponse.JsonContent.Replace("Errors", Randomm.Word() , StringComparison.OrdinalIgnoreCase); break; default: contextResponse.JsonContent = contextResponse.JsonContent.Replace("error", Randomm.Word() , StringComparison.OrdinalIgnoreCase); break; } _mockAddressesApiContext.Setup(c => c.GetAddressesRequest(It.IsAny <string>())).Returns(contextResponse); // act Action gatewayCall = () => _classUnderTest.GetPostcodeCoordinates(It.IsAny <string>()); // assert gatewayCall.Should().Throw <ResponseSchemaNotRecognisedException>(); }
public async Task UpdateServiceUseCaseWithLocationCallsAddressXrefGateway() { var requestParams = Randomm.Create <ServiceRequest>(); var orgDomain = Randomm.Create <OrganisationDomain>(); requestParams.OrganisationId = orgDomain.Id; var locationRequest = Randomm.Create <ServiceLocationRequest>(); requestParams.Locations = new List <ServiceLocationRequest>() { locationRequest }; var serviceDomainData = requestParams.ToDomain(); serviceDomainData.Organisation = orgDomain; serviceDomainData.Id = 123; var accessToken = Randomm.Word(); _mockServicesGateway.Setup(g => g.UpdateService(It.IsAny <ServiceRequest>(), 123)).ReturnsAsync(serviceDomainData); _mockAddressXRefGateway.Setup(g => g.GetNHSNeighbourhood(It.IsAny <string>())).Returns("NHS1"); var response = await _classUnderTest.Execute(requestParams, 123).ConfigureAwait(false); response.Should().NotBeNull(); response.Should().BeEquivalentTo(serviceDomainData, options => { options.Excluding(ex => ex.ImageId); options.Excluding(ex => ex.ServiceTaxonomies); options.Excluding(ex => ex.Organisation); options.Excluding(ex => ex.ServiceLocations); return(options); }); response.Locations.FirstOrDefault().Address1.Should().Be(serviceDomainData.ServiceLocations.FirstOrDefault().Address1); response.Locations.FirstOrDefault().Address2.Should().Be(serviceDomainData.ServiceLocations.FirstOrDefault().Address2); response.Locations.FirstOrDefault().City.Should().Be(serviceDomainData.ServiceLocations.FirstOrDefault().City); response.Locations.FirstOrDefault().Country.Should().Be(serviceDomainData.ServiceLocations.FirstOrDefault().Country); response.Locations.FirstOrDefault().NHSNeighbourhood.Should().Be(serviceDomainData.ServiceLocations.FirstOrDefault().NHSNeighbourhood); }
public void WholeAndSplitUserInputMatchesAreReturnedInCorrectRank() { // arrange var searchWord1 = Randomm.Word(); // word that won't match any results, however 1 of its synonyms from synonym group will var searchWord2 = Randomm.Word(); // same as above, but the matching synonym will be in another synonym group var irrelevantWord = Randomm.Word(); // a control word, that won't match anything, nor its synonyms will. var userInput = $"{searchWord1} " + $"{irrelevantWord} " + $"{searchWord2}"; var request = new SearchServicesRequest(); request.Search = userInput; var bridgeSyn1Word = Utility.SuperSetOfString(searchWord1); // A superset word of search word 1 that will relate to a synonym word inside synonym group 1 - this word has no match in the DB var bridgeSyn2Word = Utility.SuperSetOfString(searchWord2); // A superset word of search word 2 that will relate to a synonym word inside synonym group 2 - this word has no match in the DB var synWord1 = Randomm.Word(); // synonym within the same synonym group (1) as a word related to search word 1 - this word has a match in the DB var synWord2 = Randomm.Word(); // synonym within the same synonym group (1) as a word related to search word 1 - this word has a match in the DB var synWord3 = Randomm.Word(); // synonym within the same synonym group (2) as a word related to search word 2 - this word has a match in the DB var synonymGroup1 = EntityHelpers.CreateSynonymGroupWithWords(); // relevant group with dummy synonym words var synonymGroup2 = EntityHelpers.CreateSynonymGroupWithWords(); // relevant group with dummy synonym words var dummySynGroup = EntityHelpers.CreateSynonymGroupWithWords(); // dummy synonym group that should not be picked up var bridgeSynonym1 = EntityHelpers.SynWord(synonymGroup1, bridgeSyn1Word); // synonym that has no match in DB, however it bridges user input search word with the synonym group 1 var bridgeSynonym2 = EntityHelpers.SynWord(synonymGroup2, bridgeSyn2Word); var matchSynonym1 = EntityHelpers.SynWord(synonymGroup1, synWord1); // creating a synonym word object to insert that will have a match, creating a link with synonym group 1 var matchSynonym2 = EntityHelpers.SynWord(synonymGroup1, synWord2); var matchSynonym3 = EntityHelpers.SynWord(synonymGroup2, synWord3); synonymGroup1.SynonymWords.Add(bridgeSynonym1); // added bridge synonym to the synonym group synonymGroup2.SynonymWords.Add(bridgeSynonym2); synonymGroup1.SynonymWords.Add(matchSynonym1); // added match synonym into a synonym group synonymGroup1.SynonymWords.Add(matchSynonym2); synonymGroup2.SynonymWords.Add(matchSynonym3); var services = EntityHelpers.CreateServices(5); // creating list of dummy services that should not be found var matchService1 = EntityHelpers.CreateService(); // service that is intended to be found through the synonym of synonym group 1 var matchService2 = EntityHelpers.CreateService(); // service that is intended to be found through the synonym of synonym group 1 var matchService3 = EntityHelpers.CreateService(); // service that is intended to be found through the synonym of synonym group 2 var matchService4 = EntityHelpers.CreateService(); // service that is intended to be found through the main search term matchService1.Name += searchWord2; // creating a link between a service and a match synonym 1 // creating a link between a service and a match synonym 2 matchService2.Description += " " + synWord2; //15 Feb 2021 - Change made so we only search for whole words in the service description! - So we add a space. matchService3.Organization.Name += synWord3; // creating a link between a service and a match synonym 3 matchService4.Organization.Name += searchWord1; // creating a link between a service and a main search word services.AddMany(matchService1, matchService2, matchService3, matchService4); // include match services into a to be inserted services collection DatabaseContext.SynonymGroups.AddRange(synonymGroup1); // adding synonym groups containing synonym words into a database DatabaseContext.SynonymGroups.AddRange(synonymGroup2); DatabaseContext.SynonymGroups.AddRange(dummySynGroup); DatabaseContext.Services.AddRange(services); // adding services into a database DatabaseContext.SaveChanges(); // act var gatewayResult = _classUnderTest.SearchServices(request); var splitMatches = gatewayResult.SplitMatchServices; var fullMatches = gatewayResult.FullMatchServices; // assert splitMatches.Should().HaveCount(4); fullMatches.Should().HaveCount(0); splitMatches[0].Name.Should().Be(matchService4.Name); splitMatches[1].Name.Should().Be(matchService1.Name); splitMatches[2].Name.Should().Be(matchService3.Name); splitMatches[3].Name.Should().Be(matchService2.Name); }