Пример #1
0
    def test_performance(self):
        """Count the number of queries required to fetch the centroids."""

        # Make a GeometryStore object without points/lines/polygons/centroid
        # This should not appear in list
        unlocated = GeometryStore()
        unlocated.save()
        # Single point store which doesn't have an associcated project
        # This should not appear in list
        random_point = GeometryStore()
        random_point.save()
        point = PointGeometry(geom=Point(20, 30))
        point.save()
        random_point.points.add(point)
        # Create 9 more (for a total of 10) random point projects for the map
        for i in range(9):
            geo = GeometryStore()
            geo.save()
            point = PointGeometry(geom=Point(20, 30))
            point.save()
            geo.points.add(point)
            project = ProjectFactory(published=True)
            project.geo = geo
            project.save()

        with self.settings(PUBLISH_FILTER_ENABLED=True):
            self.client.logout()
            with self.assertNumQueries(3):
                # All response data should be fetched in a single query
                response = self.client.get(self.list_url)
                self.assertEqual(response.status_code, 200)
            data = json.loads(response.content.decode())
            self.assertEqual(len(data['features']), 10)
Пример #2
0
    def test_project_totals(self):
        """Project totals should be in the homepage context."""

        road = InfrastructureTypeFactory(name='Road', slug='road')
        rail = InfrastructureTypeFactory(name='Railroad', slug='rail')
        # Create 3 road projects, 2 of which are published
        ProjectFactory(infrastructure_type=road, published=True)
        ProjectFactory(infrastructure_type=road, published=True)
        ProjectFactory(infrastructure_type=road, published=False)
        # Create 2 rail projects, 1 of which is published
        ProjectFactory(infrastructure_type=rail, published=True)
        ProjectFactory(infrastructure_type=rail, published=False)
        # Totals should be in the response
        response = self.client.get(self.url)
        self.assertEqual(response.status_code, 200)
        expected = {
            'road': {
                'id': road.pk,
                'count': 2,
                'label': 'Road',
            },
            'rail': {
                'id': rail.pk,
                'count': 1,
                'label': 'Railroad',
            }
        }
        self.assertEqual(response.context['db_totals'], expected)
Пример #3
0
    def setUp(self):
        self.geom_with_published_project = GeometryStore()
        self.geom_with_published_project.save()
        point = PointGeometry(geom=Point(20, 30))
        point.save()
        self.geom_with_published_project.points.add(point)
        self.published_project = ProjectFactory(
            published=True,
            countries=[CountryFactory(), CountryFactory()],
            total_cost=1200000)
        self.published_project.geo = self.geom_with_published_project
        self.published_project.save()

        self.geom_with_unpublished_project = GeometryStore()
        self.geom_with_unpublished_project.save()
        point = PointGeometry(geom=Point(40, 50))
        point.save()
        self.geom_with_unpublished_project.points.add(point)
        self.unpublished_project = ProjectFactory(published=False)
        self.unpublished_project.geo = self.geom_with_unpublished_project
        self.unpublished_project.save()

        self.list_url = reverse('api:geostore-centroids-list')

        self.user = User(username='******', password='******')
        self.user.save()
Пример #4
0
 def setUp(self):
     super().setUp()
     self.project = ProjectFactory(published=True)
     self.other_project = ProjectFactory(published=True)
     self.curated_project_collection = CuratedProjectCollectionFactory(
         published=True, )
     self.curated_project_collection.projects.add(self.project,
                                                  self.other_project)
     self.url = reverse('api:curated-projects-list')
Пример #5
0
    def setUp(self):
        self.geometry_store = GeometryStore()
        self.geometry_store.save()
        point = PointGeometryFactory()
        self.geometry_store.points.add(point)
        self.url = reverse('api:geometrystore-detail',
                           args=[self.geometry_store.identifier])
        # View ignores GeometryStores without projects, so add one
        self.project = ProjectFactory(
            countries=[CountryFactory(), CountryFactory()])
        self.project.geo = self.geometry_store
        self.project.save()

        self.user = User(username='******', password='******')
        self.user.save()
Пример #6
0
    def setUp(self):
        super().setUp()
        self.published_entry_count = 102
        self.published_project_count = 101
        EntryFactory.create_batch(self.published_entry_count, published=True)
        ProjectFactory.create_batch(self.published_project_count,
                                    published=True)
        self.unpublished_entry_count = 14
        self.unpublished_project_count = 6
        EntryFactory.create_batch(self.unpublished_entry_count,
                                  published=False)
        ProjectFactory.create_batch(self.unpublished_project_count,
                                    published=False)

        from django.conf import settings
        self.SEARCH = getattr(settings, 'SEARCH')
        self.PUBLISH_FILTER_ENABLED = getattr(settings,
                                              'PUBLISH_FILTER_ENABLED', True)
Пример #7
0
    def test_project_serializer(self):
        obj = ProjectFactory.create(name='Test title',
                                    countries=CountryFactory.create_batch(4),
                                    status=5)
        serializer = ProjectSerializer()
        doc = serializer.create_document(obj)

        self.assertIsInstance(doc, ProjectDoc)
        self.assertEqual(doc.name, 'Test title')
        self.assertEqual(len(doc.countries), 4)
        self.assertEqual(obj.status, 5)
        # doc should have string representation of choice
        self.assertEqual(obj.get_status_display(), doc.status)
Пример #8
0
    def test_rebuild_index_no_args(self):
        EntryFactory.create_batch(100, published=True)
        ProjectFactory.create_batch(100, published=True)
        num_base_people = 100
        num_employed_people = 120
        total_num_people = num_base_people + num_employed_people
        PersonFactory.create_batch(num_base_people, published=True)
        PositionFactory.create_batch(num_employed_people)

        out = io.StringIO()

        call_command('rebuild_index', stdout=out)

        self.assertIn(
            "Reindexed {} '{}' documents".format(
                100, EntryFactory._meta.model._meta.label), out.getvalue())
        self.assertIn(
            "Reindexed {} '{}' documents".format(
                100, ProjectFactory._meta.model._meta.label), out.getvalue())
        self.assertIn(
            "Reindexed {} '{}' documents".format(
                total_num_people, PersonFactory._meta.model._meta.label),
            out.getvalue())
Пример #9
0
    def test_index_model_multiple_models(self):
        entry_objects = EntryFactory.create_batch(30, published=True)
        project_objects = ProjectFactory.create_batch(20, published=True)

        job = self.queue.enqueue(index_model,
                                 EntryFactory._meta.model._meta.label)

        self.assertEqual(job.result, (30, []))
        self.assertEqual(job.get_status(), 'finished')

        job = self.queue.enqueue(index_model,
                                 ProjectFactory._meta.model._meta.label)

        self.assertEqual(job.result, (20, []))
        self.assertEqual(job.get_status(), 'finished')

        self.index.refresh()

        self.assertEqual(
            len(entry_objects) + len(project_objects), self.search.count())
Пример #10
0
    def test_filters(self):
        included_project = ProjectFactory(published=True)
        included_project.save()
        excluded_project = ProjectFactory(published=True)
        excluded_project.save()

        with self.subTest('no filters'):
            response = self.client.get(self.url)
            returned_projects = [
                result['name']
                for result in json.loads(response.content.decode())['results']
            ]
            self.assertIn(included_project.name, returned_projects)
            self.assertIn(excluded_project.name, returned_projects)

        with self.subTest('filter by funding'):
            funding = ProjectFunding(project=included_project, amount=5)
            funding.save()
            params = {'funding__amount__gte': '4'}
            response = self.client.get(self.url, params)
            returned_projects = [
                result['name']
                for result in json.loads(response.content.decode())['results']
            ]
            self.assertIn(included_project.name, returned_projects)
            self.assertNotIn(excluded_project.name, returned_projects)

        with self.subTest('filter by funding - currency amount'):
            funding = ProjectFunding(project=included_project, amount=5)
            funding.save()
            params = {'funding__currency_amount__gte': '4 USD'}
            response = self.client.get(self.url, params)
            returned_projects = [
                result['name']
                for result in json.loads(response.content.decode())['results']
            ]
            self.assertIn(included_project.name, returned_projects)
            self.assertNotIn(excluded_project.name, returned_projects)
Пример #11
0
    def setUp(self):
        super().setUp()
        self.url = reverse('search:search')
        self.index_patch = patch.object(SiteSearch, 'index',
                                        TEST_SEARCH['default']['index'])
        self.index_patch.start()
        india = CountryFactory(name='India')
        china = CountryFactory(name='China')
        rail_type = InfrastructureTypeFactory(name='Railroad')
        road_type = InfrastructureTypeFactory(name='Road')

        self.china_rail = ProjectFactory(name='China Rail Project',
                                         infrastructure_type=rail_type,
                                         countries=[
                                             china,
                                         ])
        self.china_road = ProjectFactory(name='China Road Project',
                                         infrastructure_type=road_type,
                                         countries=[
                                             china,
                                         ])
        self.india_rail = ProjectFactory(name='India Rail Project',
                                         infrastructure_type=rail_type,
                                         countries=[
                                             india,
                                         ])
        self.india_road = ProjectFactory(name='India Road Project',
                                         infrastructure_type=road_type,
                                         countries=[
                                             india,
                                         ])
        serializer = ProjectSerializer()
        serializer.create_document(self.china_rail).save()
        serializer.create_document(self.china_road).save()
        serializer.create_document(self.india_rail).save()
        serializer.create_document(self.india_road).save()
        self.index.refresh()
Пример #12
0
class TestGeometryStoreDetailView(TestCase):
    def setUp(self):
        self.geometry_store = GeometryStore()
        self.geometry_store.save()
        point = PointGeometryFactory()
        self.geometry_store.points.add(point)
        self.url = reverse('api:geometrystore-detail',
                           args=[self.geometry_store.identifier])
        # View ignores GeometryStores without projects, so add one
        self.project = ProjectFactory(
            countries=[CountryFactory(), CountryFactory()])
        self.project.geo = self.geometry_store
        self.project.save()

        self.user = User(username='******', password='******')
        self.user.save()

    def test_geometrystore_with_no_project(self):
        """
        Without a project, the GeometryStoreDetailView should return a 404
        """
        geometry_store = GeometryStore()
        geometry_store.save()
        point = PointGeometryFactory()
        geometry_store.points.add(point)
        url = reverse('api:geometrystore-detail',
                      args=[geometry_store.identifier])

        with self.subTest('Authenticated'):
            self.client.force_login(self.user)
            response = self.client.get(url)
            self.assertEqual(response.status_code, 404)

        with self.subTest('Anonymous'):
            self.client.logout()
            response = self.client.get(url)
            self.assertEqual(response.status_code, 404)

    def test_published_project(self):
        self.project.published = True
        self.project.save()

        with self.settings(PUBLISH_FILTER_ENABLED=True):
            with self.subTest('Authenticated and PUBLISH_FILTER_ENABLED'):
                self.client.force_login(self.user)
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))

            with self.subTest('Not authenticated, PUBLISH_FILTER_ENABLED'):
                self.client.logout()
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))

        with self.settings(PUBLISH_FILTER_ENABLED=False):
            with self.subTest(
                    'Authenticated and PUBLISH_FILTER_ENABLED == False'):
                self.client.force_login(self.user)
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))

            with self.subTest(
                    'Not authenticated, PUBLISH_FILTER_ENABLED == False'):
                self.client.logout()
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))

    def test_unpublished_project(self):
        self.project.published = False
        self.project.save()

        with self.settings(PUBLISH_FILTER_ENABLED=True):
            with self.subTest('Authenticated and PUBLISH_FILTER_ENABLED'):
                self.client.force_login(self.user)
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))

            with self.subTest('Not authenticated, PUBLISH_FILTER_ENABLED'):
                self.client.logout()
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 404)

        with self.settings(PUBLISH_FILTER_ENABLED=False):
            with self.subTest(
                    'Authenticated and PUBLISH_FILTER_ENABLED == False'):
                self.client.force_login(self.user)
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))

            with self.subTest(
                    'Not authenticated, PUBLISH_FILTER_ENABLED == False'):
                self.client.logout()
                response = self.client.get(self.url)
                self.assertEqual(response.status_code, 200)
                response_locations = [
                    proj['locations'] for proj in response.data['projects']
                ][0]
                self.assertEqual(
                    set(response_locations),
                    set(self.project.countries.values_list('name', flat=True)))
Пример #13
0
class TestGeometryStoreCentroidViewSet(TestCase):
    def setUp(self):
        self.geom_with_published_project = GeometryStore()
        self.geom_with_published_project.save()
        point = PointGeometry(geom=Point(20, 30))
        point.save()
        self.geom_with_published_project.points.add(point)
        self.published_project = ProjectFactory(
            published=True,
            countries=[CountryFactory(), CountryFactory()],
            total_cost=1200000)
        self.published_project.geo = self.geom_with_published_project
        self.published_project.save()

        self.geom_with_unpublished_project = GeometryStore()
        self.geom_with_unpublished_project.save()
        point = PointGeometry(geom=Point(40, 50))
        point.save()
        self.geom_with_unpublished_project.points.add(point)
        self.unpublished_project = ProjectFactory(published=False)
        self.unpublished_project.geo = self.geom_with_unpublished_project
        self.unpublished_project.save()

        self.list_url = reverse('api:geostore-centroids-list')

        self.user = User(username='******', password='******')
        self.user.save()

    def test_centroid_list(self):

        # Make a GeometryStore object without points/lines/polygons/centroid
        # This should not appear in list
        unlocated = GeometryStore()
        unlocated.save()
        # Single point store which doesn't have an associcated project
        # This should not appear in list
        random_point = GeometryStore()
        random_point.save()
        point = PointGeometry(geom=Point(20, 30))
        point.save()
        random_point.points.add(point)

        with self.settings(PUBLISH_FILTER_ENABLED=True):
            with self.subTest('Authenticated and PUBLISH_FILTER_ENABLED'):
                self.client.force_login(self.user)
                response = self.client.get(self.list_url)
                self.assertEqual(response.status_code, 200)
                # Both geometries from setUp should be in the list, but not the one without a centroid.
                data = json.loads(response.content.decode())
                self.assertEqual(len(data['features']), 2)

            with self.subTest('Not authenticated, PUBLISH_FILTER_ENABLED'):
                self.client.logout()
                response = self.client.get(self.list_url)
                self.assertEqual(response.status_code, 200)
                # Only the geometry with a published project should be included.
                data = json.loads(response.content.decode())
                self.assertEqual(len(data['features']), 1)

        with self.settings(PUBLISH_FILTER_ENABLED=False):
            with self.subTest(
                    'Authenticated and PUBLISH_FILTER_ENABLED == False'):
                self.client.force_login(self.user)
                response = self.client.get(self.list_url)
                self.assertEqual(response.status_code, 200)
                # Both geometries from setUp should be in the list, but not the one without a centroid.
                data = json.loads(response.content.decode())
                self.assertEqual(len(data['features']), 2)

            with self.subTest(
                    'Not authenticated, PUBLISH_FILTER_ENABLED == False'):
                self.client.logout()
                response = self.client.get(self.list_url)
                self.assertEqual(response.status_code, 200)
                # Both geometries from setUp should be in the list, but not the one without a centroid.
                data = json.loads(response.content.decode())
                self.assertEqual(len(data['features']), 2)

    def test_response_format(self):
        """Centroids should include related project information in their properties."""

        with self.settings(PUBLISH_FILTER_ENABLED=True):
            self.client.logout()
            response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, 200)
        # Only the geometry with a published project should be included.
        data = json.loads(response.content.decode())
        self.assertEqual(len(data['features']), 1)
        feature = data['features'][0]
        self.assertEqual(
            feature, {
                'id': str(self.geom_with_published_project.identifier),
                'type': 'Feature',
                'geometry': {
                    'type':
                    'Point',
                    'coordinates': [
                        self.geom_with_published_project.centroid.x,
                        self.geom_with_published_project.centroid.y,
                    ],
                },
                'properties': {
                    'label':
                    self.published_project.name,
                    'geostore':
                    str(self.geom_with_published_project.identifier),
                    'icon-image':
                    'dot',
                    'infrastructureType':
                    self.published_project.infrastructure_type.name,
                    "locations":
                    ','.join(
                        self.geom_with_published_project.projects.values_list(
                            'countries__name', flat=True)),
                    "total_cost":
                    self.geom_with_published_project.projects.all()
                    [0].total_cost,
                    "currency":
                    self.geom_with_published_project.projects.all()
                    [0].total_cost_currency,
                }
            })

    def test_performance(self):
        """Count the number of queries required to fetch the centroids."""

        # Make a GeometryStore object without points/lines/polygons/centroid
        # This should not appear in list
        unlocated = GeometryStore()
        unlocated.save()
        # Single point store which doesn't have an associcated project
        # This should not appear in list
        random_point = GeometryStore()
        random_point.save()
        point = PointGeometry(geom=Point(20, 30))
        point.save()
        random_point.points.add(point)
        # Create 9 more (for a total of 10) random point projects for the map
        for i in range(9):
            geo = GeometryStore()
            geo.save()
            point = PointGeometry(geom=Point(20, 30))
            point.save()
            geo.points.add(point)
            project = ProjectFactory(published=True)
            project.geo = geo
            project.save()

        with self.settings(PUBLISH_FILTER_ENABLED=True):
            self.client.logout()
            with self.assertNumQueries(3):
                # All response data should be fetched in a single query
                response = self.client.get(self.list_url)
                self.assertEqual(response.status_code, 200)
            data = json.loads(response.content.decode())
            self.assertEqual(len(data['features']), 10)

    def test_centroid_list_filters(self):
        """
        Test that one can filter by the related project's infrastructure type name,
        which is set as an annoation
        """
        project_type = self.geom_with_published_project.projects.first(
        ).infrastructure_type.name
        with self.subTest('project type match'):
            response = self.client.get(self.list_url,
                                       {'project_type': project_type})
            self.assertEqual(response.status_code, 200)
            data = json.loads(response.content.decode())
            self.assertEqual(len(data['features']), 1)

        with self.subTest('project type not match'):
            response = self.client.get(self.list_url, {'project_type': "FOO"})
            self.assertEqual(response.status_code, 200)
            data = json.loads(response.content.decode())
            self.assertEqual(len(data['features']), 0)
Пример #14
0
class TestSearchViewSet(BaseSearchTestCase):
    def setUp(self):
        super().setUp()
        self.url = reverse('search:search')
        self.index_patch = patch.object(SiteSearch, 'index',
                                        TEST_SEARCH['default']['index'])
        self.index_patch.start()
        india = CountryFactory(name='India')
        china = CountryFactory(name='China')
        rail_type = InfrastructureTypeFactory(name='Railroad')
        road_type = InfrastructureTypeFactory(name='Road')

        self.china_rail = ProjectFactory(name='China Rail Project',
                                         infrastructure_type=rail_type,
                                         countries=[
                                             china,
                                         ])
        self.china_road = ProjectFactory(name='China Road Project',
                                         infrastructure_type=road_type,
                                         countries=[
                                             china,
                                         ])
        self.india_rail = ProjectFactory(name='India Rail Project',
                                         infrastructure_type=rail_type,
                                         countries=[
                                             india,
                                         ])
        self.india_road = ProjectFactory(name='India Road Project',
                                         infrastructure_type=road_type,
                                         countries=[
                                             india,
                                         ])
        serializer = ProjectSerializer()
        serializer.create_document(self.china_rail).save()
        serializer.create_document(self.china_road).save()
        serializer.create_document(self.india_rail).save()
        serializer.create_document(self.india_road).save()
        self.index.refresh()

    def tearDown(self):
        super().tearDown()
        self.index_patch.stop()

    def test_that_view_loads(self):
        """Load search page with no query string."""

        response = self.client.get(self.url)
        self.assertEqual(response.status_code, 200)

    def test_with_search_param(self):
        """Search for objects in the index."""

        with self.subTest('No results'):
            params = {'q': '123'}
            response = self.client.get(self.url, params)
            self.assertContains(response, 'No results found')

        with self.subTest('Find project'):
            self.index.refresh()
            params = {'q': 'China Rail'}
            response = self.client.get(self.url, params)
            self.assertContains(response, self.china_rail.get_absolute_url())

    def test_with_search_facets(self):
        """Narrow results by using facets."""

        with self.subTest('Find all projects'):
            params = {
                'q': 'project',
                'facet': [
                    '_category:Project',
                ],
            }
            response = self.client.get(self.url, params)
            self.assertContains(response, self.china_rail.get_absolute_url())
            self.assertContains(response, self.china_road.get_absolute_url())
            self.assertContains(response, self.india_rail.get_absolute_url())
            self.assertContains(response, self.india_road.get_absolute_url())

        with self.subTest('Find road projects'):
            params = {
                'q': 'project',
                'facet': [
                    '_category:Project',
                    'infrastructure_type:Road',
                ],
            }
            response = self.client.get(self.url, params)
            self.assertNotContains(response,
                                   self.china_rail.get_absolute_url())
            self.assertContains(response, self.china_road.get_absolute_url())
            self.assertNotContains(response,
                                   self.india_rail.get_absolute_url())
            self.assertContains(response, self.india_road.get_absolute_url())

        with self.subTest('Find road projects in China'):
            params = {
                'q':
                'project',
                'facet': [
                    '_category:Project',
                    'infrastructure_type:Road',
                    'project_location:China',
                ],
            }
            response = self.client.get(self.url, params)
            self.assertNotContains(response,
                                   self.china_rail.get_absolute_url())
            self.assertContains(response, self.china_road.get_absolute_url())
            self.assertNotContains(response,
                                   self.india_rail.get_absolute_url())
            self.assertNotContains(response,
                                   self.india_road.get_absolute_url())

    def test_search_pagination(self):
        """User can select page size and the page they want to view."""

        with self.subTest('Change page size'):
            params = {'q': 'project', 'size': '2'}
            response = self.client.get(self.url, params)
            self.assertEqual(response.context['search']['offset'], 0)
            self.assertEqual(response.context['search']['size'], 2)
            self.assertEqual(len(response.context['search']['results']), 2)
            self.assertEqual(response.context['search']['total'], 4)

        with self.subTest('Get next page'):
            params = {
                'q': 'project',
                'size': '2',
                'offset': '2',
            }
            response = self.client.get(self.url, params)
            self.assertEqual(response.context['search']['offset'], 2)
            self.assertEqual(response.context['search']['size'], 2)
            self.assertEqual(len(response.context['search']['results']), 2)
            self.assertEqual(response.context['search']['total'], 4)

        with self.subTest('Invalid page'):
            params = {
                'q': 'project',
                'size': 'foo',
                'offset': 'bar',
            }
            response = self.client.get(self.url, params)
            self.assertEqual(response.context['search']['offset'], 0)
            self.assertEqual(response.context['search']['size'], 20)
            self.assertEqual(len(response.context['search']['results']), 4)
            self.assertEqual(response.context['search']['total'], 4)