from django.contrib.auth import get_user_model from django.contrib.auth.models import AnonymousUser from django.contrib.contenttypes.models import ContentType from django.test import TestCase from django.urls import reverse from common.models import Role, UserConfig from interventions.models import Intervention from projects.models import Project from .models import DocumentAttachment, DocumentFolder, DocumentFolderShare, DocumentShare, ManagedDocument from .views import ensure_document_deletable from .permissions import ( filter_documents_for_user, filter_folders_for_user, get_user_visible_folder_ids, user_has_document_permission, ) User = get_user_model() class DocumentPermissionTests(TestCase): def setUp(self): self.owner = User.objects.create_user(username="owner", password="owner") self.shared_user = User.objects.create_user(username="shared", password="shared") self.folder_user = User.objects.create_user(username="folder", password="folder") self.other_user = User.objects.create_user(username="other", password="other") self.superuser = User.objects.create_superuser(username="admin", password="admin") self.document = ManagedDocument.objects.create(title="Doc", created_by=self.owner) self.folder = DocumentFolder.objects.create( name="Folder", slug="folder", created_by=self.owner ) self.parent_folder = DocumentFolder.objects.create( name="Parent", slug="parent-folder", created_by=self.owner ) self.folder.parent_folders.add(self.parent_folder) self.document.folders.add(self.folder) DocumentShare.objects.create( document=self.document, user=self.shared_user, permission=ManagedDocument.PERMISSION_COMMENT, ) DocumentFolderShare.objects.create( folder=self.folder, user=self.folder_user, permission=ManagedDocument.PERMISSION_VIEW, ) def test_owner_has_full_access(self): self.assertTrue(user_has_document_permission(self.owner, self.document)) self.assertTrue( user_has_document_permission( self.owner, self.document, required_permission=ManagedDocument.PERMISSION_APPROVE, ) ) def test_share_permission_respected(self): self.assertTrue(user_has_document_permission(self.shared_user, self.document)) self.assertFalse( user_has_document_permission( self.shared_user, self.document, required_permission=ManagedDocument.PERMISSION_EDIT, ) ) def test_folder_share_grants_access(self): self.assertTrue(user_has_document_permission(self.folder_user, self.document)) def test_superuser_has_access(self): self.assertTrue(user_has_document_permission(self.superuser, self.document)) def test_anonymous_user_has_no_access(self): self.assertFalse(user_has_document_permission(AnonymousUser(), self.document)) def test_filter_documents_for_user(self): queryset = ManagedDocument.objects.order_by("pk") shared_ids = set(filter_documents_for_user(queryset, self.shared_user).values_list("pk", flat=True)) folder_ids = set(filter_documents_for_user(queryset, self.folder_user).values_list("pk", flat=True)) other_ids = set(filter_documents_for_user(queryset, self.other_user).values_list("pk", flat=True)) self.assertEqual(shared_ids, {self.document.pk}) self.assertEqual(folder_ids, {self.document.pk}) self.assertEqual(other_ids, set()) def test_filter_documents_for_superuser_returns_all(self): queryset = ManagedDocument.objects.order_by("pk") filtered = filter_documents_for_user(queryset, self.superuser) self.assertEqual(set(filtered.values_list("pk", flat=True)), set(queryset.values_list("pk", flat=True))) def test_filter_folders_for_user(self): queryset = DocumentFolder.objects.order_by("pk") owner_ids = set(filter_folders_for_user(queryset, self.owner).values_list("pk", flat=True)) shared_ids = set(filter_folders_for_user(queryset, self.folder_user).values_list("pk", flat=True)) other_ids = set(filter_folders_for_user(queryset, self.other_user).values_list("pk", flat=True)) self.assertIn(self.folder.pk, owner_ids) self.assertIn(self.folder.pk, shared_ids) self.assertEqual(other_ids, set()) def test_visible_folder_ids_include_ancestors(self): visible = get_user_visible_folder_ids(self.folder_user) self.assertIn(self.folder.pk, visible) self.assertIn(self.parent_folder.pk, visible) class DocumentListViewTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="viewer", password="viewer") UserConfig.objects.create(user=self.user, is_intern=True) self.client.force_login(self.user) self.parent = DocumentFolder.objects.create( name="Parent", slug="parent", created_by=self.user ) self.child = DocumentFolder.objects.create( name="Child", slug="child", created_by=self.user ) self.grandchild = DocumentFolder.objects.create( name="Grandchild", slug="grandchild", created_by=self.user ) self.child.parent_folders.add(self.parent) self.grandchild.parent_folders.add(self.child) self.parent_doc = ManagedDocument.objects.create( title="Parent document", created_by=self.user, ) self.parent_doc.folders.add(self.parent) self.child_doc = ManagedDocument.objects.create( title="Child note", created_by=self.user, ) self.child_doc.folders.add(self.child) self.grandchild_doc = ManagedDocument.objects.create( title="Grand strategy", created_by=self.user, ) self.grandchild_doc.folders.add(self.grandchild) self.outside_folder = DocumentFolder.objects.create(name="External", slug="external") self.outside_doc = ManagedDocument.objects.create( title="Grand outside", created_by=self.user, ) self.outside_doc.folders.add(self.outside_folder) def test_folder_filter_only_includes_direct_documents(self): response = self.client.get(reverse("documents:list"), {"folder": self.parent.slug}) self.assertEqual(response.status_code, 200) documents = list(response.context["documents"]) document_ids = {document.pk for document in documents} self.assertSetEqual( document_ids, {self.parent_doc.pk}, ) self.assertNotIn(self.outside_doc.pk, document_ids) def test_search_returns_descendant_folders(self): response = self.client.get( reverse("documents:list"), {"folder": self.parent.slug, "search": "Grand"}, ) self.assertEqual(response.status_code, 200) visible_folders = response.context["visible_folders"] self.assertIn(self.grandchild, visible_folders) self.assertNotIn(self.outside_folder, visible_folders) self.assertNotIn(self.child, visible_folders) listing_items = response.context["listing_items"] self.assertTrue( any( item["type"] == "folder" and item["object"].pk == self.grandchild.pk for item in listing_items ) ) def test_search_limits_documents_to_folder_descendants(self): response = self.client.get( reverse("documents:list"), {"folder": self.parent.slug, "search": "Grand"}, ) self.assertEqual(response.status_code, 200) documents = list(response.context["documents"]) document_ids = {document.pk for document in documents} self.assertSetEqual(document_ids, {self.grandchild_doc.pk}) self.assertNotIn(self.outside_doc.pk, document_ids) class DocumentFolderManagementTests(TestCase): def setUp(self): self.owner = User.objects.create_user(username="folder-owner", password="owner") UserConfig.objects.create(user=self.owner, is_intern=True) self.other = User.objects.create_user(username="folder-other", password="other") UserConfig.objects.create(user=self.other, is_intern=True) self.admin = User.objects.create_user(username="folder-admin", password="admin") admin_role, _ = Role.objects.get_or_create(name="admin") admin_config = UserConfig.objects.create(user=self.admin, is_intern=True) admin_config.roles.add(admin_role) self.folder = DocumentFolder.objects.create( name="Root", slug="root", created_by=self.owner, ) def test_owner_can_update_folder(self): self.client.force_login(self.owner) response = self.client.post( reverse("documents:folder_edit", args=[self.folder.pk]), { "name": "Updated", "description": "", "application_label": "", "parent_folders": [], }, ) self.assertRedirects(response, f"{reverse('documents:list')}?folder={self.folder.slug}") self.folder.refresh_from_db() self.assertEqual(self.folder.name, "Updated") self.assertEqual(self.folder.created_by, self.owner) def test_non_owner_cannot_update_folder(self): self.client.force_login(self.other) response = self.client.post( reverse("documents:folder_edit", args=[self.folder.pk]), { "name": "Blocked", "description": "", "application_label": "", "parent_folders": [], }, ) self.assertEqual(response.status_code, 403) def test_predefined_folder_cannot_be_modified(self): self.folder.is_predefined = True self.folder.save() self.client.force_login(self.owner) def test_admin_can_change_owner(self): new_owner = User.objects.create_user(username="new-owner", password="new") self.client.force_login(self.admin) response = self.client.post( reverse("documents:folder_edit", args=[self.folder.pk]), { "name": "Admin updated", "description": "", "application_label": "", "parent_folders": [], "created_by": new_owner.pk, }, ) self.assertRedirects(response, f"{reverse('documents:list')}?folder={self.folder.slug}") self.folder.refresh_from_db() self.assertEqual(self.folder.created_by, new_owner) def test_owner_can_access_share_page(self): self.client.force_login(self.owner) response = self.client.get( reverse("documents:folder_share", args=[self.folder.pk]) ) self.assertEqual(response.status_code, 200) def test_owner_can_create_share(self): target = User.objects.create_user(username="share-target", password="pass") self.client.force_login(self.owner) response = self.client.post( reverse("documents:folder_share_add", args=[self.folder.pk]), {"user": target.pk, "permission": ManagedDocument.PERMISSION_VIEW}, ) self.assertRedirects( response, reverse("documents:folder_share", args=[self.folder.pk]) ) self.assertTrue( DocumentFolderShare.objects.filter(folder=self.folder, user=target).exists() ) def test_owner_can_create_access_link(self): self.client.force_login(self.owner) response = self.client.post( reverse("documents:folder_access_link", args=[self.folder.pk]), {"permission": ManagedDocument.PERMISSION_VIEW}, ) self.assertRedirects( response, reverse("documents:folder_share", args=[self.folder.pk]) ) self.assertEqual(self.folder.access_links.count(), 1) def test_owner_can_delete_folder(self): self.client.force_login(self.owner) response = self.client.post( reverse("documents:folder_delete", args=[self.folder.pk]), {}, ) self.assertRedirects(response, reverse("documents:list")) self.assertFalse(DocumentFolder.objects.filter(pk=self.folder.pk).exists()) def test_non_owner_cannot_delete_folder(self): self.client.force_login(self.other) response = self.client.post( reverse("documents:folder_delete", args=[self.folder.pk]), {}, ) self.assertEqual(response.status_code, 403) def test_admin_can_delete_folder(self): self.client.force_login(self.admin) response = self.client.post( reverse("documents:folder_delete", args=[self.folder.pk]), {}, ) self.assertRedirects(response, reverse("documents:list")) self.assertFalse(DocumentFolder.objects.filter(pk=self.folder.pk).exists()) def test_predefined_folder_cannot_be_deleted(self): self.folder.is_predefined = True self.folder.save() self.client.force_login(self.owner) response = self.client.post( reverse("documents:folder_delete", args=[self.folder.pk]), {}, ) self.assertEqual(response.status_code, 403) def test_cannot_set_folder_as_child_of_descendant(self): child = DocumentFolder.objects.create(name="Child", slug="child", created_by=self.owner) child.parent_folders.add(self.folder) self.client.force_login(self.owner) response = self.client.post( reverse("documents:folder_edit", args=[self.folder.pk]), { "name": self.folder.name, "description": "", "application_label": "", "parent_folders": [child.pk], }, ) self.assertEqual(response.status_code, 200) self.assertIn("parent_folders", response.context["form"].errors) def test_folder_creation_assigns_owner(self): self.client.force_login(self.other) response = self.client.post( reverse("documents:folder_create"), { "name": "New Folder", "description": "", "application_label": "", "parent_folders": [], }, ) created_folder = DocumentFolder.objects.get(name="New Folder") expected_redirect = f"{reverse('documents:list')}?folder={created_folder.slug}" self.assertRedirects(response, expected_redirect) self.assertEqual(created_folder.created_by, self.other) class DocumentDeletionPermissionTests(TestCase): def setUp(self): self.owner = User.objects.create_user(username="doc-owner", password="owner") UserConfig.objects.create(user=self.owner, is_intern=True) self.manager = User.objects.create_user(username="doc-manager", password="manager") manager_role, _ = Role.objects.get_or_create(name="manager") self.manager_config = UserConfig.objects.create(user=self.manager, is_intern=True) self.manager_config.roles.add(manager_role) self.project = Project.objects.create(name="Project linked doc", created_by=self.owner) self.intervention = Intervention.objects.create(title="Intervention linked doc") self.folder = DocumentFolder.objects.create( name="Root", slug="root", created_by=self.owner, ) def test_internal_manager_can_delete_thematic_asset_document_owned_by_others(self): from common.models import Thematic, UserThematics from assets.models import TrafficLightIntersection from documents.models import DocumentFolderAttachment from django.core.exceptions import PermissionDenied thematic, _ = Thematic.objects.get_or_create( code="trafficlights", defaults={"name_fr": "Signalisation Lumineuse Tricolore", "name_nl": "Verkeerslichten"} ) UserThematics.objects.create(user_config=self.manager_config, thematic=thematic, can_edit_assets=True) intersection = TrafficLightIntersection.objects.create(code="TL-TEST-1", name_fr="Carrefour Test 1") root_folder = DocumentFolder.objects.create(name="Root Intersection Folder", created_by=self.owner) sub_folder = DocumentFolder.objects.create(name="Subfolder Schemas", created_by=self.owner) sub_folder.parent_folders.add(root_folder) DocumentFolderAttachment.objects.create( folder=root_folder, content_type=ContentType.objects.get_for_model(TrafficLightIntersection), object_id=intersection.pk, ) other_doc = ManagedDocument.objects.create(title="Other User Doc in Subfolder", created_by=self.owner) other_doc.folders.add(sub_folder) # The manager with edit rights on trafficlights should be allowed to delete the document in the subfolder ensure_document_deletable(other_doc, self.manager) def test_internal_manager_without_edit_rights_cannot_delete_thematic_asset_document_owned_by_others(self): from common.models import Thematic, UserThematics from assets.models import TrafficLightIntersection from documents.models import DocumentFolderAttachment from django.core.exceptions import PermissionDenied thematic, _ = Thematic.objects.get_or_create( code="trafficlights", defaults={"name_fr": "Signalisation Lumineuse Tricolore", "name_nl": "Verkeerslichten"} ) # Manager has can_edit_assets=False UserThematics.objects.create(user_config=self.manager_config, thematic=thematic, can_edit_assets=False) intersection = TrafficLightIntersection.objects.create(code="TL-TEST-2", name_fr="Carrefour Test 2") root_folder = DocumentFolder.objects.create(name="Root Intersection Folder 2", created_by=self.owner) DocumentFolderAttachment.objects.create( folder=root_folder, content_type=ContentType.objects.get_for_model(TrafficLightIntersection), object_id=intersection.pk, ) other_doc = ManagedDocument.objects.create(title="Other User Doc 2", created_by=self.owner) other_doc.folders.add(root_folder) # Deletion should raise PermissionDenied because manager lacks edit rights on the thematic with self.assertRaises(PermissionDenied): ensure_document_deletable(other_doc, self.manager) def test_document_list_view_renders_delete_button_when_user_has_permission(self): from common.models import Thematic, UserThematics from assets.models import TrafficLightIntersection from documents.models import DocumentFolderAttachment thematic, _ = Thematic.objects.get_or_create( code="trafficlights", defaults={"name_fr": "Signalisation Lumineuse Tricolore", "name_nl": "Verkeerslichten"} ) UserThematics.objects.create(user_config=self.manager_config, thematic=thematic, can_edit_assets=True) intersection = TrafficLightIntersection.objects.create(code="TL-LIST-1", name_fr="Carrefour List 1") root_folder = DocumentFolder.objects.create(name="Root Intersection Folder List", created_by=self.owner) DocumentFolderAttachment.objects.create( folder=root_folder, content_type=ContentType.objects.get_for_model(TrafficLightIntersection), object_id=intersection.pk, ) other_doc = ManagedDocument.objects.create(title="Other User Doc List Test", created_by=self.owner) other_doc.folders.add(root_folder) self.client.force_login(self.manager) response = self.client.get(reverse("documents:list")) self.assertEqual(response.status_code, 200) delete_url = reverse("documents:delete", args=[other_doc.pk]) self.assertContains(response, delete_url) def test_document_list_view_hides_delete_button_when_user_lacks_permission(self): from common.models import Thematic, UserThematics from assets.models import TrafficLightIntersection from documents.models import DocumentFolderAttachment thematic, _ = Thematic.objects.get_or_create( code="trafficlights", defaults={"name_fr": "Signalisation Lumineuse Tricolore", "name_nl": "Verkeerslichten"} ) UserThematics.objects.create(user_config=self.manager_config, thematic=thematic, can_edit_assets=False) intersection = TrafficLightIntersection.objects.create(code="TL-LIST-2", name_fr="Carrefour List 2") root_folder = DocumentFolder.objects.create(name="Root Intersection Folder List 2", created_by=self.owner) DocumentFolderAttachment.objects.create( folder=root_folder, content_type=ContentType.objects.get_for_model(TrafficLightIntersection), object_id=intersection.pk, ) other_doc = ManagedDocument.objects.create(title="Other User Doc List Test 2", created_by=self.owner) other_doc.folders.add(root_folder) self.client.force_login(self.manager) response = self.client.get(reverse("documents:list")) self.assertEqual(response.status_code, 200) delete_url = reverse("documents:delete", args=[other_doc.pk]) self.assertNotContains(response, delete_url) class SearchObjectsViewTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="testuser", password="testpassword") UserConfig.objects.create(user=self.user, is_intern=True) self.document = ManagedDocument.objects.create(title="Test Document", created_by=self.user) self.project = Project.objects.create(name="Awesome project name", created_by=self.user) self.content_type = ContentType.objects.get_for_model(Project) def test_search_objects_anonymous(self): url = reverse("documents:search_objects", args=[self.document.pk]) response = self.client.get(url, {"content_type": self.content_type.pk, "q": "Awesome"}) self.assertEqual(response.status_code, 302) def test_search_objects_authenticated(self): self.client.force_login(self.user) url = reverse("documents:search_objects", args=[self.document.pk]) response = self.client.get(url, {"content_type": self.content_type.pk, "q": "Awesome"}) self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(len(data["results"]), 1) self.assertEqual(data["results"][0]["id"], self.project.pk) self.assertIn("Awesome project name", data["results"][0]["text"]) class DocumentGeoreferenceTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="geo_user", password="password") UserConfig.objects.create(user=self.user, is_intern=True) self.document = ManagedDocument.objects.create(title="Geo Doc", created_by=self.user) def test_georeference_view_denied_for_anonymous(self): url = reverse("documents:georeference", args=[self.document.pk]) response = self.client.get(url) self.assertEqual(response.status_code, 302) # Redirect to login def test_georeference_view_allowed_for_owner(self): self.client.force_login(self.user) url = reverse("documents:georeference", args=[self.document.pk]) response = self.client.get(url, {"mode": "overlay"}) self.assertEqual(response.status_code, 200) self.assertContains(response, "Superposition") def test_georeference_save_success(self): self.client.force_login(self.user) url = reverse("documents:georeference_save", args=[self.document.pk]) coords = [[4.1, 50.1], [4.2, 50.1], [4.2, 50.2], [4.1, 50.2]] response = self.client.post( url, {"coordinates": coords, "page": 1}, content_type="application/json" ) self.assertEqual(response.status_code, 200) self.assertEqual(response.json()["status"], "success") # Verify model updated self.document.refresh_from_db() self.assertEqual(self.document.georeference_coords, coords) self.assertEqual(self.document.georeference_page, 1) def test_georeference_save_invalid_format(self): self.client.force_login(self.user) url = reverse("documents:georeference_save", args=[self.document.pk]) # 3 points instead of 4 coords = [[4.1, 50.1], [4.2, 50.1], [4.2, 50.2]] response = self.client.post( url, {"coordinates": coords}, content_type="application/json" ) self.assertEqual(response.status_code, 400) self.assertEqual(response.json()["status"], "error") def test_map_view_not_georeferenced(self): self.client.force_login(self.user) url = reverse("documents:map_view", args=[self.document.pk]) response = self.client.get(url) self.assertEqual(response.status_code, 404) def test_map_view_georeferenced(self): self.client.force_login(self.user) self.document.georeference_coords = [[4.1, 50.1], [4.2, 50.1], [4.2, 50.2], [4.1, 50.2]] self.document.save() url = reverse("documents:map_view", args=[self.document.pk]) response = self.client.get(url) self.assertEqual(response.status_code, 200) from unittest.mock import patch from django.core.files.uploadedfile import SimpleUploadedFile from documents.models import DocumentVersion import os class DocumentCadPreviewTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="cad_user", password="password") UserConfig.objects.create(user=self.user, is_intern=True) self.document = ManagedDocument.objects.create(title="Cad Doc", created_by=self.user) # Create a version with a mock DXF file self.version = DocumentVersion.objects.create( document=self.document, file=SimpleUploadedFile("plan.dxf", b"DUMMY DXF CONTENT"), uploaded_by=self.user, version_number=1 ) @patch("documents.utils.render_cad_file_to_image") def test_dxf_preview_rendering_and_serving(self, mock_render): # We simulate the render_cad_file_to_image writing a mock file def fake_render(input_path, output_path): with open(output_path, "wb") as f: f.write(b"MOCK PNG CONTENT") mock_render.side_effect = fake_render self.client.force_login(self.user) url = reverse("documents:page_image", args=[self.document.pk, 1]) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(response["Content-Type"], "image/png") self.assertEqual(b"".join(response.streaming_content), b"MOCK PNG CONTENT") # Verify preview file was created on disk preview_path = self.version.file.path + ".preview.png" self.assertTrue(os.path.exists(preview_path)) # Clean up preview file after test if os.path.exists(preview_path): os.remove(preview_path) @patch("documents.utils.render_cad_file_to_image") def test_dwg_preview_rendering_and_serving(self, mock_render): # Create a document and version with .dwg file doc_dwg = ManagedDocument.objects.create(title="Dwg Doc", created_by=self.user) version_dwg = DocumentVersion.objects.create( document=doc_dwg, file=SimpleUploadedFile("plan.dwg", b"DUMMY DWG CONTENT"), uploaded_by=self.user, version_number=1 ) def fake_render(input_path, output_path): with open(output_path, "wb") as f: f.write(b"MOCK DWG PNG CONTENT") mock_render.side_effect = fake_render self.client.force_login(self.user) url = reverse("documents:page_image", args=[doc_dwg.pk, 1]) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(response["Content-Type"], "image/png") self.assertEqual(b"".join(response.streaming_content), b"MOCK DWG PNG CONTENT") # Clean up preview file after test preview_path = version_dwg.file.path + ".preview.png" if os.path.exists(preview_path): os.remove(preview_path) from assets.models import NatureLocation from documents.models import DocumentFolderAttachment class DocumentGeoreferenceAutoZoomTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="geo_user", password="password") UserConfig.objects.create(user=self.user, is_intern=True) self.document = ManagedDocument.objects.create( title="Auto Zoom Doc", created_by=self.user ) self.location = NatureLocation.objects.create( code="LOC1", name_fr="Location 1", lon=4.3517, lat=50.8503 ) def test_direct_attachment_coords(self): # Create direct attachment to the geolocated asset DocumentAttachment.objects.create( document=self.document, content_type=ContentType.objects.get_for_model(self.location), object_id=self.location.pk ) # Test helper function from .views import _get_associated_asset_coords coords = _get_associated_asset_coords(self.document) self.assertEqual(coords, [4.3517, 50.8503]) # Test that view injects associated_coords into template context self.client.force_login(self.user) url = reverse("documents:georeference", args=[self.document.pk]) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(response.context["associated_coords"], [4.3517, 50.8503]) def test_folder_attachment_coords(self): # Create folder and associate with document folder = DocumentFolder.objects.create(name="Geo Folder", slug="geo-folder") self.document.folders.add(folder) # Create folder attachment to the geolocated asset DocumentFolderAttachment.objects.create( folder=folder, content_type=ContentType.objects.get_for_model(self.location), object_id=self.location.pk ) from .views import _get_associated_asset_coords coords = _get_associated_asset_coords(self.document) self.assertEqual(coords, [4.3517, 50.8503]) def test_parent_folder_attachment_coords(self): # Create parent folder, child folder, and associate with document parent_folder = DocumentFolder.objects.create(name="Parent Geo Folder", slug="parent-geo-folder") child_folder = DocumentFolder.objects.create(name="Child Folder", slug="child-folder") child_folder.parent_folders.add(parent_folder) self.document.folders.add(child_folder) # Create folder attachment to the parent folder DocumentFolderAttachment.objects.create( folder=parent_folder, content_type=ContentType.objects.get_for_model(self.location), object_id=self.location.pk ) from .views import _get_associated_asset_coords coords = _get_associated_asset_coords(self.document) self.assertEqual(coords, [4.3517, 50.8503])