diff options
-rw-r--r-- | ishtar_common/tests.py | 481 |
1 files changed, 480 insertions, 1 deletions
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index a7cc8361c..71bf38f28 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -39,7 +39,15 @@ from django.apps import apps from django.conf import settings from django.contrib.auth.models import User, Permission from django.contrib.contenttypes.models import ContentType -from django.contrib.gis.geos import GEOSGeometry +from django.contrib.gis.geos import ( + GEOSGeometry, + Point, + MultiPoint, + LineString, + MultiLineString, + Polygon, + MultiPolygon +) from django.core.cache import cache from django.core.exceptions import ValidationError from django.core.files import File as DjangoFile @@ -84,6 +92,7 @@ from ishtar_common.utils import ( move_dict_data, rename_and_simplify_media_name, try_fix_file, + reverse_coordinates, ) from ishtar_common.tasks import launch_export from ishtar_common import utils_secretary @@ -2833,6 +2842,476 @@ class IshtarBasicTest(TestCase): self.assertEqual(town.cached_label, "Sin City - 99 (2050)") +class GeoVectorTest(TestCase): + fixtures = FILE_FIXTURES + + def setUp(self): + Operation = apps.get_model("archaeological_operations", "Operation") + self.username, self.password, self.user = create_superuser() + self.ct = ContentType.objects.get_for_model(models.GeoVectorData) + operation_type = models.OperationType.objects.get(txt_idx="arch_diagnostic") + dct = { + "year": 2010, + "operation_type_id": operation_type.pk, + "history_modifier": self.user, + "code_patriarche": 99999 + } + self.operation = Operation.objects.create(**dct) + + self.origin = models.GeoOriginType.objects.get( + txt_idx="georeferencement", + ) + self.data_type = models.GeoDataType.objects.get( + txt_idx="operation-center", + ) + self.provider = models.GeoProviderType.objects.get( + txt_idx="france-ign", + ) + self.srs, _ = models.SpatialReferenceSystem.objects.get_or_create( + label="EPSG-27572", + txt_idx="epsg-27572", + srid=2154 + ) + self.app_source = "archaeological_operations" + self.model_source = "operation" + self.source_pk = self.operation.pk + + def _test_get_create_geo(self, c, geom_type): + response = c.get(reverse( + "create-geo", + kwargs={ + "app_source": self.app_source, + "model_source": self.model_source, + "source_pk": self.source_pk, + "geom_type": geom_type + } + )) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self.assertIn("id_name", content) + self.assertIn("id_origin", content) + self.assertIn("id_data_type", content) + self.assertIn("id_provider", content) + self.assertIn("id_comment", content) + return content + + def _test_fields_geo_coordinates(self, edited_geo): + self.assertEqual(edited_geo.x, 1.3) + self.assertEqual(edited_geo.y, 3.4) + self.assertEqual(edited_geo.z, 4.4) + self.assertEqual(edited_geo.estimated_error_x, 0.1) + self.assertEqual(edited_geo.estimated_error_y, 0.1) + self.assertEqual(edited_geo.estimated_error_z, 0.1) + self.assertEqual( + edited_geo.spatial_reference_system, + self.srs + ) + + def _test_post_geo(self, c, geom_type, data, geo_vector=None): + if geo_vector: + response = c.post(reverse( + "edit-geo", + kwargs={ + "pk": geo_vector.pk, + } + ), data) + else: + response = c.post(reverse( + "create-geo", + kwargs={ + "app_source": self.app_source, + "model_source": self.model_source, + "source_pk": self.source_pk, + "geom_type": geom_type + } + ), data) + edited_geo = models.GeoVectorData.objects.get( + name="Test Geo {}".format(geom_type) + ) + self.assertRedirects(response, "/geo/edit/{}/".format(edited_geo.pk)) + self.assertEqual(edited_geo.name, "Test Geo {}".format(geom_type)) + self.assertEqual(edited_geo.origin, self.origin) + self.assertEqual(edited_geo.data_type, self.data_type) + self.assertEqual(edited_geo.provider, self.provider) + self.assertEqual(edited_geo.comment, "This is a comment") + self.assertEqual(edited_geo, self.operation.geodata.last()) + return edited_geo + + def _update_data_coordinates(self, data): + data.update({ + "x": 1.3, + "y": 3.4, + "z": 4.4, + "estimated_error_x": 0.1, + "estimated_error_y": 0.1, + "estimated_error_z": 0.1, + "spatial_reference_system": self.srs.pk, + }) + return data + + def _init_default_data(self, geom_type): + data = { + f"related_items_{self.app_source}_{self.model_source}": self.operation.pk, + "name": "Test Geo {}".format(geom_type), + "origin": self.origin.pk, + "data_type": self.data_type.pk, + "provider": self.provider.pk, + "comment": "This is a comment", + } + return data + + def test_create_geo_vector(self): + c = Client() + c.login(username=self.username, password=self.password) + response = c.get(reverse( + "create-pre-geo", + kwargs={ + "app_source": self.app_source, + "model_source": self.model_source, + "source_pk": self.source_pk, + } + )) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self.assertIn("coordinates", content) + self.assertIn("point_2d", content) + self.assertIn("point_3d", content) + self.assertIn("multi_points", content) + self.assertIn("multi_line", content) + self.assertIn("multi_polygon", content) + + def test_create_geo_vector_coordinates(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "coordinates" + + content = self._test_get_create_geo(c, geom_type) + self.assertIn("id_x", content) + self.assertIn("id_y", content) + self.assertIn("id_z", content) + self.assertIn("id_estimated_error_x", content) + self.assertIn("id_estimated_error_y", content) + self.assertIn("id_estimated_error_z", content) + self.assertIn("id_spatial_reference_system", content) + self._test_post_create_pre_geo(c, geom_type) + + data = self._init_default_data(geom_type) + data = self._update_data_coordinates(data) + edited_geo = self._test_post_geo(c, geom_type, data) + self._test_fields_geo_coordinates(edited_geo) + + def test_create_geo_vector_point2d(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "point_2d" + point_2d = Point(3.8, 3, srid=4326) + + content = self._test_get_create_geo(c, geom_type) + + self.assertIn("id_point_2d", content) + self._test_post_create_pre_geo(c, geom_type) + data = self._init_default_data(geom_type) + data.update({geom_type: reverse_coordinates(point_2d.ewkt)}) + edited_geo = self._test_post_geo(c, geom_type, data) + self.assertEqual(edited_geo.point_2d.coords, point_2d.coords) + self.assertEqual(edited_geo.point_2d.srid, point_2d.srid) + + def test_create_geo_vector_point3d(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "point_3d" + point = Point(3.8, 3, 10, srid=4326) + + content = self._test_get_create_geo(c, geom_type) + self.assertIn("id_point_3d", content) + self.assertIn("id_z", content) + self._test_post_create_pre_geo(c, geom_type) + data = self._init_default_data(geom_type) + data.update({ + "point_3d": reverse_coordinates(point.ewkt), + "z": 10 + }) + edited_geo = self._test_post_geo(c, geom_type, data) + self.assertEqual(edited_geo.point_3d.coords, point.coords) + self.assertEqual(edited_geo.point_3d.srid, point.srid) + self.assertEqual(edited_geo.z, 10) + + def test_create_geo_vector_multipoints(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "multi_points" + points = MultiPoint(Point(3.8, 3), Point(7.8, 5), srid=4326) + + content = self._test_get_create_geo(c, geom_type) + + self.assertIn("id_multi_points", content) + self._test_post_create_pre_geo(c, geom_type) + data = self._init_default_data(geom_type) + data.update({geom_type: points.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data) + self.assertEqual( + list(edited_geo.multi_points.coords), + [tuple(reversed(t)) for t in points.coords] + ) + self.assertEqual(edited_geo.multi_points.srid, 4326) + + def test_create_geo_vector_multilines(self): + c = Client() + c.login(username=self.username, password=self.password) + lines = MultiLineString( + LineString(Point(1, 1), Point(2, 2)), + LineString(Point(3, 3), Point(4, 4)), + srid=4326 + ) + geom_type = "multi_line" + + content = self._test_get_create_geo(c, geom_type) + + self.assertIn("id_multi_line", content) + self._test_post_create_pre_geo(c, geom_type) + data = self._init_default_data(geom_type) + data.update({geom_type: lines.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data) + self.assertEqual( + list(edited_geo.multi_line.coords), + [tuple(t[::-1] for t in tu) for tu in lines.coords] + ) + self.assertEqual(edited_geo.multi_line.srid, 4326) + + def test_create_geo_vector_multipolygon(self): + c = Client() + c.login(username=self.username, password=self.password) + multi_polygon = MultiPolygon( + Polygon(((1, 1), (5, 1), (5, 5), (1, 1))), + Polygon(((2, 2), (2, 3), (3, 3), (2, 2))), + srid=4326 + ) + geom_type = "multi_polygon" + + content = self._test_get_create_geo(c, geom_type) + self.assertIn("id_multi_polygon", content) + self._test_post_create_pre_geo(c, geom_type) + data = self._init_default_data(geom_type) + data.update({geom_type: multi_polygon.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data) + self.assertEqual( + list(edited_geo.multi_polygon.coords), + [tuple(tuple(t[::-1] for t in tu) for tu in tup) for tup in multi_polygon.coords] + ) + self.assertEqual(edited_geo.multi_polygon.srid, 4326) + + def test_edit_geo_vector_coordinates(self): + c = Client() + c.login(username=self.username, password=self.password) + + geom_type = "coordinates" + geo_vector = self._create_geo(geom_type) + geo_vector.x = 10.3 + geo_vector.y = 32.4 + geo_vector.z = 44.4 + geo_vector.estimated_error_x = geo_vector.estimated_error_y = geo_vector.estimated_error_z = 2.43 + geo_vector.spatial_reference_system = self.srs + geo_vector.save() + + response = c.get(reverse("edit-geo", kwargs={"pk": geo_vector.pk})) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self._test_get_edit_geo(geo_vector, content) + self.assertIn(self.srs.label, content) + data = self._init_default_data(geom_type) + data = self._update_data_coordinates(data) + edited_geo = self._test_post_geo(c, geom_type, data, geo_vector) + self._test_fields_geo_coordinates(edited_geo) + + def test_edit_geo_vector_point2d(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "point_2d" + point_2d = Point(3.9, 3, srid=4326) + point_2d_for_edit = Point(6, 9.2, srid=4326) + geo_vector = self._create_geo(geom_type) + geo_vector.point_2d = point_2d + geo_vector.save() + + response = c.get(reverse("edit-geo", kwargs={"pk": geo_vector.pk})) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self._test_get_edit_geo(geo_vector, content) + data = self._init_default_data(geom_type) + data.update({geom_type: point_2d_for_edit.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data, geo_vector) + # Old version of django reverse coordinates + self.assertEqual(edited_geo.point_2d.coords, point_2d_for_edit.coords[::-1]) + self.assertEqual(edited_geo.point_2d.srid, point_2d_for_edit.srid) + + def test_edit_geo_vector_point3d(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "point_3d" + point_3d = Point(3.9, 3, -40, srid=4326) + point_for_edit = Point(6, 9.2, 20, srid=4326) + geo_vector = self._create_geo(geom_type) + geo_vector.point_3d = point_3d + geo_vector.z = -40 + geo_vector.save() + + response = c.get(reverse("edit-geo", kwargs={"pk": geo_vector.pk})) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self._test_get_edit_geo(geo_vector, content) + data = self._init_default_data(geom_type) + data.update({"z": 20}) + data.update({geom_type: reverse_coordinates(point_for_edit.ewkt)}) + edited_geo = self._test_post_geo(c, geom_type, data, geo_vector) + # Old version of django reverse coordinates + self.assertEqual(edited_geo.point_3d.coords, point_for_edit.coords) + self.assertEqual(edited_geo.point_3d.srid, point_for_edit.srid) + self.assertEqual(edited_geo.z, 20) + + def test_edit_geo_vector_multipoints(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "multi_points" + points = MultiPoint(Point(34.9, 20.2), Point(64.2, 58.21), srid=4326) + points_edit = MultiPoint(Point(3.8, 3), Point(7.8, 5), srid=4326) + geo_vector = self._create_geo(geom_type) + geo_vector.multi_points = points + geo_vector.save() + + response = c.get(reverse("edit-geo", kwargs={"pk": geo_vector.pk})) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self._test_get_edit_geo(geo_vector, content) + data = self._init_default_data(geom_type) + data.update({geom_type: points_edit.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data, geo_vector) + # Old version of django reverse coordinates + self.assertEqual( + list(edited_geo.multi_points.coords), + [tuple(reversed(t)) for t in points_edit.coords] + ) + self.assertEqual(edited_geo.multi_points.srid, 4326) + + def test_edit_geo_vector_multilines(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "multi_line" + lines = MultiLineString( + LineString(Point(4, 5), Point(5, 10)), + LineString(Point(10, 49), Point(40, 1)), + srid=4326 + ) + lines_edit = MultiLineString( + LineString(Point(3, 2), Point(1, 2)), + LineString(Point(4, 5), Point(6, 7)), + srid=4326 + ) + geo_vector = self._create_geo(geom_type) + geo_vector.multi_line = lines + geo_vector.save() + + response = c.get(reverse("edit-geo", kwargs={"pk": geo_vector.pk})) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self._test_get_edit_geo(geo_vector, content) + data = self._init_default_data(geom_type) + data.update({geom_type: lines_edit.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data, geo_vector) + # Old version of django reverse coordinates + self.assertEqual( + list(edited_geo.multi_line.coords), + [tuple(t[::-1] for t in tu) for tu in lines_edit.coords] + ) + self.assertEqual(edited_geo.multi_line.srid, 4326) + + def test_edit_geo_vector_multipolygon(self): + c = Client() + c.login(username=self.username, password=self.password) + geom_type = "multi_polygon" + multi_polygon = MultiPolygon( + Polygon(((0, 0), (0, 1), (1, 1), (0, 0))), + Polygon(((1, 1), (1, 2), (2, 2), (1, 1))), + srid=4326 + ) + multi_polygon_edit = MultiPolygon( + Polygon(((1, 1), (5, 1), (5, 5), (1, 1))), + Polygon(((2, 2), (2, 3), (3, 3), (2, 2))), + srid=4326 + ) + geo_vector = self._create_geo(geom_type) + geo_vector.multi_polygon = multi_polygon + geo_vector.save() + + response = c.get(reverse("edit-geo", kwargs={"pk": geo_vector.pk})) + self.assertEqual(response.status_code, 200) + content = response.content.decode() + self._test_get_edit_geo(geo_vector, content) + data = self._init_default_data(geom_type) + data.update({geom_type: multi_polygon_edit.ewkt}) + edited_geo = self._test_post_geo(c, geom_type, data, geo_vector) + # Old version of django reverse coordinates + self.assertEqual( + list(edited_geo.multi_polygon.coords), + [tuple(tuple(t[::-1] for t in tu) for tu in tup) for tup in multi_polygon_edit.coords] + ) + self.assertEqual(edited_geo.multi_polygon.srid, 4326) + + def _test_get_edit_geo(self, geo_vector, content): + geo_vector_dict = geo_vector.__dict__ + + self.assertIn(self.operation.name, content) + for field in geo_vector_dict: + val = geo_vector_dict[field] + if ( + # Exclude fields not in form + # Must be careful if GeoVectorData models is modified + # and important boolean fields are added + val is not None and + type(val) is not bool and + field.startswith(("_", "id", "cached")) == False and + field.endswith("_id") == False + ): + self.assertIn(f"id_{field}", content) + if isinstance(val, GEOSGeometry): + # TODO: need to know how osmwidget convert coordinates + self.assertIn(str(val.srid), content) + else: + self.assertIn(str(val), content) + + def _create_geo(self, geom_type): + geo_vector = models.GeoVectorData.objects.create( + source_content_type_id=self.source_pk, + source_id=self.source_pk, + name=f"Before edition geo {geom_type}", + origin=self.origin, + data_type=self.data_type, + provider=self.provider, + comment="This is a comment not edited." + ) + return geo_vector + + def _test_post_create_pre_geo(self, c, geom_type): + data_pre_geo = {"geom_type": geom_type} + response = c.post(reverse( + "create-pre-geo", + kwargs={ + "app_source": self.app_source, + "model_source": self.model_source, + "source_pk": self.source_pk, + } + ), data_pre_geo) + + self.assertRedirects( + response, + "/geo/create/{}/{}/{}/{}/".format( + self.app_source, + self.model_source, + self.source_pk, + geom_type + ) + ) + + class NewItems(TestCase): fixtures = COMMON_FIXTURES |