def test_features_filter_by_properties_with_several_string_field(self): layer = LayerFactory() FeatureFactory( layer=layer, geom=self.fake_geometry, properties={ 'text': 'foobar', 'sentence': 'foobar is here' }, ) FeatureFactory( layer=layer, geom=self.fake_geometry, properties={ 'text': 'foo', 'sentence': 'foobar is missing' }, ) FeatureFactory( layer=layer, geom=self.fake_geometry, properties={ 'text': 'foobar', 'sentence': 'foobar is here' }, ) response = self.client.get( reverse('feature-list', kwargs={'layer': layer.pk}), { 'properties__text': 'foobar', 'properties__sentence': 'foobar is here' }) self.assertEqual(response.status_code, status.HTTP_200_OK) json_response = response.json() self.assertEqual(len(json_response), 2)
def test_relation(self, mock_relation): mock_relation.return_value = True city_cover = FeatureFactory(layer=self.layer_city, geom='POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))') intersect_relation = LayerRelation.objects.create( relation_type='intersects', origin=self.layer_trek, destination=self.layer_city, ) url = reverse('feature-relation', args=(self.layer_trek.pk, self.trek.identifier, intersect_relation.pk)) # city cover should be present after sync self.trek.sync_relations(intersect_relation.pk) response = self.client.get(url, data={'page_size': 1}) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 1, data) # city cover should not be present after deletion city_cover.delete() response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 0, data)
def setUp(self) -> None: self.property_key = 'logo' self.feature_without_file_name = FeatureFactory( properties={ self.property_key: 'data:image/png;base64,xxxxxxxxxxxxxxxxxxxxxxxxxx==' } ) self.feature_without_file_data = FeatureFactory( properties={ self.property_key: None } ) self.crud_view = factories.CrudViewFactory( layer__schema={ 'properties': { self.property_key: { "type": "string", "format": 'data-url', } } } ) self.feature_with_file_name = FeatureFactory( layer=self.crud_view.layer, properties={ self.property_key: 'data:image/png;name=toto.png;base64,xxxxxxxxxxxxxxxxxxxxxxxxxx==' } )
def setUp(self) -> None: self.property_key = 'logo' self.feature_without_file_name = FeatureFactory( properties={ self.property_key: 'data:image/png;base64,xxxxxxxxxxxxxxxxxxxxxxxxxx==' } ) self.feature_without_file_data = FeatureFactory( properties={ self.property_key: None } ) self.crud_view = factories.CrudViewFactory( layer__schema={ 'properties': { self.property_key: { "type": "string", "format": 'data-url', } } } ) self.feature_with_file_name = FeatureFactory( layer=self.crud_view.layer, properties={ self.property_key: 'data:image/png;name=toto.png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII=' } )
def setUp(self) -> None: self.layer_trek = LayerSchemaFactory( geom_type=GeometryTypes.LineString) self.layer_city = LayerSchemaFactory(geom_type=GeometryTypes.Polygon) self.trek = FeatureFactory(layer=self.layer_trek, geom='LINESTRING(0 0, 1 1, 2 2, 3 3)') self.city_cover = FeatureFactory( layer=self.layer_city, geom='POLYGON((0 0, 0 3, 3 3, 3 0, 0 0))') self.city_uncover = FeatureFactory( layer=self.layer_city, geom='POLYGON((4 4, 4 7, 7 7, 7 4, 4 4))')
def test_shapefile_same_import_export(self): FeatureFactory(layer=self.layer, properties={'key1': [{ 'key3': 'hello world', }]}) shape_url = reverse('layer-shapefile', args=[ self.layer.pk, ]) response = self.client.get(shape_url) self.assertEqual(HTTP_200_OK, response.status_code) shapefile = SimpleUploadedFile('shapefile-WGS84.zip', response.content) new_layer = LayerFactory() response = self.client.post(reverse('layer-shapefile', args=[ new_layer.pk, ]), { 'shapefile': shapefile, }, format="multipart") self.assertEqual(HTTP_200_OK, response.status_code) self.assertEqual(self.layer.features.first().properties, new_layer.features.first().properties)
def test_features_intersections(self): layer = LayerFactory() FeatureFactory(layer=layer, geom=GEOSGeometry( json.dumps(self.intersect_ref_geometry))) """The layer below must intersect""" response = self.client.post( reverse('layer-intersects', args=[ layer.pk, ]), {'geom': json.dumps(self.intersect_geometry)}) self.assertEqual(HTTP_200_OK, response.status_code) response = response.json().get('results', {}) self.assertEqual(1, len(response.get('features'))) self.assertDictEqual(self.intersect_ref_geometry, response.get('features')[0].get('geometry')) """The layer below must NOT intersect""" response = self.client.post( reverse('layer-intersects', args=[ layer.name, ]), {'geom': json.dumps(self.fake_geometry)}) self.assertEqual(HTTP_200_OK, response.status_code) response = response.json().get('results', {}) self.assertEqual(0, len(response.get('features'))) """Tests that the intersects view throw an error if geometry is invalid """ response = self.client.post( reverse('layer-intersects', args=[ layer.pk, ]), {'geom': '''Invalid geometry'''}) self.assertEqual(HTTP_400_BAD_REQUEST, response.status_code)
def test_no_permission(self): FeatureFactory(layer=self.layer, properties={'a': 'b'}) response = self.client.patch( reverse('layer-detail', args=[self.layer.name, ]), {}) self.assertEqual(HTTP_403_FORBIDDEN, response.status_code)
def test_layer_processing_clear_output(self): geojson = get_files_tests('toulouse.geojson') call_command( 'import_geojson', f'{geojson}', verbosity=0) # Retrieve the layer in_layer = Layer.objects.first() out_layer = LayerFactory(name='out') FeatureFactory(layer=out_layer, properties="Test") self.assertEqual(out_layer.features.count(), 1) call_command( 'layer_processing', f'--layer-name-ins={in_layer.name}', f'--layer-pk-out={out_layer.pk}', f'--sql-centroid', f'-co', verbosity=0) out_layer = Layer.objects.get(name='out') self.assertTrue(out_layer.features.count() > 1) self.assertNotIn('Test', [feature.properties for feature in out_layer.features.all()])
def test_edit_extra_features_bad_geom(self): feature = FeatureFactory( layer=self.layer, geom=GEOSGeometry(json.dumps(self.linestring)), properties={ 'number': 1, 'text': 'bar' }, ) layer_extra_geom = LayerExtraGeom.objects.create( layer=self.layer, geom_type=GeometryTypes.Point, title='Test') extra_feature = FeatureExtraGeom.objects.create( layer_extra_geom=layer_extra_geom, feature=feature, geom=GEOSGeometry(json.dumps(self.point))) feature.extra_geometries.add(extra_feature) response = self.client.put(reverse('feature-detail-extra-geometry', kwargs={ 'layer': str(self.layer.name), 'identifier': str(feature.identifier), 'id_extra_feature': extra_feature.pk }), data={'geom': "WRONG_GEOM"}) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) json_response = response.json() self.assertEqual( json_response, { 'geom': [ 'Unable to convert to python object: ' 'String input unrecognized as WKT EWKT, and HEXEWKB.' ] })
def test_get_extra_features(self): feature = FeatureFactory( layer=self.layer, geom=GEOSGeometry(json.dumps(self.linestring)), properties={ 'number': 1, 'text': 'bar' }, ) layer_extra_geom = LayerExtraGeom.objects.create( layer=self.layer, geom_type=GeometryTypes.Point, title='Test') extra_feature = FeatureExtraGeom.objects.create( layer_extra_geom=layer_extra_geom, feature=feature, geom=GEOSGeometry(json.dumps(self.point))) feature.extra_geometries.add(extra_feature) response = self.client.get( reverse('feature-detail-extra-geometry', kwargs={ 'layer': str(self.layer.name), 'identifier': str(feature.identifier), 'id_extra_feature': extra_feature.pk })) self.assertEqual(response.status_code, status.HTTP_200_OK) json_response = response.json() self.assertEqual( json_response, { 'id': extra_feature.pk, 'geom': { 'type': 'Point', 'coordinates': [1.44, 43.6] } })
def test_delete_extra_feature_not_editable(self): feature = FeatureFactory( layer=self.layer, geom=GEOSGeometry(json.dumps(self.linestring)), properties={ 'number': 1, 'text': 'bar' }, ) layer_extra_geom = LayerExtraGeom.objects.create( layer=self.layer, geom_type=GeometryTypes.Point, title='Test', editable=False) extra_feature = FeatureExtraGeom.objects.create( layer_extra_geom=layer_extra_geom, feature=feature, geom=GEOSGeometry(json.dumps(self.point))) self.assertEqual(feature.extra_geometries.count(), 1) response = self.client.delete( reverse('feature-detail-extra-geometry', kwargs={ 'layer': str(self.layer.name), 'identifier': str(feature.identifier), 'id_extra_feature': extra_feature.pk })) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) self.assertEqual(feature.extra_geometries.count(), 1)
def test_to_geojson_no_permission(self): # Create at least one feature in the layer, so it's not empty FeatureFactory(layer=self.layer) geojson_url = reverse('layer-geojson', args=[self.layer.pk, ]) response = self.client.get(geojson_url) self.assertEqual(HTTP_403_FORBIDDEN, response.status_code)
def setUpTestData(cls): cls.layer = Layer.objects.create(name='test_layer', geom_type=GeometryTypes.LineString, routable=True) cls.user = UserFactory(is_superuser=True) cls.point_1 = Point(cls.points[0]["coordinates"]) cls.point_2 = Point(cls.points[1]["coordinates"]) cls.out_point_1 = Point(cls.out_points[0]["coordinates"]) cls.out_point_2 = Point(cls.out_points[1]["coordinates"]) cls.out_point_3 = Point(cls.out_points[2]["coordinates"]) cls.point_second_line_1 = Point(cls.points_second_line[0]["coordinates"]) cls.point_second_line_2 = Point(cls.points_second_line[1]["coordinates"]) cls.feature = FeatureFactory.create(geom=LineString([cls.point_1, cls.point_2]), layer=cls.layer) cls.feature_2 = FeatureFactory.create(geom=LineString([cls.point_second_line_1, cls.point_second_line_2]), layer=cls.layer) Routing.update_topology(cls.layer, tolerance=0.0001)
def setUpTestData(cls): # create a geometry undefined layer with all kind of geometry as features props = {"name": "test", "label": "Test"} cls.layer = LayerFactory() cls.point = FeatureFactory(layer=cls.layer, geom="POINT(0 0)", properties=props) cls.line = FeatureFactory(layer=cls.layer, geom="LINESTRING(0 0, 1 1)", properties=props) cls.polygon = FeatureFactory( layer=cls.layer, geom= "POLYGON((0 0, 1 0, 1 1, 0 1, 0 0), (0.4 0.4, 0.5 0.4, 0.5 0.5, 0.4 0.5, 0.4 0.4 ))", properties=props) cls.multipoint = FeatureFactory(layer=cls.layer, geom="MULTIPOINT((0 0), (1 0))", properties=props) cls.multilinestring = FeatureFactory( layer=cls.layer, geom="MULTILINESTRING((3 4,10 50,20 25),(-5 -8,-10 -8,-15 -4))", properties=props) cls.multipolygon = FeatureFactory( layer=cls.layer, geom= "MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2)),((6 3,9 2,9 4,6 3)))", properties=props) cls.geometrycollection = FeatureFactory( layer=cls.layer, geom="GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))", properties=props)
def test_features_filter_by_properties_with_wrong_field(self): layer = LayerFactory() FeatureFactory( layer=layer, geom=self.fake_geometry, properties={'number': 1}, ) FeatureFactory( layer=layer, geom=self.fake_geometry, properties={'number': 2}, ) response = self.client.get( reverse('feature-list', kwargs={'layer': layer.pk}), {'properties__wrongfield': 'wrong value'}, ) self.assertEqual(response.status_code, status.HTTP_200_OK) json_response = response.json() self.assertEqual(len(json_response), 0)
def test_geojson_renderer(self): FeatureFactory.create_batch(50, layer=self.layer, geom=self.fake_geometry, properties={ 'test': 'name', 'name': 'test' }) response = self.client.get( reverse('feature-list', kwargs={ 'layer': self.layer.pk, 'format': 'geojson' })) self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertListEqual(sorted(list(('features', 'type'))), sorted(list(data.keys()))) self.assertEqual(data['type'], "FeatureCollection") self.assertEqual(len(data['features']), self.layer.features.count())
def test_to_geojson(self): # Create at least one feature in the layer, so it's not empty FeatureFactory(layer=self.layer) FeatureFactory( layer=self.layer, geom=GEOSGeometry(json.dumps(self.fake_geometry)), properties={ 'number': 1, 'digit': 34 }, ) geojson = json.loads(self.layer.to_geojson()) self.assertEqual( str(geojson['features'][0]['geometry']), "{'type': 'Point', 'coordinates': [2.4609375, 45.583289756006316]}" ) self.assertEqual(str(geojson['features'][1]['geometry']), "{'type': 'Point', 'coordinates': [2.0, 45.0]}") self.assertEqual(str(geojson['features'][1]['properties']), "{'digit': 34, 'number': 1}")
def setUp(self) -> None: self.layer_trek = LayerSchemaFactory( geom_type=GeometryTypes.LineString) self.layer_city = LayerSchemaFactory(geom_type=GeometryTypes.Polygon) self.trek = FeatureFactory(layer=self.layer_trek, geom='LINESTRING(0 0, 1 1, 2 2, 3 3)') self.city_uncover = FeatureFactory( layer=self.layer_city, geom='POLYGON((4 4, 4 7, 7 7, 7 4, 4 4))', properties={ "name": "Cahors", "age": 50000 }) self.detail_url = reverse('feature-detail', args=( self.layer_city.pk, self.city_uncover.identifier, )) self.super_user = UserFactory(is_superuser=True) self.client.force_authenticate(self.super_user)
def test_shapefile_export(self): # Create at least one feature in the layer, so it's not empty FeatureFactory(layer=self.layer) shape_url = reverse('layer-shapefile', args=[ self.layer.pk, ]) response = self.client.get(shape_url) self.assertEqual(HTTP_200_OK, response.status_code) zip_file = ZipFile(BytesIO(response.content), 'r') self.assertListEqual( sorted(['prj', 'cpg', 'shx', 'shp', 'dbf']), sorted(set([f.split('.')[1] for f in zip_file.namelist()])))
def test_to_geojson(self): # Create at least one feature in the layer, so it's not empty self.user.user_permissions.add(Permission.objects.get(codename='can_export_layers')) FeatureFactory(layer=self.layer) geojson_url = reverse('layer-geojson', args=[self.layer.pk, ]) response = self.client.get(geojson_url) self.assertEqual(HTTP_200_OK, response.status_code) response = response.json() self.assertEqual('FeatureCollection', response.get('type')) self.assertEqual(self.layer.features.all().count(), len(response.get('features')))
def test_features_filter_by_properties(self): layer = LayerFactory() FeatureFactory( layer=layer, geom=self.fake_geometry, properties={ 'number': 1, 'text': 'bar' }, ) FeatureFactory( layer=layer, geom=self.fake_geometry, properties={ 'number': 1, 'text': 'foo' }, ) FeatureFactory( layer=layer, geom=self.fake_geometry, properties={ 'number': 2, 'text': 'foo' }, ) response = self.client.get( reverse('feature-list', kwargs={'layer': layer.pk}), { 'properties__number': 1, 'properties__text': 'foo' }, ) self.assertEqual(response.status_code, status.HTTP_200_OK) json_response = response.json() self.assertEqual(len(json_response), 1)
def test_features_filter_by_properties_with_several_int_field(self): layer = LayerFactory() FeatureFactory( layer=layer, geom=GEOSGeometry(json.dumps(self.fake_geometry)), properties={'number': 2, 'digit': 42}, ) FeatureFactory( layer=layer, geom=GEOSGeometry(json.dumps(self.fake_geometry)), properties={'number': 1, 'digit': 42}, ) FeatureFactory( layer=layer, geom=GEOSGeometry(json.dumps(self.fake_geometry)), properties={'number': 1, 'digit': 34}, ) response = self.client.get( reverse('feature-list', kwargs={'layer': layer.pk}), {'properties__number': 1, 'properties__digit': 42}, ) self.assertEqual(response.status_code, HTTP_200_OK) json_response = response.json() self.assertEqual(len(json_response), 1)
def test_update(self): self.user.user_permissions.add( Permission.objects.get(codename='can_manage_layers')) geom = GEOSGeometry(json.dumps(self.geometry)) feature = FeatureFactory(layer=self.layer, geom=geom, properties={'a': 'b'}) updated_properties = { 'c': 'd', 'a': 'd', } response = self.client.patch(reverse( 'layer-detail', args=[ self.layer.name, ]), { "type": "FeatureCollection", "features": [ { "type": "Feature", 'geometry': self.geometry, 'properties': updated_properties, }, ] }, format='json') self.assertEqual(HTTP_200_OK, response.status_code) response = response.json() self.assertEqual(response['features'][0]['properties'], updated_properties) feature.refresh_from_db() self.assertDictEqual(feature.properties, updated_properties)
def test_feature_from_layer_name(self): layer = LayerFactory() feature = FeatureFactory( layer=layer, geom=GEOSGeometry(json.dumps(self.fake_geometry)), properties={'text': 'foobar', 'sentence': 'foobar is here'}, ) response = self.client.get( reverse( 'feature-detail', kwargs={'layer': str(layer.name), 'identifier': str(feature.identifier)} ), ) self.assertEqual(response.status_code, HTTP_200_OK)
def test_post_extra_layer_do_not_exists(self): feature = FeatureFactory( layer=self.layer, geom=GEOSGeometry(json.dumps(self.linestring)), properties={ 'number': 1, 'text': 'bar' }, ) response = self.client.post( reverse('feature-create-extra-geometry', kwargs={ 'layer': str(self.layer.name), 'identifier': str(feature.identifier), 'id_extra_layer': 999 }), {'geom': json.dumps(self.point)}) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_routing_view_with_polygon(self): """test that a layer with another kind of geometry raise the right exception""" feature = FeatureFactory() points = [Point( *p['coordinates'], srid=app_settings.INTERNAL_GEOMETRY_SRID) for p in [self.points[0], self.points[0]]] geometry = LineString(*points) response = self.client.post(reverse('layer-route', args=[feature.layer.pk]), {'geom': geometry.geojson, }) self.assertEqual(HTTP_400_BAD_REQUEST, response.status_code) error = response.json()['errors'][0] self.assertEqual("Layer is not routable", error)
def setUpTestData(cls): cls.feature = FeatureFactory() cls.user = TerraUserFactory() # Create viewpoint with draft picture attached to it cls.viewpoint = ViewpointFactory(label="Basic viewpoint") # Create viewpoint with accepted picture attached to it cls.viewpoint_with_accepted_picture = ViewpointFactory( label="Viewpoint with accepted picture", pictures__state="accepted", properties={"test_update": "ko"}, active=True, ) # Create viewpoints with no picture attached to it cls.viewpoint_without_picture = ViewpointFactory( label="Viewpoint without picture", pictures=None, properties={"test_update": "ko"}, )
def test_get_extra_layer(self): feature = FeatureFactory( layer=self.layer, geom=GEOSGeometry(json.dumps(self.linestring)), properties={ 'number': 1, 'text': 'bar' }, ) layer_extra_geom = LayerExtraGeom.objects.create( layer=self.layer, geom_type=GeometryTypes.Point, title='Test') response = self.client.get( reverse('feature-create-extra-geometry', kwargs={ 'layer': str(self.layer.name), 'identifier': str(feature.identifier), 'id_extra_layer': layer_extra_geom.pk }), {'geom': json.dumps(self.point)}) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
def test_layer_processing_by_name(self): geojson = get_files_tests('toulouse.geojson') call_command('import_geojson', geojson, verbosity=0) # Retrieve the layer in_layer = Layer.objects.first() out_layer = Layer.objects.create(name='out') FeatureFactory(layer=out_layer, properties="Test") call_command( 'layer_processing', f'--layer-name-ins={in_layer.name}', f'--layer-name-out={out_layer.name}', f'--sql-centroid', verbosity=0) out_layer = Layer.objects.get(name='out') self.assertIn('Test', [feature.properties for feature in out_layer.features.all()]) self.assertTrue(len(out_layer.features.all()) > 0)