""" ARCHES - a program developed to inventory and manage immovable cultural heritage. Copyright (C) 2013 J. Paul Getty Trust and World Monuments Fund This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ import random import os, uuid from django.test import TransactionTestCase from django.test.utils import captured_stdout from django.db import connection, connections from django.core import management from tests.base_test import ArchesTestCase from arches.app.models import models from arches.app.models.models import SpatialView from arches.app.utils.data_management.resources.importer import BusinessDataImporter from tests import test_settings # these tests can be run from the command line via # python manage.py test tests.models.spatialview_model_tests --settings="tests.test_settings" class SpatialViewTests(ArchesTestCase): @classmethod def setUpTestData(cls): super().setUpTestData() spatialviews_other_test_model_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "resource_graphs", "SpatialViews_Other_Model.json", ) spatialviews_test_model_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "resource_graphs", "SpatialViews_Test_Model.json", ) spatialviews_other_test_data_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "data", "json", "Spatialviews_Other_Model_Data.json", ) spatialviews_test_data_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "data", "json", "SpatialViews_Test_Model_Data.json", ) with captured_stdout(): management.call_command("es", operation="index_concepts") management.call_command( "packages", operation="import_graphs", source=spatialviews_other_test_model_path, verbosity=0, ) management.call_command( "packages", operation="import_graphs", source=spatialviews_test_model_path, verbosity=0, ) BusinessDataImporter( spatialviews_other_test_data_path ).import_business_data() BusinessDataImporter(spatialviews_test_data_path).import_business_data() def setUp(self): # test ids self.spatialviews_test_model_id = "5db49c51-2c70-47b3-b7be-66afced863c8" self.spatialviews_other_test_model_id = "114dd3fb-404d-4fb3-a639-1333b89cf60c" self.spatialview_id = "47ddb63e-9d04-4953-910a-b780759c22e9" self.spatialview_geometrynode_id = "95b2c8de-1cf8-11ef-971a-0242ac130005" self.spatialview_invalid_geometrynode_id = ( "7584e966-1cf8-11ef-971a-0242ac130005" ) self.generated_spatialview_ids = [] def find_postgres_views_with_name(self, schema_name, view_name): view_count = 0 with connections[ f"{test_settings.DATABASES['default']['NAME']}" ].cursor() as cursor: cursor.execute( "SELECT viewname FROM pg_views WHERE viewname = %s and schemaname = %s", [view_name, schema_name], ) views = cursor.fetchall() view_count = len(views) return view_count def get_language_instance(self, language): l, created = models.Language.objects.get_or_create(code=language) return l def generate_valid_spatiatview(self): spatialview = SpatialView() spatialview.spatialviewid = uuid.uuid4() spatialview.schema = "public" spatialview.slug = "spatialviews_test_" + str(random.randint(1, 1000)) spatialview.description = "test_description" spatialview.geometrynode = models.Node.objects.get( nodeid=self.spatialview_geometrynode_id ) spatialview.ismixedgeometrytypes = False # Discreet geometry spatialview.language = self.get_language_instance("en") spatialview.isactive = True spatialview.attributenodes = [ { "nodeid": "a379b7ac-1cf8-11ef-ab82-0242ac130005", "description": "gridref", }, {"nodeid": "bee90060-1cf8-11ef-971a-0242ac130005", "description": "name"}, {"nodeid": "ccfe0a6a-1cf8-11ef-971a-0242ac130005", "description": "date"}, { "nodeid": "d1a59230-1cf9-11ef-a1fe-0242ac130005", "description": "concept_list", }, {"nodeid": "d2a55a44-1cf9-11ef-a1fe-0242ac130005", "description": "bool"}, { "nodeid": "d2f5d474-1cf9-11ef-a1fe-0242ac130005", "description": "non_local_string", }, { "nodeid": "e514005a-1cf8-11ef-971a-0242ac130005", "description": "edtf_date", }, {"nodeid": "e674837a-1cf8-11ef-971a-0242ac130005", "description": "count"}, {"nodeid": "e70850dc-1cf8-11ef-971a-0242ac130005", "description": "url"}, {"nodeid": "fe3a586c-1cf9-11ef-a1fe-0242ac130005", "description": "domain"}, {"nodeid": "298ef7ac-1cfa-11ef-a1fe-0242ac130005", "description": "file"}, { "nodeid": "0e65f1d4-1cf9-11ef-971a-0242ac130005", "description": "concept", }, { "nodeid": "0e8d1560-1cfa-11ef-a1fe-0242ac130005", "description": "domain_list", }, { "nodeid": "348eb80a-1cf9-11ef-ab82-0242ac130005", "description": "other_spatialviews", }, { "nodeid": "54fc2d0c-1cf9-11ef-ab82-0242ac130005", "description": "other_models_list", }, ] return spatialview def test_create_spatialview_discreet_geometry(self): spatialview = self.generate_valid_spatiatview() spatialview.full_clean() spatialview.save() fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) self.assertTrue(fetched_spatialview.spatialviewid == spatialview.spatialviewid) spatialview.delete() def test_create_spatialview_mixed_geometry(self): spatialview = self.generate_valid_spatiatview() spatialview.ismixedgeometrytypes = True spatialview.full_clean() spatialview.save() fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) self.assertTrue( fetched_spatialview.spatialviewid == spatialview.spatialviewid and fetched_spatialview.ismixedgeometrytypes == True ) spatialview.delete() def test_create_spatialview_invalid_geometrynode(self): spatialview = self.generate_valid_spatiatview() spatialview.geometrynode = models.Node.objects.get( nodeid="7584e966-1cf8-11ef-971a-0242ac130005" ) node_type = spatialview.geometrynode.datatype with self.assertRaises(Exception): spatialview.full_clean() spatialview.save() with self.assertRaises(SpatialView.DoesNotExist): fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) def test_create_spatialview_invalid_attributenode(self): spatialview = self.generate_valid_spatiatview() # invalid nodeid spatialview.attributenodes.append( {"nodeid": "7584e966-1cf8-9999-9999-0242ac130005", "description": "invalid"} ) with self.assertRaises(Exception): spatialview.full_clean() spatialview.save() # empty attributenodes spatialview.attributenodes = None with self.assertRaises(Exception): spatialview.full_clean() spatialview.save() with self.assertRaises(SpatialView.DoesNotExist): fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) def test_create_spatialview_invalid_language(self): spatialview = self.generate_valid_spatiatview() spatialview.language = self.get_language_instance("fr") with self.assertRaises(Exception): spatialview.full_clean() spatialview.save() with self.assertRaises(SpatialView.DoesNotExist): fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) def test_create_spatialview_invalid_schema(self): spatialview = self.generate_valid_spatiatview() spatialview.schema = "invalid" with self.assertRaises(Exception): spatialview.full_clean() spatialview.save() with self.assertRaises(SpatialView.DoesNotExist): fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) def test_create_spatialview_invalid_slug(self): spatialview = self.generate_valid_spatiatview() spatialview.slug = "1_invalid" with self.assertRaises(Exception): spatialview.full_clean() spatialview.save() with self.assertRaises(SpatialView.DoesNotExist): fetched_spatialview = SpatialView.objects.get(pk=spatialview.spatialviewid) def test_spatial_view_isactive_set_to_false_removes_views(self): # first create a valid spatial view that isactive=True spatialview = self.generate_valid_spatiatview() spatialview.full_clean() spatialview.save() self.assertTrue( SpatialView.objects.filter(spatialviewid=spatialview.spatialviewid).exists() ) # now set isactive=False spatialview.isactive = False spatialview.full_clean() spatialview.save() self.assertTrue( SpatialView.objects.filter(spatialviewid=spatialview.spatialviewid).exists() ) spatialview.delete() class SpatialViewTriggerTests(TransactionTestCase): serialized_rollback = True def setUp(self): spatialviews_other_test_model_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "resource_graphs", "SpatialViews_Other_Model.json", ) spatialviews_test_model_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "resource_graphs", "SpatialViews_Test_Model.json", ) spatialviews_other_test_data_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "data", "json", "Spatialviews_Other_Model_Data.json", ) spatialviews_test_data_path = os.path.join( test_settings.TEST_ROOT, "fixtures", "data", "json", "SpatialViews_Test_Model_Data.json", ) with captured_stdout(): management.call_command("es", operation="index_concepts") management.call_command( "packages", operation="import_graphs", source=spatialviews_other_test_model_path, verbosity=0, ) management.call_command( "packages", operation="import_graphs", source=spatialviews_test_model_path, verbosity=0, ) BusinessDataImporter( spatialviews_other_test_data_path ).import_business_data() BusinessDataImporter(spatialviews_test_data_path).import_business_data() self.spatialviews_test_model_id = "5db49c51-2c70-47b3-b7be-66afced863c8" self.spatialviews_other_test_model_id = "114dd3fb-404d-4fb3-a639-1333b89cf60c" self.spatialview_geometrynode_id = "95b2c8de-1cf8-11ef-971a-0242ac130005" # create a spatialview with objects to test triggers self.spatialview_slug = "spatialviews_test" self.test_spatial_view = self.generate_valid_spatiatview() self.test_spatial_view.full_clean() self.test_spatial_view.save() self.spatialview_id = self.test_spatial_view.spatialviewid def get_language_instance(self, language): return models.Language.objects.get(code=language) def generate_valid_spatiatview(self): spatialview = SpatialView() spatialview.spatialviewid = uuid.uuid4() spatialview.schema = "public" spatialview.slug = self.spatialview_slug spatialview.description = "test description" spatialview.geometrynode = models.Node.objects.get( nodeid="95b2c8de-1cf8-11ef-971a-0242ac130005" ) # self.spatialview_geometrynode_id) spatialview.ismixedgeometrytypes = False # Discreet geometry spatialview.language = self.get_language_instance("en") spatialview.isactive = True spatialview.attributenodes = [ { "nodeid": "a379b7ac-1cf8-11ef-ab82-0242ac130005", "description": "gridref", }, {"nodeid": "bee90060-1cf8-11ef-971a-0242ac130005", "description": "name"}, {"nodeid": "ccfe0a6a-1cf8-11ef-971a-0242ac130005", "description": "date"}, { "nodeid": "d1a59230-1cf9-11ef-a1fe-0242ac130005", "description": "concept_list", }, {"nodeid": "d2a55a44-1cf9-11ef-a1fe-0242ac130005", "description": "bool"}, { "nodeid": "d2f5d474-1cf9-11ef-a1fe-0242ac130005", "description": "non_local_string", }, { "nodeid": "e514005a-1cf8-11ef-971a-0242ac130005", "description": "edtf_date", }, {"nodeid": "e674837a-1cf8-11ef-971a-0242ac130005", "description": "count"}, {"nodeid": "e70850dc-1cf8-11ef-971a-0242ac130005", "description": "url"}, {"nodeid": "fe3a586c-1cf9-11ef-a1fe-0242ac130005", "description": "domain"}, {"nodeid": "298ef7ac-1cfa-11ef-a1fe-0242ac130005", "description": "file"}, { "nodeid": "0e65f1d4-1cf9-11ef-971a-0242ac130005", "description": "concept", }, { "nodeid": "0e8d1560-1cfa-11ef-a1fe-0242ac130005", "description": "domain_list", }, { "nodeid": "348eb80a-1cf9-11ef-ab82-0242ac130005", "description": "other_spatialviews", }, { "nodeid": "54fc2d0c-1cf9-11ef-ab82-0242ac130005", "description": "other_models_list", }, ] return spatialview def test_check_spatialview_row_values(self): """ Test views for the spatial view are created and have the correct values """ # check spatial view got created self.assertTrue( SpatialView.objects.filter(spatialviewid=self.spatialview_id).exists() ) with connection.cursor() as cursor: cursor.execute( f""" SELECT gid, tileid, nodeid, geom, resourceinstanceid, gridref, name, date, concept_list, bool, non_local_string, edtf_date, count, url, domain, file, concept, domain_list, other_spatialviews, other_models_list FROM public.{self.test_spatial_view.slug}_polygon""" ) rows = cursor.fetchall() self.assertTrue(len(rows) == 1) row = rows[0] self.assertTrue(row[5] == "ABC123") # gridref self.assertTrue(row[6] == "Bat Willow") # name self.assertTrue(row[7] == "2024-05-10") # date self.assertTrue(row[8] == "is related to") # concept_list self.assertTrue(row[9] == "true") # bool (disabled as boolean node) self.assertTrue(row[10] == "non-local") # non_local_string self.assertTrue(row[11] == "2010") # edtf_date self.assertTrue(row[12] == "11111") # count self.assertTrue(row[13] == "https://www.cnbc.com") # url self.assertTrue(row[14] == "1") # domain self.assertTrue(row[15] == "Arches Project, elastic.png") # file self.assertTrue(row[16] == "is related to") # concept self.assertTrue(row[17] == "george, john, ringo, Paul") # domain_list self.assertTrue(row[18] == "Bat Willow") # other_spatialviews self.assertTrue(row[19] == "Other Model 2") # other_models_list