def test_orders_by_task_passed_to_the_query(self): task_passed_to_query = 'the-task-id' task_to_ignore = 'some-other-task' create_tasks([task_passed_to_query, task_to_ignore]) similar_service = ServiceBuilder(self.organization).with_location( self.location).create() dissimilar_service = ServiceBuilder(self.organization).with_location( self.location).create() lower_score = 0.1 low_score = 0.2 high_score = 0.8 higher_score = 0.9 self.set_service_similarity_score(task_passed_to_query, similar_service.id, high_score) self.set_service_similarity_score(task_passed_to_query, dissimilar_service.id, low_score) # Test verifies that these scores are ignored, # if they were considered then dissimilar_service would be returned as the first element self.set_service_similarity_score(task_to_ignore, similar_service.id, lower_score) self.set_service_similarity_score(task_to_ignore, dissimilar_service.id, higher_score) url = '/v1/services_at_location/?related_to_task={0}'.format( task_passed_to_query) json = self.client.get(url).json() self.assertEqual(len(json), 2) self.assertEqual(json[0]['service']['name'], similar_service.name) self.assertEqual(json[1]['service']['name'], dissimilar_service.name)
def test_returns_services_ordered_by_score(self): task_id = a_string() task = Task(id=task_id, name=a_string(), description=a_string()) task.save() organization = OrganizationBuilder().create() more_related_service = ServiceBuilder(organization).create() less_related_service = ServiceBuilder(organization).create() higher_score = 0.9 lower_score = 0.1 TaskServiceSimilarityScore(task=task, service=more_related_service, similarity_score=higher_score).save() TaskServiceSimilarityScore(task=task, service=less_related_service, similarity_score=lower_score).save() url = '/v1/tasks/{}/related_services/'.format(task_id) response = self.client.get(url) self.assertEqual(response.json()[0]['service_id'], more_related_service.id) self.assertEqual(response.json()[1]['service_id'], less_related_service.id)
def setUp(self): self.organization = OrganizationBuilder().build() self.organization.save() self.service = ServiceBuilder(self.organization).build() self.service.save() self.location = LocationBuilder(self.organization).build() self.location.save()
def setUp(self): self.first_organization = OrganizationBuilder().create() self.second_organization = OrganizationBuilder().create() self.first_location = LocationBuilder(self.first_organization).create() self.second_location = LocationBuilder(self.first_organization).create() self.first_service = ServiceBuilder(self.first_organization).create() self.second_service = ServiceBuilder(self.second_organization).create() add_service_to_location(self.first_service, self.first_location) add_service_to_location(self.second_service, self.second_location)
def test_full_text_search_with_two_search_terms_implies_logical_and(self): first_name = a_string() second_name = a_string() combined_name = first_name + second_name ServiceBuilder(self.organization).with_name(first_name).create() ServiceBuilder(self.organization).with_name(second_name).create() ServiceBuilder(self.organization).with_name(combined_name).create() url = '/v1/services/?search={0}+{1}'.format(first_name, second_name) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['name'], combined_name)
def test_does_not_return_unrelated_services(self): task_id = 'the-task-id' create_tasks([task_id]) related_service = ServiceBuilder(self.organization).with_location( self.location).create() self.set_service_similarity_score(task_id, related_service.id, a_float()) unrelated_service = ServiceBuilder(self.organization).with_location( self.location).create() url = '/v1/services_at_location/?related_to_task={0}'.format(task_id) json = self.client.get(url).json() self.assertEqual(len(json), 1) self.assertEqual(json[0]['service']['name'], related_service.name)
def create_many_services(self, count): for i in range(0, count): one_based_id = i + 1 id_as_string = str(one_based_id) id_with_zero_prefix = ('00' + id_as_string)[-3:] ServiceBuilder( self.organization).with_id(id_with_zero_prefix).create()
def test_empty_description_is_saved_as_null(self): empty_description = '' null_description = None service = ServiceBuilder( self.organization).with_description(empty_description).build() service_from_db = validate_save_and_reload(service) self.assertEqual(service_from_db.description, null_description)
def test_name_cannot_be_none(self): null_name = None service = ServiceBuilder(self.organization).with_name(null_name).build() # Note that we're getting an integrity error from the database here, # haven't figured out how to make this fail validation which would be cleaner # and would also allow us invalidate on the empty string. with self.assertRaises(django_utils.IntegrityError): validate_save_and_reload(service)
def test_full_text_search_ignores_empty_search_term(self): ServiceBuilder(self.organization).create() url = '/v1/services/?search={0},{1},{2}'.format('', a_string(), a_string()) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 0)
def create_many(self, count=3): organization = OrganizationBuilder().create() return ([ ServiceAtLocation.objects.create( location=LocationBuilder(organization).create(), service=ServiceBuilder(organization).create()) for _ in range(0, count) ])
def test_removes_phone_numbers_in_brackets_from_description(self): description_with_phone_numbers = 'Call 1-(800)-123-4567 or (604)-123-4567 for more information.' description_without_phone_numbers = ('Call or for more information.') ServiceBuilder(self.organization).with_description( description_with_phone_numbers).create() _, descriptions = to_service_ids_and_descriptions( Service.objects.all()) self.assertIn(description_without_phone_numbers, descriptions[0])
def test_full_text_search_with_no_match_returns_empty_array(self): service = ServiceBuilder(self.organization).create() url = '/v1/services/?search={0}'.format(a_string()) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 0)
def test_description_is_multilingual(self): service = ServiceBuilder(self.organization).build() self.set_description_in_language(service, 'en', 'In English') self.set_description_in_language(service, 'fr', 'En français') service_from_db = validate_save_and_reload(service) self.assert_description_in_language_equals(service_from_db, 'en', 'In English') self.assert_description_in_language_equals(service_from_db, 'fr', 'En français')
def setUp(self): self.organization = OrganizationBuilder().create() self.three_task_ids = [a_string() for i in range(3)] create_tasks(self.three_task_ids) services = [ ServiceBuilder(self.organization).create() for i in range(3) ] self.three_service_ids = [service.id for service in services]
def test_does_not_remove_numbers_that_are_not_phone_numbers(self): description_with_numbers = 'In 2017 the Canadian population was approximately 36,710,0000.' expected_description = ( 'In 2017 the Canadian population was approximately 36,710,0000.') ServiceBuilder(self.organization).with_description( description_with_numbers).create() _, descriptions = to_service_ids_and_descriptions( Service.objects.all()) self.assertIn(expected_description, descriptions[0])
def test_can_order_by_similarity_to_task(self): task_id = 'the-task-id' create_tasks([task_id]) similar_service = ServiceBuilder(self.organization).with_location( self.location).create() dissimilar_service = ServiceBuilder(self.organization).with_location( self.location).create() self.set_service_similarity_score(task_id, similar_service.id, 0.9) self.set_service_similarity_score(task_id, dissimilar_service.id, 0.1) url = '/v1/services_at_location/?related_to_task={0}'.format(task_id) json = self.client.get(url).json() self.assertEqual(len(json), 2) self.assertEqual(json[0]['service']['name'], similar_service.name) self.assertEqual(json[1]['service']['name'], dissimilar_service.name)
def test_removes_phone_numbers_beginning_with_plus_sign_from_description( self): description_with_phone_numbers = 'Call +1-800-123-4567 or +604-123-4567 for more information.' description_without_phone_numbers = ('Call or for more information.') ServiceBuilder(self.organization).with_description( description_with_phone_numbers).create() _, descriptions = to_service_ids_and_descriptions( Service.objects.all()) self.assertIn(description_without_phone_numbers, descriptions[0])
def test_getting_description_for_service_returns_name_and_description( self): name = a_string() description = a_string() ServiceBuilder(self.organization).with_name(name).with_description( description).create() _, descriptions = to_service_ids_and_descriptions( Service.objects.all()) self.assertEqual(descriptions[0], name + ' ' + description)
def test_can_reverse_order_by_one_of_two_fields(self): ServiceBuilder(self.organization).with_description('bbb').create() ServiceBuilder(self.organization).with_description('bbb').create() ServiceBuilder(self.organization).with_description('bbb').create() ServiceBuilder(self.organization).with_description('ccc').create() ServiceBuilder(self.organization).with_description('aaa').create() response = self.client.get('/v1/services/?sort_by=description+-name') first, second, third, fourth, fifth = response.json() self.assertLess(first['description'], second['description']) self.assertEqual(second['description'], third['description']) self.assertEqual(third['description'], fourth['description']) self.assertLess(fourth['description'], fifth['description']) self.assertGreater(second['name'], third['name']) self.assertGreater(third['name'], fourth['name'])
def test_full_text_search_returns_service_with_exact_match_on_name(self): the_name = a_string() ServiceBuilder(self.organization).with_name(the_name).create() url = '/v1/services/?search={0}'.format(the_name) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['name'], the_name)
def test_has_locations_attribute(self): service = ServiceBuilder(self.organization).build() validate_save_and_reload(service) location = LocationBuilder(self.organization).build() validate_save_and_reload(location) service_at_location = ServiceLocationBuilder(service, location).build() validate_save_and_reload(service_at_location) self.assertEqual(service.locations.first(), location)
def test_taxonomy_search_returns_service(self): taxonomy_term = TaxonomyTermBuilder().create() service = ServiceBuilder(self.organization).with_taxonomy_terms([taxonomy_term]).create() url = '/v1/services/?taxonomy_terms={0}.{1}'.format(taxonomy_term.taxonomy_id, taxonomy_term.name) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['id'], service.id)
def test_full_text_search_is_case_insensitive(self): the_name = 'FooBar' the_search_term = 'foobar' ServiceBuilder(self.organization).with_name(the_name).create() url = '/v1/services/?search={0}'.format(the_search_term) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['name'], the_name)
def test_full_text_search_returns_service_with_substring_match_to_description(self): part_of_the_description = a_string() the_description = part_of_the_description + a_string() ServiceBuilder(self.organization).with_description(the_description).create() url = '/v1/services/?search={0}'.format(part_of_the_description) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['description'], the_description)
def test_can_combine_taxonomic_search_and_full_text_search(self): the_search_term = a_string() the_taxonomy_term = TaxonomyTermBuilder().create() a_service = (ServiceBuilder(self.organization). with_name(the_search_term + a_string()). with_taxonomy_terms([the_taxonomy_term]). create()) ServiceBuilder(self.organization).with_taxonomy_terms([the_taxonomy_term]).create() ServiceBuilder(self.organization).with_name(the_search_term + a_string()).create() url = '/v1/services/?search={0}&taxonomy_terms={1}.{2}'.format(the_search_term, the_taxonomy_term.taxonomy_id, the_taxonomy_term.name) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['name'], a_service.name)
def test_taxonomy_search_with_wrong_taxonomy_term_returns_empty_array(self): taxonomy_term = TaxonomyTermBuilder().create() wrong_taxonomy_term = TaxonomyTermBuilder().create() ServiceBuilder(self.organization).with_taxonomy_terms([taxonomy_term]).create() url = '/v1/services/?taxonomy_terms={0}.{1}'.format(taxonomy_term.taxonomy_id, wrong_taxonomy_term.name) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 0)
def test_deletes_existing_records(self): task_id = a_string() Task(id=task_id, name=a_string(), description=a_string()).save() service = ServiceBuilder(self.organization).create() record = TaskServiceSimilarityScore(task_id=task_id, service=service, similarity_score=a_float()) record.save() save_task_service_similarity_scores([], [], [], 0) self.assertEqual(TaskServiceSimilarityScore.objects.count(), 0)
def test_can_retrieve_service_under_given_location_and_organization(self): service_with_wrong_location = ServiceBuilder(self.first_organization).create() add_service_to_location(service_with_wrong_location, self.second_location) service_with_wrong_organization = ServiceBuilder(self.second_organization).create() add_service_to_location(service_with_wrong_organization, self.first_location) url = '/v1/organizations/{0}/locations/{1}/services/'.format(self.first_organization.id, self.first_location.id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['name'], self.first_service.name) url = '/v1/locations/{0}/organizations/{1}/services/'.format(self.first_location.id, self.first_organization.id) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.json()), 1) self.assertEqual(response.json()[0]['name'], self.first_service.name)
def test_can_create_row(self): organization = OrganizationBuilder().create() service = ServiceBuilder(organization).create() task_id = a_string() score = a_float() create_tasks([task_id]) score_record = TaskServiceSimilarityScore(task_id=task_id, service=service, similarity_score=score) score_record_from_db = validate_save_and_reload(score_record) self.assertEqual(score_record_from_db.task_id, task_id) self.assertEqual(score_record_from_db.service_id, service.id) self.assertAlmostEqual(score_record_from_db.similarity_score, score)